Version 1.15.0-dev.3.0

Merge commit '1c698c183be2d74bfb1576cffb4476e6d77317e6' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6a62b7f..55db4b3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,14 @@
     `SecurityContext.setTrustedCertificates` is no longer supported.
     The method now only supports one argument for the PEM file name containing
     the trusted certificates.
+  * Added support to SecurityContext for PKCS12 certificate and key containers.
+* `dart:async`
+  * Made `StreamView` class a `const` class.
+
+## 1.14.2 - 2016-02-09
+
+* Fixes a bug where pub would download packages from pub.dartlang.org even when
+  a different hosted URL was specified.
 
 ## 1.14.1 - 2016-02-04
 
diff --git a/DEPS b/DEPS
index d605a86..702e439 100644
--- a/DEPS
+++ b/DEPS
@@ -52,7 +52,7 @@
   "intl_rev": "@a8b480b9c436f6c0ec16730804c914bdb4e30d53",
   "jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_tag": "@1.1.1",
-  "linter_rev": "@5a599fd32d3b6ef00ffa7c330d1f32bbad287228",
+  "linter_rev": "@87f066f9243b36540c33186e742a798b87e76f8e",
   "logging_rev": "@85d83e002670545e9039ad3985f0018ab640e597",
   "markdown_rev": "@4aaadf3d940bb172e1f6285af4d2b1710d309982",
   "matcher_tag": "@0.12.0",
@@ -91,7 +91,7 @@
   "when_tag": "@0.2.0+2",
   "which_tag": "@0.1.3+1",
   "web_components_rev": "@0e636b534d9b12c9e96f841e6679398e91a986ec",
-  "WebCore_rev": "@4f90b41b0165f23f412cecdba07b7d81d3fbb5b5",
+  "WebCore_rev": "@5ecb723fd9ffcc0d108f5e0e24d12b8b3df7b200",
   "yaml_tag": "@2.1.5",
   "zlib_rev": "@c3d0a6190f2f8c924a05ab6cc97b8f975bddd33f",
   "barback-0.13.0_rev": "@34853",
@@ -293,20 +293,6 @@
     "action": ["python", Var("dart_root") + "/tools/gyp_dart.py"],
   },
   {
-    'name': 'checked_in_dart_binaries',
-    'pattern': '.',
-    'action': [
-      'download_from_google_storage',
-      '--no_auth',
-      '--no_resume',
-      '--bucket',
-      'dart-dependencies',
-      '--recursive',
-      '--directory',
-      Var('dart_root') + '/tools/testing/bin',
-    ],
-  },
-  {
     'name': 'd8_testing_binaries',
     'pattern': '.',
     'action': [
diff --git a/WATCHLISTS b/WATCHLISTS
index 9b4f4dc..a6f72e3 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -10,9 +10,6 @@
     'runtime': {
       'filepath': '^runtime/',
     },
-    'tools': {
-      'filepath': 'tools/',
-    },
     'observatory': {
       'filepath': 'runtime/bin/vmservice/' \
                   '|runtime/bin/vmservice*' \
@@ -24,7 +21,6 @@
 
   'WATCHLISTS': {
     'runtime': ['vm-dev@dartlang.org'],
-    'tools': ['ricow@google.com'],
     'observatory': ['johnmccutchan@google.com', 'turnidge@google.com', 'rmacnak@google.com'],
   },
 }
diff --git a/dart.gyp b/dart.gyp
index a7d4f95..918e5d6 100644
--- a/dart.gyp
+++ b/dart.gyp
@@ -27,6 +27,7 @@
         'runtime/dart-runtime.gyp:dart',
         'runtime/dart-runtime.gyp:dart_noopt',
         'runtime/dart-runtime.gyp:dart_precompiled_runtime',
+        'runtime/dart-runtime.gyp:dart_product',
         'runtime/dart-runtime.gyp:dart_no_snapshot',
         'runtime/dart-runtime.gyp:run_vm_tests',
         'runtime/dart-runtime.gyp:process_test',
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 430a2e6..df9075e 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -9,7 +9,8 @@
 import 'dart:core' hide Resource;
 import 'dart:math' show max;
 
-import 'package:analysis_server/plugin/protocol/protocol.dart' hide Element;
+import 'package:analysis_server/plugin/protocol/protocol.dart'
+    hide AnalysisOptions, Element;
 import 'package:analysis_server/src/analysis_logger.dart';
 import 'package:analysis_server/src/channel/channel.dart';
 import 'package:analysis_server/src/context_manager.dart';
@@ -140,9 +141,14 @@
   List<RequestHandler> handlers;
 
   /**
-   * The current default [DartSdk].
+   * The function used to create a new SDK using the default SDK.
    */
-  final DartSdk defaultSdk;
+  final SdkCreator defaultSdkCreator;
+
+  /**
+   * The object used to manage the SDK's known to this server.
+   */
+  DartSdkManager sdkManager;
 
   /**
    * The instrumentation service that is to be used by this analysis server.
@@ -300,7 +306,7 @@
       Index _index,
       this.serverPlugin,
       this.options,
-      this.defaultSdk,
+      this.defaultSdkCreator,
       this.instrumentationService,
       {ResolverProvider packageResolverProvider: null,
       EmbeddedResolverProvider embeddedResolverProvider: null,
@@ -342,6 +348,7 @@
     channel.sendNotification(notification);
     channel.listen(handleRequest, onDone: done, onError: error);
     handlers = serverPlugin.createDomains(this);
+    sdkManager = new DartSdkManager(defaultSdkCreator);
   }
 
   /**
@@ -427,6 +434,19 @@
   }
 
   /**
+   * Return one of the SDKs that has been created, or `null` if no SDKs have
+   * been created yet.
+   */
+  DartSdk findSdk() {
+    DartSdk sdk = sdkManager.anySdk;
+    if (sdk != null) {
+      return sdk;
+    }
+    // TODO(brianwilkerson) Should we create an SDK using the default options?
+    return null;
+  }
+
+  /**
    * Return the preferred [AnalysisContext] for analyzing the given [path].
    * This will be the context that explicitly contains the path, if any such
    * context exists, otherwise it will be the first analysis context that
@@ -510,11 +530,13 @@
   ContextSourcePair getContextSourcePair(String path) {
     // try SDK
     {
-      Uri uri = resourceProvider.pathContext.toUri(path);
-      Source sdkSource = defaultSdk.fromFileUri(uri);
-      if (sdkSource != null) {
-        AnalysisContext sdkContext = defaultSdk.context;
-        return new ContextSourcePair(sdkContext, sdkSource);
+      DartSdk sdk = findSdk();
+      if (sdk != null) {
+        Uri uri = resourceProvider.pathContext.toUri(path);
+        Source sdkSource = sdk.fromFileUri(uri);
+        if (sdkSource != null) {
+          return new ContextSourcePair(sdk.context, sdkSource);
+        }
       }
     }
     // try to find the deep-most containing context
@@ -1459,15 +1481,20 @@
   }
 
   @override
-  AnalysisContext addContext(Folder folder, FolderDisposition disposition) {
+  AnalysisOptions get defaultAnalysisOptions =>
+      analysisServer.defaultContextOptions;
+
+  @override
+  AnalysisContext addContext(
+      Folder folder, AnalysisOptions options, FolderDisposition disposition) {
     InternalAnalysisContext context =
         AnalysisEngine.instance.createAnalysisContext();
     context.contentCache = analysisServer.overlayState;
     analysisServer.folderMap[folder] = context;
     _locateEmbedderYamls(context, disposition);
-    context.sourceFactory = _createSourceFactory(context, disposition, folder);
-    context.analysisOptions =
-        new AnalysisOptionsImpl.from(analysisServer.defaultContextOptions);
+    context.sourceFactory =
+        _createSourceFactory(context, options, disposition, folder);
+    context.analysisOptions = options;
     analysisServer._onContextsChangedController
         .add(new ContextsChangedEvent(added: [context]));
     analysisServer.schedulePerformAnalysisOperation(context);
@@ -1536,8 +1563,8 @@
   void updateContextPackageUriResolver(
       Folder contextFolder, FolderDisposition disposition) {
     AnalysisContext context = analysisServer.folderMap[contextFolder];
-    context.sourceFactory =
-        _createSourceFactory(context, disposition, contextFolder);
+    context.sourceFactory = _createSourceFactory(
+        context, context.analysisOptions, disposition, contextFolder);
     analysisServer._onContextsChangedController
         .add(new ContextsChangedEvent(changed: [context]));
     analysisServer.schedulePerformAnalysisOperation(context);
@@ -1556,7 +1583,7 @@
    * given [disposition].
    */
   SourceFactory _createSourceFactory(InternalAnalysisContext context,
-      FolderDisposition disposition, Folder folder) {
+      AnalysisOptions options, FolderDisposition disposition, Folder folder) {
     List<UriResolver> resolvers = [];
     List<UriResolver> packageUriResolvers =
         disposition.createPackageUriResolvers(resourceProvider);
@@ -1579,7 +1606,8 @@
     if (embedderUriResolver.length == 0) {
       // The embedder uri resolver has no mappings. Use the default Dart SDK
       // uri resolver.
-      resolvers.add(new DartUriResolver(analysisServer.defaultSdk));
+      resolvers.add(new DartUriResolver(
+          analysisServer.sdkManager.getSdkForOptions(options)));
     } else {
       // The embedder uri resolver has mappings, use it instead of the default
       // Dart SDK uri resolver.
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights.dart b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
index a91e47d..ed5e8e9 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
@@ -5,10 +5,10 @@
 library computer.highlights;
 
 import 'package:analysis_server/plugin/protocol/protocol.dart' hide Element;
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 
 /**
  * A computer for [HighlightRegion]s in a Dart [CompilationUnit].
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights2.dart b/pkg/analysis_server/lib/src/computer/computer_highlights2.dart
index fc0d77e..5665d49 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights2.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights2.dart
@@ -5,10 +5,10 @@
 library computer.highlights2;
 
 import 'package:analysis_server/plugin/protocol/protocol.dart' hide Element;
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 
 /**
  * A computer for [HighlightRegion]s in a Dart [CompilationUnit].
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 92efe4d..992cf55 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -307,10 +307,18 @@
  */
 abstract class ContextManagerCallbacks {
   /**
-   * Create and return a new analysis context, allowing [disposition] to govern
-   * details of how the context is to be created.
+   * Return the default analysis options to be used when creating an analysis
+   * context.
    */
-  AnalysisContext addContext(Folder folder, FolderDisposition disposition);
+  AnalysisOptions get defaultAnalysisOptions;
+
+  /**
+   * Create and return a new analysis context rooted at the given [folder], with
+   * the given analysis [options], allowing [disposition] to govern details of
+   * how the context is to be created.
+   */
+  AnalysisContext addContext(
+      Folder folder, AnalysisOptions options, FolderDisposition disposition);
 
   /**
    * Called when the set of files associated with a context have changed (or
@@ -550,15 +558,8 @@
   /**
    * Process [options] for the given context [info].
    */
-  void processOptionsForContext(ContextInfo info, Folder folder,
+  void processOptionsForContext(ContextInfo info, Map<String, Object> options,
       {bool optionsRemoved: false}) {
-    Map<String, Object> options;
-    try {
-      options = analysisOptionsProvider.getOptions(folder);
-    } catch (_) {
-      // Parse errors are reported by GenerateOptionsErrorsTask.
-    }
-
     if (options == null && !optionsRemoved) {
       return;
     }
@@ -613,6 +614,20 @@
     }
   }
 
+  /**
+   * Return the options from the analysis options file in the given [folder], or
+   * `null` if there is no file in the folder or if the contents of the file are
+   * not valid YAML.
+   */
+  Map<String, Object> readOptions(Folder folder) {
+    try {
+      return analysisOptionsProvider.getOptions(folder);
+    } catch (_) {
+      // Parse errors are reported by GenerateOptionsErrorsTask.
+    }
+    return null;
+  }
+
   @override
   void refresh(List<Resource> roots) {
     // Destroy old contexts
@@ -835,7 +850,11 @@
     if (AnalysisEngine.isAnalysisOptionsFileName(path, pathContext)) {
       var analysisContext = info.context;
       if (analysisContext is context.AnalysisContextImpl) {
-        processOptionsForContext(info, info.folder,
+        // TODO(brianwilkerson) This doesn't correctly update the source factory
+        // if the changes necessitate it (such as by changing the setting of the
+        // strong-mode option).
+        Map<String, Object> options = readOptions(info.folder);
+        processOptionsForContext(info, options,
             optionsRemoved: changeType == ChangeType.REMOVE);
         analysisContext.invalidateCachedResults();
         callbacks.applyChangesToContext(info.folder, new ChangeSet());
@@ -1019,11 +1038,16 @@
           _computeFolderDisposition(folder, dependencies.add, packagespecFile);
     }
 
+    Map<String, Object> optionMap = readOptions(info.folder);
+    AnalysisOptions options =
+        new AnalysisOptionsImpl.from(callbacks.defaultAnalysisOptions);
+    applyToAnalysisOptions(options, optionMap);
+
     info.setDependencies(dependencies);
-    info.context = callbacks.addContext(folder, disposition);
+    info.context = callbacks.addContext(folder, options, disposition);
     info.context.name = folder.path;
 
-    processOptionsForContext(info, folder);
+    processOptionsForContext(info, optionMap);
 
     return info;
   }
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 8810ff6..f9ea745 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -53,12 +53,17 @@
   CompletionPerformance computeCachePerformance;
 
   /**
+   * The current request being processed or `null` if none.
+   */
+  CompletionRequestImpl _currentRequest;
+
+  /**
    * Initialize a new request handler for the given [server].
    */
   CompletionDomainHandler(this.server);
 
   /**
-   * Compute completion results for the given reqeust and append them to the stream.
+   * Compute completion results for the given request 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
@@ -76,7 +81,12 @@
     for (CompletionContributor contributor in newContributors) {
       String contributorTag = 'computeSuggestions - ${contributor.runtimeType}';
       performance.logStartTime(contributorTag);
-      suggestions.addAll(await contributor.computeSuggestions(request));
+      try {
+        suggestions.addAll(await contributor.computeSuggestions(request));
+      } on AbortCompletion {
+        suggestions.clear();
+        break;
+      }
       performance.logElapseTime(contributorTag);
     }
 
@@ -139,7 +149,7 @@
 
     recordRequest(performance, context, source, params.offset);
 
-    CompletionRequest completionRequest = new CompletionRequestImpl(
+    CompletionRequestImpl completionRequest = new CompletionRequestImpl(
         context,
         server.resourceProvider,
         server.searchEngine,
@@ -148,6 +158,9 @@
         performance);
     String completionId = (_nextCompletionId++).toString();
 
+    _abortCurrentRequest();
+    _currentRequest = completionRequest;
+
     // Compute suggestions in the background
     computeSuggestions(completionRequest).then((CompletionResult result) {
       const SEND_NOTIFICATION_TAG = 'send notification';
@@ -161,6 +174,10 @@
       performance.suggestionCountFirst = result.suggestions.length;
       performance.suggestionCountLast = result.suggestions.length;
       performance.complete();
+    }).whenComplete(() {
+      if (_currentRequest == completionRequest) {
+        _currentRequest = null;
+      }
     });
 
     // initial response without results
@@ -198,6 +215,16 @@
             completionId, replacementOffset, replacementLength, results, true)
         .toNotification());
   }
+
+  /**
+   * Abort the current completion request, if any.
+   */
+  void _abortCurrentRequest() {
+    if (_currentRequest != null) {
+      _currentRequest.abort();
+      _currentRequest = null;
+    }
+  }
 }
 
 /**
diff --git a/pkg/analysis_server/lib/src/domain_diagnostic.dart b/pkg/analysis_server/lib/src/domain_diagnostic.dart
index e9bd0c3..94b1c3a 100644
--- a/pkg/analysis_server/lib/src/domain_diagnostic.dart
+++ b/pkg/analysis_server/lib/src/domain_diagnostic.dart
@@ -63,6 +63,10 @@
           AnalysisTarget target = iterator.key;
           if (countedTargets.add(target)) {
             CacheEntry cacheEntry = iterator.value;
+            if (cacheEntry == null) {
+              throw new StateError(
+                  "mutated cache key detected: $target (${target.runtimeType})");
+            }
             if (target is Source) {
               if (cacheEntry.explicitlyAdded) {
                 explicitFiles++;
diff --git a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
index 931d87f..20ddb4f 100644
--- a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
@@ -6,11 +6,11 @@
 
 import 'package:analysis_server/plugin/analysis/navigation/navigation_core.dart';
 import 'package:analysis_server/src/protocol_server.dart' as protocol;
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 
 /**
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index ce2b38c..4197555 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -20,11 +20,11 @@
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart' as engine;
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart' as engine;
 import 'package:analyzer/src/generated/error.dart' as engine;
 import 'package:analyzer/src/generated/parser.dart' as engine;
-import 'package:analyzer/src/generated/scanner.dart' as engine;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:dart_style/dart_style.dart';
 
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 9a585dd..1aa1c9f 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
@@ -26,6 +26,14 @@
 typedef CompletionContributor CompletionContributorFactory();
 
 /**
+ * [AbortCompletion] is thrown when the current completion request
+ * should be aborted because either
+ * the source changed since the request was made, or
+ * a new completion request was received.
+ */
+class AbortCompletion {}
+
+/**
  * An object used to produce completions at a specific location within a file.
  *
  * Clients may implement this class when implementing plugins.
@@ -33,7 +41,8 @@
 abstract class CompletionContributor {
   /**
    * Return a [Future] that completes with a list of suggestions
-   * for the given completion [request].
+   * for the given completion [request]. This will
+   * throw [AbortCompletion] if the completion request has been aborted.
    */
   Future<List<CompletionSuggestion>> computeSuggestions(
       CompletionRequest request);
@@ -70,4 +79,9 @@
    * Return the source in which the completion is being requested.
    */
   Source get source;
+
+  /**
+   * Throw [AbortCompletion] if the completion request has been aborted.
+   */
+  void checkAborted();
 }
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
index c6a9a74..434ae63 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
@@ -107,16 +107,6 @@
   CompletionTarget get target;
 
   /**
-   * Return a [Future] that completes with a list of directives for the library
-   * in which in which the completion is occurring.
-   * The [Future] may return `null` if the library unit cannot be determined
-   * (e.g. unlinked part file).
-   * Any information obtained from [target] prior to calling this method
-   * should be discarded as it may have changed.
-   */
-  Future<List<Directive>> resolveDirectives();
-
-  /**
    * Return a [Future] that completes when the element associated with
    * the given [expression] in the target compilation unit is available.
    * It may also complete if the expression cannot be resolved
@@ -125,4 +115,24 @@
    * should be discarded as it may have changed.
    */
   Future resolveExpression(Expression expression);
+
+  /**
+     * Return a [Future] that completes with a list of [ImportElement]s
+     * for the library in which in which the completion is occurring.
+     * The [Future] may return `null` if the library unit cannot be determined
+     * (e.g. unlinked part file).
+     * Any information obtained from [target] prior to calling this method
+     * should be discarded as it may have changed.
+     */
+  Future<List<ImportElement>> resolveImports();
+
+  /**
+   * Return a [Future] that completes with a list of [CompilationUnitElement]s
+   * comprising the library in which in which the completion is occurring.
+   * The [Future] may return `null` if the library unit cannot be determined
+   * (e.g. unlinked part file).
+   * Any information obtained from [target] prior to calling this method
+   * should be discarded as it may have changed.
+   */
+  Future<List<CompilationUnitElement>> resolveUnits();
 }
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart
index c04ce43..9a03a1e 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart
@@ -4,10 +4,10 @@
 
 library analysis_server.src.provisional.completion.dart.completion_target;
 
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
 int _computeArgIndex(AstNode containingNode, Object entity) {
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 2cdb251..4f9e472 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -375,14 +375,20 @@
 
     _initIncrementalLogger(results[INCREMENTAL_RESOLUTION_LOG]);
 
-    DartSdk defaultSdk;
+    JavaFile defaultSdkDirectory;
     if (results[SDK_OPTION] != null) {
-      defaultSdk = new DirectoryBasedDartSdk(new JavaFile(results[SDK_OPTION]));
+      defaultSdkDirectory = new JavaFile(results[SDK_OPTION]);
     } else {
-      // No path to the SDK provided; use DirectoryBasedDartSdk.defaultSdk,
-      // which will make a guess.
-      defaultSdk = DirectoryBasedDartSdk.defaultSdk;
+      // No path to the SDK was provided.
+      // Use DirectoryBasedDartSdk.defaultSdkDirectory, which will make a guess.
+      defaultSdkDirectory = DirectoryBasedDartSdk.defaultSdkDirectory;
     }
+    SdkCreator defaultSdkCreator =
+        () => new DirectoryBasedDartSdk(defaultSdkDirectory);
+    // TODO(brianwilkerson) It would be nice to avoid creating an SDK that
+    // cannot be re-used, but the SDK is needed to create a package map provider
+    // in the case where we need to run `pub` in order to get the package map.
+    DirectoryBasedDartSdk defaultSdk = defaultSdkCreator();
     //
     // Initialize the instrumentation service.
     //
@@ -420,8 +426,14 @@
     //
     // Create the sockets and start listening for requests.
     //
-    socketServer = new SocketServer(analysisServerOptions, defaultSdk, service,
-        serverPlugin, packageResolverProvider, embeddedUriResolverProvider);
+    socketServer = new SocketServer(
+        analysisServerOptions,
+        defaultSdkCreator,
+        defaultSdk,
+        service,
+        serverPlugin,
+        packageResolverProvider,
+        embeddedUriResolverProvider);
     httpServer = new HttpAnalysisServer(socketServer);
     stdioServer = new StdioAnalysisServer(socketServer);
     socketServer.userDefinedPlugins = _userDefinedPlugins;
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 e0635aa..b79a9d8 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
@@ -21,6 +21,14 @@
   @override
   final Source source;
 
+  /**
+   * The content cache modification stamp of the associated [source],
+   * or `null` if the content cache does not override the [source] content.
+   * This is used to determine if the [source] contents have been modified
+   * after the completion request was made.
+   */
+  final int sourceModificationStamp;
+
   @override
   final int offset;
 
@@ -48,16 +56,21 @@
   @override
   final SearchEngine searchEngine;
 
+  bool _aborted = false;
+
   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.performance) {
-    replacementOffset = offset;
-    replacementLength = 0;
-  }
+  CompletionRequestImpl(AnalysisContext context, this.resourceProvider,
+      this.searchEngine, Source source, int offset, this.performance)
+      : this.context = context,
+        this.source = source,
+        this.offset = offset,
+        replacementOffset = offset,
+        replacementLength = 0,
+        sourceModificationStamp = context.getModificationStamp(source);
 
   /**
    * Return the original text from the [replacementOffset] to the [offset]
@@ -69,4 +82,22 @@
         .data
         .substring(replacementOffset, offset);
   }
+
+  /**
+   * Abort the current completion request.
+   */
+  void abort() {
+    _aborted = true;
+  }
+
+  @override
+  void checkAborted() {
+    if (_aborted) {
+      throw new AbortCompletion();
+    }
+    if (sourceModificationStamp != context.getModificationStamp(source)) {
+      _aborted = true;
+      throw new AbortCompletion();
+    }
+  }
 }
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 602503e..b56bd9f 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
@@ -18,17 +18,20 @@
 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/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/context.dart'
     show AnalysisFutureHelper, AnalysisContextImpl;
+import 'package:analyzer/src/dart/ast/token.dart';
 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/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/task/dart.dart';
+import 'package:analyzer/task/model.dart';
 
 /**
  * [DartCompletionManager] determines if a completion request is Dart specific
@@ -44,17 +47,15 @@
   @override
   Future<List<CompletionSuggestion>> computeSuggestions(
       CompletionRequest request) async {
+    request.checkAborted();
     if (!AnalysisEngine.isDartFileName(request.source.shortName)) {
       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);
-    performance.logElapseTime(BUILD_REQUEST_TAG);
 
     // Don't suggest in comments.
     if (dartRequest.target.isCommentText) {
@@ -78,6 +79,7 @@
       List<CompletionSuggestion> contributorSuggestions =
           await contributor.computeSuggestions(dartRequest);
       performance.logElapseTime(contributorTag);
+      request.checkAborted();
 
       for (CompletionSuggestion newSuggestion in contributorSuggestions) {
         var oldSuggestion = suggestionMap.putIfAbsent(
@@ -95,6 +97,7 @@
     performance.logStartTime(SORT_TAG);
     await contributionSorter.sort(dartRequest, suggestions);
     performance.logElapseTime(SORT_TAG);
+    request.checkAborted();
     return suggestions;
   }
 }
@@ -137,8 +140,22 @@
    */
   InterfaceType _objectType;
 
+  /**
+   * A list of resolved [ImportElement]s for the imported libraries
+   * or `null` if not computed.
+   */
+  List<ImportElement> _resolvedImports;
+
+  /**
+   * The resolved [CompilationUnitElement]s comprising the library
+   * or `null` if not computed.
+   */
+  List<CompilationUnitElement> _resolvedUnits;
+
   OpType _opType;
 
+  final CompletionRequest _originalRequest;
+
   final CompletionPerformance performance;
 
   DartCompletionRequestImpl._(
@@ -149,6 +166,7 @@
       this.source,
       this.offset,
       CompilationUnit unit,
+      this._originalRequest,
       this.performance) {
     _updateTargets(unit);
   }
@@ -200,26 +218,17 @@
     return _opType;
   }
 
-  // For internal use only
-  @override
-  Future<List<Directive>> resolveDirectives() async {
-    CompilationUnit libUnit;
-    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;
+  /**
+   * Throw [AbortCompletion] if the completion request has been aborted.
+   */
+  void checkAborted() {
+    _originalRequest.checkAborted();
   }
 
   @override
   Future resolveExpression(Expression expression) async {
+    checkAborted();
+
     // Return immediately if the expression has already been resolved
     if (expression.propagatedType != null) {
       return;
@@ -233,13 +242,12 @@
     // 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);
+    CompilationUnit resolvedUnit = await _computeAsync(
+        this,
+        new LibrarySpecificUnit(librarySource, source),
+        RESOLVED_UNIT,
+        performance,
+        'resolve expression');
 
     // TODO(danrubel) determine if the underlying source has been modified
     // in a way that invalidates the completion request
@@ -254,6 +262,55 @@
     _updateTargets(resolvedUnit);
   }
 
+  @override
+  Future<List<ImportElement>> resolveImports() async {
+    checkAborted();
+    if (_resolvedImports != null) {
+      return _resolvedImports;
+    }
+    LibraryElement libElem = libraryElement;
+    if (libElem == null) {
+      return null;
+    }
+    _resolvedImports = <ImportElement>[];
+    for (ImportElement importElem in libElem.imports) {
+      if (importElem.importedLibrary.exportNamespace == null) {
+        await _computeAsync(this, importElem.importedLibrary.source,
+            LIBRARY_ELEMENT4, performance, 'resolve imported library');
+        checkAborted();
+      }
+      _resolvedImports.add(importElem);
+    }
+    return _resolvedImports;
+  }
+
+  @override
+  Future<List<CompilationUnitElement>> resolveUnits() async {
+    checkAborted();
+    if (_resolvedUnits != null) {
+      return _resolvedUnits;
+    }
+    LibraryElement libElem = libraryElement;
+    if (libElem == null) {
+      return null;
+    }
+    _resolvedUnits = <CompilationUnitElement>[];
+    for (CompilationUnitElement unresolvedUnit in libElem.units) {
+      CompilationUnit unit = await _computeAsync(
+          this,
+          new LibrarySpecificUnit(libElem.source, unresolvedUnit.source),
+          RESOLVED_UNIT3,
+          performance,
+          'resolve library unit');
+      checkAborted();
+      CompilationUnitElement resolvedUnit = unit?.element;
+      if (resolvedUnit != null) {
+        _resolvedUnits.add(resolvedUnit);
+      }
+    }
+    return _resolvedUnits;
+  }
+
   /**
    * Update the completion [target] and [dotTarget] based on the given [unit].
    */
@@ -285,9 +342,12 @@
 
   /**
    * Return a [Future] that completes with a newly created completion request
-   * based on the given [request].
+   * based on the given [request]. This method will throw [AbortCompletion]
+   * if the completion request has been aborted.
    */
-  static Future<DartCompletionRequest> from(CompletionRequest request) async {
+  static Future<DartCompletionRequest> from(CompletionRequest request,
+      {ResultDescriptor resultDescriptor}) async {
+    request.checkAborted();
     CompletionPerformance performance =
         (request as CompletionRequestImpl).performance;
     const BUILD_REQUEST_TAG = 'build DartCompletionRequest';
@@ -313,12 +373,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);
+      unit = await _computeAsync(
+          request,
+          new LibrarySpecificUnit(libSource, source),
+          resultDescriptor ?? RESOLVED_UNIT3,
+          performance,
+          'resolve declarations');
     }
 
     DartCompletionRequestImpl dartRequest = new DartCompletionRequestImpl._(
@@ -329,6 +389,7 @@
         request.source,
         request.offset,
         unit,
+        request,
         performance);
 
     // Resolve the expression in which the completion occurs
@@ -341,12 +402,37 @@
         performance.logStartTime(FUNCTIONAL_ARG_TAG);
         await dartRequest.resolveExpression(node);
         performance.logElapseTime(FUNCTIONAL_ARG_TAG);
+        dartRequest.checkAborted();
       }
     }
 
     performance.logElapseTime(BUILD_REQUEST_TAG);
     return dartRequest;
   }
+
+  static Future _computeAsync(
+      CompletionRequest request,
+      AnalysisTarget target,
+      ResultDescriptor descriptor,
+      CompletionPerformance performance,
+      String perfTag) async {
+    request.checkAborted();
+    performance.logStartTime(perfTag);
+    var result;
+    try {
+      result =
+          await new AnalysisFutureHelper(request.context, target, descriptor)
+              .computeAsync();
+    } catch (e, s) {
+      if (e is AnalysisNotScheduledError) {
+        request.checkAborted();
+      }
+      throw new AnalysisException(
+          'failed to $perfTag', new CaughtException(e, s));
+    }
+    request.checkAborted();
+    return result;
+  }
 }
 
 /**
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 736f2a0..abed735 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
@@ -10,12 +10,11 @@
 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/dart/optype.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
+import 'package:analyzer/src/generated/resolver.dart';
 
 import '../../../protocol_server.dart'
     show CompletionSuggestion, CompletionSuggestionKind;
-import 'package:analyzer/src/generated/resolver.dart';
 
 /**
  * A contributor for calculating suggestions for imported top level members.
@@ -31,29 +30,23 @@
       return EMPTY_LIST;
     }
 
-    List<Directive> directives = await request.resolveDirectives();
-    if (directives == null) {
+    List<ImportElement> imports = await request.resolveImports();
+    if (imports == null) {
       return EMPTY_LIST;
     }
 
     this.request = request;
     this.optype = (request as DartCompletionRequestImpl).opType;
+    List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
 
-    // Traverse dart:core
-    List<CompletionSuggestion> suggestions =
-        _buildSuggestions(request.coreLib.exportNamespace);
-
-    // Traverse imports
-    for (Directive directive in directives) {
-      if (directive is ImportDirective) {
-        ImportElement importElem = directive.element;
-        LibraryElement libElem = importElem?.importedLibrary;
-        if (libElem != null) {
-          suggestions.addAll(_buildSuggestions(libElem.exportNamespace,
-              prefix: importElem.prefix?.name,
-              showNames: showNamesIn(importElem),
-              hiddenNames: hiddenNamesIn(importElem)));
-        }
+    // Traverse imports including dart:core
+    for (ImportElement importElem in imports) {
+      LibraryElement libElem = importElem?.importedLibrary;
+      if (libElem != null) {
+        suggestions.addAll(_buildSuggestions(libElem.exportNamespace,
+            prefix: importElem.prefix?.name,
+            showNames: showNamesIn(importElem),
+            hiddenNames: hiddenNamesIn(importElem)));
       }
     }
 
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
index 9892a10..6008fe7 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
@@ -9,8 +9,9 @@
 
 import 'package:analysis_server/plugin/protocol/protocol.dart';
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 
 const ASYNC = 'async';
 const ASYNC_STAR = 'async*';
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 014d4ee..b5bae6c 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
@@ -14,8 +14,9 @@
 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:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 
 import '../../../protocol_server.dart'
@@ -27,6 +28,127 @@
     new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, '', 0)), null);
 
 /**
+* Create a new protocol Element for inclusion in a completion suggestion.
+*/
+protocol.Element createLocalElement(
+    Source source, protocol.ElementKind kind, SimpleIdentifier id,
+    {String parameters,
+    TypeName returnType,
+    bool isAbstract: false,
+    bool isDeprecated: false}) {
+  String name;
+  Location location;
+  if (id != null) {
+    name = id.name;
+    // TODO(danrubel) use lineInfo to determine startLine and startColumn
+    location = new Location(source.fullName, id.offset, id.length, 0, 0);
+  } else {
+    name = '';
+    location = new Location(source.fullName, -1, 0, 1, 0);
+  }
+  int flags = protocol.Element.makeFlags(
+      isAbstract: isAbstract,
+      isDeprecated: isDeprecated,
+      isPrivate: Identifier.isPrivateName(name));
+  return new protocol.Element(kind, name, flags,
+      location: location,
+      parameters: parameters,
+      returnType: nameForType(returnType));
+}
+
+/**
+* Create a new suggestion for the given field.
+* Return the new suggestion or `null` if it could not be created.
+*/
+CompletionSuggestion createLocalFieldSuggestion(
+    Source source, FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
+  bool deprecated = isDeprecated(fieldDecl) || isDeprecated(varDecl);
+  TypeName type = fieldDecl.fields.type;
+  return createLocalSuggestion(
+      varDecl.name, deprecated, DART_RELEVANCE_LOCAL_FIELD, type,
+      classDecl: fieldDecl.parent,
+      element: createLocalElement(
+          source, protocol.ElementKind.FIELD, varDecl.name,
+          returnType: type, isDeprecated: deprecated));
+}
+
+/**
+* Create a new suggestion based upon the given information.
+* Return the new suggestion or `null` if it could not be created.
+*/
+CompletionSuggestion createLocalSuggestion(SimpleIdentifier id,
+    bool isDeprecated, int defaultRelevance, TypeName returnType,
+    {ClassDeclaration classDecl, protocol.Element element}) {
+  if (id == null) {
+    return null;
+  }
+  String completion = id.name;
+  if (completion == null || completion.length <= 0 || completion == '_') {
+    return null;
+  }
+  CompletionSuggestion suggestion = new CompletionSuggestion(
+      CompletionSuggestionKind.INVOCATION,
+      isDeprecated ? DART_RELEVANCE_LOW : defaultRelevance,
+      completion,
+      completion.length,
+      0,
+      isDeprecated,
+      false,
+      returnType: nameForType(returnType),
+      element: element);
+  if (classDecl != null) {
+    SimpleIdentifier classId = classDecl.name;
+    if (classId != null) {
+      String className = classId.name;
+      if (className != null && className.length > 0) {
+        suggestion.declaringType = className;
+      }
+    }
+  }
+  return suggestion;
+}
+
+/**
+* Return `true` if the @deprecated annotation is present
+*/
+bool isDeprecated(AnnotatedNode node) {
+  if (node != null) {
+    NodeList<Annotation> metadata = node.metadata;
+    if (metadata != null) {
+      return metadata.any((Annotation a) {
+        return a.name is SimpleIdentifier && a.name.name == 'deprecated';
+      });
+    }
+  }
+  return false;
+}
+
+/**
+* Return the name for the given type.
+*/
+String nameForType(TypeName type) {
+  if (type == NO_RETURN_TYPE) {
+    return null;
+  }
+  if (type == null) {
+    return DYNAMIC;
+  }
+  Identifier id = type.name;
+  if (id == null) {
+    return DYNAMIC;
+  }
+  String name = id.name;
+  if (name == null || name.length <= 0) {
+    return DYNAMIC;
+  }
+  TypeArgumentList typeArgs = type.typeArguments;
+  if (typeArgs != null) {
+    //TODO (danrubel) include type arguments
+  }
+  return name;
+}
+
+/**
  * A contributor for calculating label suggestions.
  */
 class LabelContributor extends DartCompletionContributor {
@@ -163,124 +285,3 @@
     return null;
   }
 }
-
-/**
-* Create a new protocol Element for inclusion in a completion suggestion.
-*/
-protocol.Element createLocalElement(
-    Source source, protocol.ElementKind kind, SimpleIdentifier id,
-    {String parameters,
-    TypeName returnType,
-    bool isAbstract: false,
-    bool isDeprecated: false}) {
-  String name;
-  Location location;
-  if (id != null) {
-    name = id.name;
-    // TODO(danrubel) use lineInfo to determine startLine and startColumn
-    location = new Location(source.fullName, id.offset, id.length, 0, 0);
-  } else {
-    name = '';
-    location = new Location(source.fullName, -1, 0, 1, 0);
-  }
-  int flags = protocol.Element.makeFlags(
-      isAbstract: isAbstract,
-      isDeprecated: isDeprecated,
-      isPrivate: Identifier.isPrivateName(name));
-  return new protocol.Element(kind, name, flags,
-      location: location,
-      parameters: parameters,
-      returnType: nameForType(returnType));
-}
-
-/**
-* Create a new suggestion for the given field.
-* Return the new suggestion or `null` if it could not be created.
-*/
-CompletionSuggestion createLocalFieldSuggestion(
-    Source source, FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
-  bool deprecated = isDeprecated(fieldDecl) || isDeprecated(varDecl);
-  TypeName type = fieldDecl.fields.type;
-  return createLocalSuggestion(
-      varDecl.name, deprecated, DART_RELEVANCE_LOCAL_FIELD, type,
-      classDecl: fieldDecl.parent,
-      element: createLocalElement(
-          source, protocol.ElementKind.FIELD, varDecl.name,
-          returnType: type, isDeprecated: deprecated));
-}
-
-/**
-* Create a new suggestion based upon the given information.
-* Return the new suggestion or `null` if it could not be created.
-*/
-CompletionSuggestion createLocalSuggestion(SimpleIdentifier id,
-    bool isDeprecated, int defaultRelevance, TypeName returnType,
-    {ClassDeclaration classDecl, protocol.Element element}) {
-  if (id == null) {
-    return null;
-  }
-  String completion = id.name;
-  if (completion == null || completion.length <= 0 || completion == '_') {
-    return null;
-  }
-  CompletionSuggestion suggestion = new CompletionSuggestion(
-      CompletionSuggestionKind.INVOCATION,
-      isDeprecated ? DART_RELEVANCE_LOW : defaultRelevance,
-      completion,
-      completion.length,
-      0,
-      isDeprecated,
-      false,
-      returnType: nameForType(returnType),
-      element: element);
-  if (classDecl != null) {
-    SimpleIdentifier classId = classDecl.name;
-    if (classId != null) {
-      String className = classId.name;
-      if (className != null && className.length > 0) {
-        suggestion.declaringType = className;
-      }
-    }
-  }
-  return suggestion;
-}
-
-/**
-* Return `true` if the @deprecated annotation is present
-*/
-bool isDeprecated(AnnotatedNode node) {
-  if (node != null) {
-    NodeList<Annotation> metadata = node.metadata;
-    if (metadata != null) {
-      return metadata.any((Annotation a) {
-        return a.name is SimpleIdentifier && a.name.name == 'deprecated';
-      });
-    }
-  }
-  return false;
-}
-
-/**
-* Return the name for the given type.
-*/
-String nameForType(TypeName type) {
-  if (type == NO_RETURN_TYPE) {
-    return null;
-  }
-  if (type == null) {
-    return DYNAMIC;
-  }
-  Identifier id = type.name;
-  if (id == null) {
-    return DYNAMIC;
-  }
-  String name = id.name;
-  if (name == null || name.length <= 0) {
-    return DYNAMIC;
-  }
-  TypeArgumentList typeArgs = type.typeArguments;
-  if (typeArgs != null) {
-    //TODO (danrubel) include type arguments
-  }
-  return name;
-}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
index c7b9590..118103f 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
@@ -34,14 +34,13 @@
     Expression targetId = request.dotTarget;
     if (targetId is SimpleIdentifier && !request.target.isCascade) {
       Element elem = targetId.bestElement;
-      if (elem is PrefixElement) {
-        List<Directive> directives = await request.resolveDirectives();
+      if (elem is PrefixElement && !elem.isSynthetic) {
+        List<ImportElement> imports = await request.resolveImports();
         LibraryElement containingLibrary = request.libraryElement;
         // Gracefully degrade if the library or directives
         // could not be determined (e.g. detached part file or source change)
-        if (containingLibrary != null && directives != null) {
-          return _buildSuggestions(
-              request, elem, containingLibrary, directives);
+        if (containingLibrary != null && imports != null) {
+          return _buildSuggestions(request, elem, containingLibrary, imports);
         }
       }
     }
@@ -52,36 +51,27 @@
       DartCompletionRequest request,
       PrefixElement elem,
       LibraryElement containingLibrary,
-      List<Directive> directives) {
+      List<ImportElement> imports) {
     List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
-    for (Directive directive in directives) {
-      if (directive is ImportDirective) {
-        if (directive.prefix != null) {
-          if (directive.prefix.name == elem.name) {
-            LibraryElement library = directive.uriElement;
+    for (ImportElement importElem in imports) {
+      if (importElem.prefix?.name == elem.name) {
+        LibraryElement library = importElem.importedLibrary;
 
-            // Suggest elements from the imported library
-            if (library != null) {
-              AstNode parent = request.target.containingNode.parent;
-              bool isConstructor = parent.parent is ConstructorName;
-              bool typesOnly = parent is TypeName;
-              bool instCreation = typesOnly && isConstructor;
-              LibraryElementSuggestionBuilder builder =
-                  new LibraryElementSuggestionBuilder(
-                      containingLibrary,
-                      CompletionSuggestionKind.INVOCATION,
-                      typesOnly,
-                      instCreation);
-              library.visitChildren(builder);
-              suggestions.addAll(builder.suggestions);
+        // Suggest elements from the imported library
+        AstNode parent = request.target.containingNode.parent;
+        bool isConstructor = parent.parent is ConstructorName;
+        bool typesOnly = parent is TypeName;
+        bool instCreation = typesOnly && isConstructor;
+        LibraryElementSuggestionBuilder builder =
+            new LibraryElementSuggestionBuilder(containingLibrary,
+                CompletionSuggestionKind.INVOCATION, typesOnly, instCreation);
+        library.visitChildren(builder);
+        suggestions.addAll(builder.suggestions);
 
-              // If the import is 'deferred' then suggest 'loadLibrary'
-              if (directive.deferredKeyword != null) {
-                FunctionElement loadLibFunct = library.loadLibraryFunction;
-                suggestions.add(createSuggestion(loadLibFunct));
-              }
-            }
-          }
+        // If the import is 'deferred' then suggest 'loadLibrary'
+        if (importElem.isDeferred) {
+          FunctionElement loadLibFunct = library.loadLibraryFunction;
+          suggestions.add(createSuggestion(loadLibFunct));
         }
       }
     }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
index 194e741..a216606 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
@@ -9,7 +9,6 @@
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
 
 import '../../../protocol_server.dart'
     show CompletionSuggestion, CompletionSuggestionKind;
@@ -26,26 +25,22 @@
       return EMPTY_LIST;
     }
 
-    List<Directive> directives = await request.resolveDirectives();
-    if (directives == null) {
+    List<ImportElement> imports = await request.resolveImports();
+    if (imports == null) {
       return EMPTY_LIST;
     }
 
     List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
-    for (Directive directive in directives) {
-      if (directive is ImportDirective) {
-        SimpleIdentifier prefix = directive.prefix;
-        ImportElement element = directive.element;
-        if (prefix != null && element != null) {
-          String completion = prefix.name;
-          LibraryElement libElem = element.importedLibrary;
-          if (completion != null && completion.length > 0 && libElem != null) {
-            CompletionSuggestion suggestion = createSuggestion(libElem,
-                completion: completion,
-                kind: CompletionSuggestionKind.IDENTIFIER);
-            if (suggestion != null) {
-              suggestions.add(suggestion);
-            }
+    for (ImportElement element in imports) {
+      String completion = element.prefix?.name;
+      if (completion != null && completion.length > 0) {
+        LibraryElement libElem = element.importedLibrary;
+        if (libElem != null) {
+          CompletionSuggestion suggestion = createSuggestion(libElem,
+              completion: completion,
+              kind: CompletionSuggestionKind.IDENTIFIER);
+          if (suggestion != null) {
+            suggestions.add(suggestion);
           }
         }
       }
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 d8d4e36..c05a215 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
@@ -15,9 +15,10 @@
     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:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 
 import '../../../protocol_server.dart'
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_declaration_visitor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_declaration_visitor.dart
index 964c6b4..586eac2 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_declaration_visitor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_declaration_visitor.dart
@@ -4,8 +4,9 @@
 
 library services.completion.dart.local.declaration.visitor;
 
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 
 /**
  * `LocalDeclarationCollector` visits an [AstNode] and its parent recursively
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 9469154..9b36935 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
@@ -11,7 +11,6 @@
 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:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
 
 import '../../../protocol_server.dart'
@@ -30,23 +29,17 @@
       return EMPTY_LIST;
     }
 
-    List<Directive> directives = await request.resolveDirectives();
-    if (directives == null) {
+    List<CompilationUnitElement> libraryUnits = await request.resolveUnits();
+    if (libraryUnits == null) {
       return EMPTY_LIST;
     }
 
     OpType optype = (request as DartCompletionRequestImpl).opType;
     LibraryElementSuggestionBuilder visitor =
         new LibraryElementSuggestionBuilder(request, optype);
-    if (request.librarySource != request.source) {
-      request.libraryElement.definingCompilationUnit.accept(visitor);
-    }
-    for (Directive directive in directives) {
-      if (directive is PartDirective) {
-        CompilationUnitElement partElem = directive.element;
-        if (partElem != null && partElem.source != request.source) {
-          partElem.accept(visitor);
-        }
+    for (CompilationUnitElement unit in libraryUnits) {
+      if (unit != null && unit.source != request.source) {
+        unit.accept(visitor);
       }
     }
     return visitor.suggestions;
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 966f1d9..661f89a 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
@@ -15,8 +15,9 @@
     show LocalDeclarationVisitor;
 import 'package:analysis_server/src/services/completion/dart/optype.dart';
 import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart' show ParameterKind;
 
@@ -29,6 +30,116 @@
     new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, '', 0)), null);
 
 /**
+* Create a new protocol Element for inclusion in a completion suggestion.
+*/
+protocol.Element _createLocalElement(
+    Source source, protocol.ElementKind kind, SimpleIdentifier id,
+    {String parameters,
+    TypeName returnType,
+    bool isAbstract: false,
+    bool isDeprecated: false}) {
+  String name;
+  Location location;
+  if (id != null) {
+    name = id.name;
+    // TODO(danrubel) use lineInfo to determine startLine and startColumn
+    location = new Location(source.fullName, id.offset, id.length, 0, 0);
+  } else {
+    name = '';
+    location = new Location(source.fullName, -1, 0, 1, 0);
+  }
+  int flags = protocol.Element.makeFlags(
+      isAbstract: isAbstract,
+      isDeprecated: isDeprecated,
+      isPrivate: Identifier.isPrivateName(name));
+  return new protocol.Element(kind, name, flags,
+      location: location,
+      parameters: parameters,
+      returnType: _nameForType(returnType));
+}
+
+/**
+* Create a new suggestion based upon the given information.
+* Return the new suggestion or `null` if it could not be created.
+*/
+CompletionSuggestion _createLocalSuggestion(
+    SimpleIdentifier id,
+    CompletionSuggestionKind kind,
+    bool isDeprecated,
+    int defaultRelevance,
+    TypeName returnType,
+    {ClassDeclaration classDecl,
+    protocol.Element element}) {
+  if (id == null) {
+    return null;
+  }
+  String completion = id.name;
+  if (completion == null || completion.length <= 0 || completion == '_') {
+    return null;
+  }
+  CompletionSuggestion suggestion = new CompletionSuggestion(
+      kind,
+      isDeprecated ? DART_RELEVANCE_LOW : defaultRelevance,
+      completion,
+      completion.length,
+      0,
+      isDeprecated,
+      false,
+      returnType: _nameForType(returnType),
+      element: element);
+  if (classDecl != null) {
+    SimpleIdentifier classId = classDecl.name;
+    if (classId != null) {
+      String className = classId.name;
+      if (className != null && className.length > 0) {
+        suggestion.declaringType = className;
+      }
+    }
+  }
+  return suggestion;
+}
+
+/**
+* Return `true` if the @deprecated annotation is present
+*/
+bool _isDeprecated(AnnotatedNode node) {
+  if (node != null) {
+    NodeList<Annotation> metadata = node.metadata;
+    if (metadata != null) {
+      return metadata.any((Annotation a) {
+        return a.name is SimpleIdentifier && a.name.name == 'deprecated';
+      });
+    }
+  }
+  return false;
+}
+
+/**
+* Return the name for the given type.
+*/
+String _nameForType(TypeName type) {
+  if (type == NO_RETURN_TYPE) {
+    return null;
+  }
+  if (type == null) {
+    return DYNAMIC;
+  }
+  Identifier id = type.name;
+  if (id == null) {
+    return DYNAMIC;
+  }
+  String name = id.name;
+  if (name == null || name.length <= 0) {
+    return DYNAMIC;
+  }
+  TypeArgumentList typeArgs = type.typeArguments;
+  if (typeArgs != null) {
+    //TODO (danrubel) include type arguments
+  }
+  return name;
+}
+
+/**
  * A contributor for calculating suggestions for declarations in the local
  * file and containing library.
  */
@@ -259,6 +370,38 @@
     }
   }
 
+  void _addLocalSuggestion(
+      SimpleIdentifier id, TypeName typeName, protocol.ElementKind elemKind,
+      {bool isAbstract: false,
+      bool isDeprecated: false,
+      ClassDeclaration classDecl,
+      FormalParameterList param,
+      int relevance: DART_RELEVANCE_DEFAULT}) {
+    CompletionSuggestionKind kind = targetIsFunctionalArgument
+        ? CompletionSuggestionKind.IDENTIFIER
+        : optype.suggestKind;
+    CompletionSuggestion suggestion = _createLocalSuggestion(
+        id, kind, isDeprecated, relevance, typeName,
+        classDecl: classDecl);
+    if (suggestion != null) {
+      if (privateMemberRelevance != null &&
+          suggestion.completion.startsWith('_')) {
+        suggestion.relevance = privateMemberRelevance;
+      }
+      suggestionMap.putIfAbsent(suggestion.completion, () => suggestion);
+      suggestion.element = _createLocalElement(request.source, elemKind, id,
+          isAbstract: isAbstract,
+          isDeprecated: isDeprecated,
+          parameters: param != null ? param.toSource() : null,
+          returnType: typeName);
+      if ((elemKind == protocol.ElementKind.METHOD ||
+              elemKind == protocol.ElementKind.FUNCTION) &&
+          param != null) {
+        _addParameterInfo(suggestion, param);
+      }
+    }
+  }
+
   void _addParameterInfo(
       CompletionSuggestion suggestion, FormalParameterList parameters) {
     var paramList = parameters.parameters;
@@ -296,38 +439,6 @@
         .any((FormalParameter param) => param.kind == ParameterKind.NAMED);
   }
 
-  void _addLocalSuggestion(
-      SimpleIdentifier id, TypeName typeName, protocol.ElementKind elemKind,
-      {bool isAbstract: false,
-      bool isDeprecated: false,
-      ClassDeclaration classDecl,
-      FormalParameterList param,
-      int relevance: DART_RELEVANCE_DEFAULT}) {
-    CompletionSuggestionKind kind = targetIsFunctionalArgument
-        ? CompletionSuggestionKind.IDENTIFIER
-        : optype.suggestKind;
-    CompletionSuggestion suggestion = _createLocalSuggestion(
-        id, kind, isDeprecated, relevance, typeName,
-        classDecl: classDecl);
-    if (suggestion != null) {
-      if (privateMemberRelevance != null &&
-          suggestion.completion.startsWith('_')) {
-        suggestion.relevance = privateMemberRelevance;
-      }
-      suggestionMap.putIfAbsent(suggestion.completion, () => suggestion);
-      suggestion.element = _createLocalElement(request.source, elemKind, id,
-          isAbstract: isAbstract,
-          isDeprecated: isDeprecated,
-          parameters: param != null ? param.toSource() : null,
-          returnType: typeName);
-      if ((elemKind == protocol.ElementKind.METHOD ||
-              elemKind == protocol.ElementKind.FUNCTION) &&
-          param != null) {
-        _addParameterInfo(suggestion, param);
-      }
-    }
-  }
-
   bool _isVoid(TypeName returnType) {
     if (returnType != null) {
       Identifier id = returnType.name;
@@ -338,113 +449,3 @@
     return false;
   }
 }
-
-/**
-* Create a new protocol Element for inclusion in a completion suggestion.
-*/
-protocol.Element _createLocalElement(
-    Source source, protocol.ElementKind kind, SimpleIdentifier id,
-    {String parameters,
-    TypeName returnType,
-    bool isAbstract: false,
-    bool isDeprecated: false}) {
-  String name;
-  Location location;
-  if (id != null) {
-    name = id.name;
-    // TODO(danrubel) use lineInfo to determine startLine and startColumn
-    location = new Location(source.fullName, id.offset, id.length, 0, 0);
-  } else {
-    name = '';
-    location = new Location(source.fullName, -1, 0, 1, 0);
-  }
-  int flags = protocol.Element.makeFlags(
-      isAbstract: isAbstract,
-      isDeprecated: isDeprecated,
-      isPrivate: Identifier.isPrivateName(name));
-  return new protocol.Element(kind, name, flags,
-      location: location,
-      parameters: parameters,
-      returnType: _nameForType(returnType));
-}
-
-/**
-* Create a new suggestion based upon the given information.
-* Return the new suggestion or `null` if it could not be created.
-*/
-CompletionSuggestion _createLocalSuggestion(
-    SimpleIdentifier id,
-    CompletionSuggestionKind kind,
-    bool isDeprecated,
-    int defaultRelevance,
-    TypeName returnType,
-    {ClassDeclaration classDecl,
-    protocol.Element element}) {
-  if (id == null) {
-    return null;
-  }
-  String completion = id.name;
-  if (completion == null || completion.length <= 0 || completion == '_') {
-    return null;
-  }
-  CompletionSuggestion suggestion = new CompletionSuggestion(
-      kind,
-      isDeprecated ? DART_RELEVANCE_LOW : defaultRelevance,
-      completion,
-      completion.length,
-      0,
-      isDeprecated,
-      false,
-      returnType: _nameForType(returnType),
-      element: element);
-  if (classDecl != null) {
-    SimpleIdentifier classId = classDecl.name;
-    if (classId != null) {
-      String className = classId.name;
-      if (className != null && className.length > 0) {
-        suggestion.declaringType = className;
-      }
-    }
-  }
-  return suggestion;
-}
-
-/**
-* Return `true` if the @deprecated annotation is present
-*/
-bool _isDeprecated(AnnotatedNode node) {
-  if (node != null) {
-    NodeList<Annotation> metadata = node.metadata;
-    if (metadata != null) {
-      return metadata.any((Annotation a) {
-        return a.name is SimpleIdentifier && a.name.name == 'deprecated';
-      });
-    }
-  }
-  return false;
-}
-
-/**
-* Return the name for the given type.
-*/
-String _nameForType(TypeName type) {
-  if (type == NO_RETURN_TYPE) {
-    return null;
-  }
-  if (type == null) {
-    return DYNAMIC;
-  }
-  Identifier id = type.name;
-  if (id == null) {
-    return DYNAMIC;
-  }
-  String name = id.name;
-  if (name == null || name.length <= 0) {
-    return DYNAMIC;
-  }
-  TypeArgumentList typeArgs = type.typeArguments;
-  if (typeArgs != null) {
-    //TODO (danrubel) include type arguments
-  }
-  return name;
-}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/optype.dart b/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
index 9acbf07..71c1bfd 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
@@ -4,10 +4,11 @@
 
 library services.completion.dart.optype;
 
-import 'package:analysis_server/src/provisional/completion/dart/completion_target.dart';
-import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analysis_server/src/provisional/completion/dart/completion_target.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/generated/ast.dart';
 
 /**
  * An [AstVisitor] for determining whether top level suggestions or invocation
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
index 257527b..7a0f760 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
@@ -72,7 +72,8 @@
         } else if (elem is LocalVariableElement) {
           type = elem.type;
         }
-        if (type.isDynamic && expression is SimpleIdentifier) {
+        if ((type == null || type.isDynamic) &&
+            expression is SimpleIdentifier) {
           // If the element does not provide a good type
           // then attempt to get a better type from a local declaration
           _LocalBestTypeVisitor visitor =
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index 13714ae..be95ec1 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -17,12 +17,13 @@
 import 'package:analysis_server/src/services/correction/statement_analyzer.dart';
 import 'package:analysis_server/src/services/correction/util.dart';
 import 'package:analysis_server/src/services/search/hierarchy.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:path/path.dart';
 
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 ffdf72d..36eb5b9 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -24,9 +24,11 @@
 import 'package:analysis_server/src/services/correction/strings.dart';
 import 'package:analysis_server/src/services/correction/util.dart';
 import 'package:analysis_server/src/services/search/hierarchy.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
@@ -35,7 +37,6 @@
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
diff --git a/pkg/analysis_server/lib/src/services/correction/organize_directives.dart b/pkg/analysis_server/lib/src/services/correction/organize_directives.dart
index a4adfac..9d9faa1 100644
--- a/pkg/analysis_server/lib/src/services/correction/organize_directives.dart
+++ b/pkg/analysis_server/lib/src/services/correction/organize_directives.dart
@@ -7,9 +7,9 @@
 import 'package:analysis_server/plugin/protocol/protocol.dart'
     hide AnalysisError, Element;
 import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 
 /**
  * Organizer of directives in the [unit].
diff --git a/pkg/analysis_server/lib/src/services/correction/sort_members.dart b/pkg/analysis_server/lib/src/services/correction/sort_members.dart
index 1810cda..49f104b 100644
--- a/pkg/analysis_server/lib/src/services/correction/sort_members.dart
+++ b/pkg/analysis_server/lib/src/services/correction/sort_members.dart
@@ -6,8 +6,8 @@
 
 import 'package:analysis_server/plugin/protocol/protocol.dart' hide Element;
 import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 
 /**
  * Sorter for unit/class members.
diff --git a/pkg/analysis_server/lib/src/services/correction/source_range.dart b/pkg/analysis_server/lib/src/services/correction/source_range.dart
index bf52759..32c98b9 100644
--- a/pkg/analysis_server/lib/src/services/correction/source_range.dart
+++ b/pkg/analysis_server/lib/src/services/correction/source_range.dart
@@ -4,10 +4,10 @@
 
 library services.src.correction.source_range_factory;
 
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 
 SourceRange rangeElementName(Element element) {
diff --git a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
index c25f77a..2ec69eb 100644
--- a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
@@ -9,9 +9,11 @@
 import 'package:analysis_server/src/services/correction/source_range.dart';
 import 'package:analysis_server/src/services/correction/status.dart';
 import 'package:analysis_server/src/services/correction/util.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.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/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index c69bf69..65c12c6 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -12,12 +12,15 @@
     show doSourceChange_addElementEdit;
 import 'package:analysis_server/src/services/correction/source_range.dart';
 import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:path/path.dart';
 
diff --git a/pkg/analysis_server/lib/src/services/index/index_contributor.dart b/pkg/analysis_server/lib/src/services/index/index_contributor.dart
index b5eee6b..ebac4d6 100644
--- a/pkg/analysis_server/lib/src/services/index/index_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/index/index_contributor.dart
@@ -12,12 +12,12 @@
 import 'package:analysis_server/src/services/index/index_store.dart';
 import 'package:analysis_server/src/services/index/indexable_element.dart';
 import 'package:analysis_server/src/services/index/indexable_file.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 
 /**
diff --git a/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart b/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
index 51db1c2..d91306c 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
@@ -13,9 +13,9 @@
 import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
 import 'package:analysis_server/src/services/search/hierarchy.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
-import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/source.dart';
 
 /**
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 a17bfda..bb513ba 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
@@ -17,10 +17,10 @@
 import 'package:analysis_server/src/services/refactoring/naming_conventions.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 
 const String _TOKEN_SEPARATOR = "\uFFFF";
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index 7855298..1cb713a 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -20,13 +20,13 @@
 import 'package:analysis_server/src/services/refactoring/rename_unit_member.dart';
 import 'package:analysis_server/src/services/search/element_visitors.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/resolver.dart' show ExitDetector;
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 
 const String _TOKEN_SEPARATOR = '\uFFFF';
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
index 1fe699a..d5c6894 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
@@ -13,10 +13,10 @@
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 
 /**
diff --git a/pkg/analysis_server/lib/src/services/refactoring/naming_conventions.dart b/pkg/analysis_server/lib/src/services/refactoring/naming_conventions.dart
index aac5275..892da77 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/naming_conventions.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/naming_conventions.dart
@@ -6,7 +6,7 @@
 
 import 'package:analysis_server/src/services/correction/status.dart';
 import 'package:analysis_server/src/services/correction/strings.dart';
-import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/dart/ast/token.dart';
 
 /**
  * Returns the [RefactoringStatus] with severity:
diff --git a/pkg/analysis_server/lib/src/socket_server.dart b/pkg/analysis_server/lib/src/socket_server.dart
index 9fd17ca..ad1baaa 100644
--- a/pkg/analysis_server/lib/src/socket_server.dart
+++ b/pkg/analysis_server/lib/src/socket_server.dart
@@ -15,6 +15,7 @@
 import 'package:analyzer/plugin/embedded_resolver_provider.dart';
 import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/source/pub_package_map_provider.dart';
+import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/sdk_io.dart';
 import 'package:plugin/plugin.dart';
 
@@ -26,6 +27,12 @@
  */
 class SocketServer {
   final AnalysisServerOptions analysisServerOptions;
+
+  /**
+   * The function used to create a new SDK using the default SDK.
+   */
+  final SdkCreator defaultSdkCreator;
+
   final DirectoryBasedDartSdk defaultSdk;
   final InstrumentationService instrumentationService;
   final ServerPlugin serverPlugin;
@@ -45,6 +52,7 @@
 
   SocketServer(
       this.analysisServerOptions,
+      this.defaultSdkCreator,
       this.defaultSdk,
       this.instrumentationService,
       this.serverPlugin,
@@ -91,7 +99,7 @@
         index,
         serverPlugin,
         analysisServerOptions,
-        defaultSdk,
+        defaultSdkCreator,
         instrumentationService,
         packageResolverProvider: packageResolverProvider,
         embeddedResolverProvider: embeddedResolverProvider,
diff --git a/pkg/analysis_server/lib/src/status/validator.dart b/pkg/analysis_server/lib/src/status/validator.dart
index b153c29..07f34b3 100644
--- a/pkg/analysis_server/lib/src/status/validator.dart
+++ b/pkg/analysis_server/lib/src/status/validator.dart
@@ -6,17 +6,17 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisEngine, AnalysisResult, CacheState, ChangeSet;
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_collection.dart';
 import 'package:analyzer/src/task/dart.dart';
@@ -24,7 +24,6 @@
 import 'package:analyzer/task/dart.dart';
 import 'package:analyzer/task/model.dart';
 import 'package:html/dom.dart' as html;
-import 'package:analyzer/src/dart/element/element.dart';
 
 /**
  * A class used to compare two element models for equality.
@@ -757,8 +756,8 @@
    * Write a simple message explaining that the [expected] and [actual] values
    * were different, using the [describe] function to describe the values.
    */
-  void _writeMismatch /*<E>*/ (Object /*=E*/ expected, Object /*=E*/ actual,
-      String describe(Object /*=E*/ value)) {
+  void _writeMismatch/*<E>*/(Object/*=E*/ expected, Object/*=E*/ actual,
+      String describe(Object/*=E*/ value)) {
     _write('Expected ');
     _write(describe(expected));
     _write('; found ');
@@ -1194,8 +1193,7 @@
     //
     // Handle special cases.
     //
-    if (first is ElementAnnotationImpl &&
-        second is ElementAnnotationImpl) {
+    if (first is ElementAnnotationImpl && second is ElementAnnotationImpl) {
       return _equal(first.source, second.source) &&
           _equal(first.librarySource, second.librarySource) &&
           _equal(first.annotationAst, second.annotationAst);
diff --git a/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart b/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
index bac921d..51131dc 100644
--- a/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
+++ b/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
@@ -10,11 +10,11 @@
 import 'package:analysis_server/src/services/correction/name_suggestion.dart';
 import 'package:analysis_server/src/services/correction/util.dart';
 import 'package:analysis_server/src/utilities/change_builder_core.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
diff --git a/pkg/analysis_server/test/analysis/set_priority_files_test.dart b/pkg/analysis_server/test/analysis/set_priority_files_test.dart
index f89ba30..9a1b5c9 100644
--- a/pkg/analysis_server/test/analysis/set_priority_files_test.dart
+++ b/pkg/analysis_server/test/analysis/set_priority_files_test.dart
@@ -58,7 +58,7 @@
     Response response = await _setPriorityFile(filePath);
     expect(response, isResponseSuccess('0'));
     // verify
-    InternalAnalysisContext sdkContext = server.defaultSdk.context;
+    InternalAnalysisContext sdkContext = server.findSdk().context;
     List<Source> prioritySources = sdkContext.prioritySources;
     expect(prioritySources, hasLength(1));
     expect(prioritySources.first.fullName, filePath);
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index 4faf108..3541d91 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -126,7 +126,7 @@
         index,
         serverPlugin,
         new AnalysisServerOptions(),
-        new MockSdk(),
+        () => new MockSdk(),
         InstrumentationService.NULL_SERVICE);
   }
 
@@ -171,7 +171,7 @@
    */
   Response handleSuccessfulRequest(Request request) {
     Response response = handler.handleRequest(request);
-    expect(response, isResponseSuccess('0'));
+    expect(response, isResponseSuccess(request.id));
     return response;
   }
 
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index 14d9fd6..e12a691 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -141,7 +141,7 @@
         null,
         new ServerPlugin(),
         new AnalysisServerOptions(),
-        new MockSdk(),
+        () => new MockSdk(),
         InstrumentationService.NULL_SERVICE,
         rethrowExceptions: true);
     processRequiredPlugins();
@@ -152,12 +152,15 @@
     resourceProvider.newFile('/foo/bar.dart', 'library lib;');
     server.setAnalysisRoots('0', ['/foo'], [], {});
     AnalysisContext context;
-    return pumpEventQueue().then((_) {
-      context = server.getAnalysisContext('/foo/bar.dart');
-      server.setAnalysisRoots('1', [], [], {});
-    }).then((_) => pumpEventQueue()).then((_) {
-      expect(context.isDisposed, isTrue);
-    });
+    return pumpEventQueue()
+        .then((_) {
+          context = server.getAnalysisContext('/foo/bar.dart');
+          server.setAnalysisRoots('1', [], [], {});
+        })
+        .then((_) => pumpEventQueue())
+        .then((_) {
+          expect(context.isDisposed, isTrue);
+        });
   }
 
   Future test_contextsChangedEvent() {
@@ -529,8 +532,9 @@
   void _assertContextOfFolder(
       AnalysisContext context, String expectedFolderPath) {
     Folder expectedFolder = resourceProvider.newFolder(expectedFolderPath);
-    ContextInfo expectedContextInfo = (server.contextManager
-        as ContextManagerImpl).getContextInfoFor(expectedFolder);
+    ContextInfo expectedContextInfo =
+        (server.contextManager as ContextManagerImpl)
+            .getContextInfoFor(expectedFolder);
     expect(expectedContextInfo, isNotNull);
     expect(context, same(expectedContextInfo.context));
   }
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index d225c90..a94314b 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -2363,7 +2363,11 @@
   Iterable<String> get currentContextPaths => currentContextTimestamps.keys;
 
   @override
-  AnalysisContext addContext(Folder folder, FolderDisposition disposition) {
+  AnalysisOptions get defaultAnalysisOptions => new AnalysisOptionsImpl();
+
+  @override
+  AnalysisContext addContext(
+      Folder folder, AnalysisOptions options, FolderDisposition disposition) {
     String path = folder.path;
     expect(currentContextPaths, isNot(contains(path)));
     currentContextTimestamps[path] = now;
@@ -2386,6 +2390,7 @@
     }
     resolvers.addAll(disposition.createPackageUriResolvers(resourceProvider));
     resolvers.add(new FileUriResolver());
+    currentContext.analysisOptions = options;
     currentContext.sourceFactory =
         new SourceFactory(resolvers, disposition.packages);
     return currentContext;
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index b7f4b34..f8c0afd 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -47,7 +47,7 @@
         null,
         serverPlugin,
         new AnalysisServerOptions(),
-        new MockSdk(),
+        () => new MockSdk(),
         InstrumentationService.NULL_SERVICE);
     handler = new AnalysisDomainHandler(server);
   });
@@ -474,7 +474,7 @@
         null,
         serverPlugin,
         new AnalysisServerOptions(),
-        new MockSdk(),
+        () => new MockSdk(),
         InstrumentationService.NULL_SERVICE);
     handler = new AnalysisDomainHandler(server);
     // listen for notifications
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index acff007..61734b6 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -17,6 +17,7 @@
 
 import 'analysis_abstract.dart';
 import 'domain_completion_util.dart';
+import 'mocks.dart' show pumpEventQueue;
 import 'utils.dart';
 
 main() {
@@ -53,6 +54,76 @@
     });
   }
 
+  test_imports_aborted_new_request() async {
+    addTestFile('''
+        class foo { }
+        c^''');
+
+    // Make a request for suggestions
+    Request request =
+        new CompletionGetSuggestionsParams(testFile, completionOffset)
+            .toRequest('7');
+    Response response = handleSuccessfulRequest(request);
+    var result1 = new CompletionGetSuggestionsResult.fromResponse(response);
+    var completionId1 = result1.id;
+    assertValidId(response.id);
+
+    // Perform some analysis but assert that no suggestions have yet been made
+    completionId = completionId1;
+    await pumpEventQueue(25);
+    expect(suggestionsDone, isFalse);
+    expect(suggestions, hasLength(0));
+
+    // Make another request before the first request completes
+    Request request2 =
+        new CompletionGetSuggestionsParams(testFile, completionOffset)
+            .toRequest('8');
+    Response response2 = handleSuccessfulRequest(request2);
+    var result2 = new CompletionGetSuggestionsResult.fromResponse(response2);
+    var completionId2 = result2.id;
+    assertValidId(completionId2);
+
+    // Wait for both sets of suggestions
+    completionId = completionId2;
+    await pumpEventQueue();
+    expect(allSuggestions[completionId1], hasLength(0));
+    expect(allSuggestions[completionId2], same(suggestions));
+    assertHasResult(CompletionSuggestionKind.KEYWORD, 'class',
+        relevance: DART_RELEVANCE_HIGH);
+  }
+
+  test_imports_aborted_source_changed() async {
+    addTestFile('''
+        class foo { }
+        c^''');
+
+    // Make a request for suggestions
+    Request request =
+        new CompletionGetSuggestionsParams(testFile, completionOffset)
+            .toRequest('0');
+    Response response = handleSuccessfulRequest(request);
+    completionId = response.id;
+    assertValidId(completionId);
+
+    // Perform some analysis but assert that no suggestions have yet been made
+    await pumpEventQueue(25);
+    expect(suggestionsDone, isFalse);
+    expect(suggestions, hasLength(0));
+
+    // Simulate user deleting text after request but before suggestions returned
+    server.updateContent('uc1', {testFile: new AddContentOverlay(testCode)});
+    server.updateContent('uc2', {
+      testFile: new ChangeContentOverlay(
+          [new SourceEdit(completionOffset - 1, 1, '')])
+    });
+
+    // Expect the completion domain to discard request because source changed
+    await pumpEventQueue().then((_) {
+      expect(suggestionsDone, isTrue);
+    });
+    expect(suggestions, hasLength(0));
+  }
+
   test_imports_incremental() async {
     addTestFile('''library foo;
       e^
diff --git a/pkg/analysis_server/test/domain_completion_util.dart b/pkg/analysis_server/test/domain_completion_util.dart
index 29cff99..7c4ed6c 100644
--- a/pkg/analysis_server/test/domain_completion_util.dart
+++ b/pkg/analysis_server/test/domain_completion_util.dart
@@ -24,6 +24,7 @@
   int replacementLength;
   List<CompletionSuggestion> suggestions = [];
   bool suggestionsDone = false;
+  Map<String,List<CompletionSuggestion>> allSuggestions = {};
 
   String addTestFile(String content, {int offset}) {
     completionOffset = content.indexOf('^');
@@ -109,6 +110,7 @@
         expect(suggestionsDone, isNotNull);
         suggestions = params.results;
       }
+      allSuggestions[id] = params.results;
     } else if (notification.event == SERVER_ERROR) {
       fail('server error: ${notification.toJson()}');
     }
diff --git a/pkg/analysis_server/test/domain_diagnostic_test.dart b/pkg/analysis_server/test/domain_diagnostic_test.dart
index e0a6867..277279a 100644
--- a/pkg/analysis_server/test/domain_diagnostic_test.dart
+++ b/pkg/analysis_server/test/domain_diagnostic_test.dart
@@ -53,7 +53,7 @@
         null,
         serverPlugin,
         new AnalysisServerOptions(),
-        new MockSdk(),
+        () => new MockSdk(),
         InstrumentationService.NULL_SERVICE);
     handler = new DiagnosticDomainHandler(server);
   });
diff --git a/pkg/analysis_server/test/domain_execution_test.dart b/pkg/analysis_server/test/domain_execution_test.dart
index a142adb..1274eab 100644
--- a/pkg/analysis_server/test/domain_execution_test.dart
+++ b/pkg/analysis_server/test/domain_execution_test.dart
@@ -48,7 +48,7 @@
           null,
           serverPlugin,
           new AnalysisServerOptions(),
-          new MockSdk(),
+          () => new MockSdk(),
           InstrumentationService.NULL_SERVICE);
       handler = new ExecutionDomainHandler(server);
     });
@@ -124,8 +124,9 @@
 
       group('file to URI', () {
         test('does not exist', () {
-          Request request = new ExecutionMapUriParams(contextId,
-              file: '/a/c.dart').toRequest('2');
+          Request request =
+              new ExecutionMapUriParams(contextId, file: '/a/c.dart')
+                  .toRequest('2');
           Response response = handler.handleRequest(request);
           expect(response, isResponseFailure('2'));
         });
@@ -141,8 +142,9 @@
 
       group('URI to file', () {
         test('invalid', () {
-          Request request = new ExecutionMapUriParams(contextId,
-              uri: 'foo:///a/b.dart').toRequest('2');
+          Request request =
+              new ExecutionMapUriParams(contextId, uri: 'foo:///a/b.dart')
+                  .toRequest('2');
           Response response = handler.handleRequest(request);
           expect(response, isResponseFailure('2'));
         });
@@ -299,7 +301,7 @@
   }
 
   void test_mapUri_file_dartUriKind() {
-    String path = server.defaultSdk.mapDartUri('dart:async').fullName;
+    String path = server.findSdk().mapDartUri('dart:async').fullName;
     // hack - pretend that the SDK file exists in the project FS
     resourceProvider.newFile(path, '// hack');
     // map file
diff --git a/pkg/analysis_server/test/domain_server_test.dart b/pkg/analysis_server/test/domain_server_test.dart
index 51237cd..6dc24d1 100644
--- a/pkg/analysis_server/test/domain_server_test.dart
+++ b/pkg/analysis_server/test/domain_server_test.dart
@@ -37,7 +37,7 @@
         null,
         serverPlugin,
         new AnalysisServerOptions(),
-        new MockSdk(),
+        () => new MockSdk(),
         InstrumentationService.NULL_SERVICE);
     handler = new ServerDomainHandler(server);
   });
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 28c6a09..8ecfc8f 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
@@ -436,6 +436,7 @@
   }
 
   Future computeSuggestions([int times = 200]) async {
+    context.analysisPriorityOrder = [testSource];
     CompletionRequestImpl baseRequest = new CompletionRequestImpl(
         context,
         provider,
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
new file mode 100644
index 0000000..fa43aa1
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
@@ -0,0 +1,106 @@
+// 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 test.services.completion.dart.manager;
+
+import 'dart:async';
+
+import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
+import 'package:analysis_server/src/services/completion/completion_core.dart';
+import 'package:analysis_server/src/services/completion/completion_performance.dart';
+import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/imported_reference_contributor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/task/dart.dart';
+import 'package:analyzer/src/task/dart.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../../utils.dart';
+import 'completion_contributor_util.dart';
+import 'package:analyzer/src/generated/source.dart';
+
+main() {
+  initializeTestEnvironment();
+  defineReflectiveTests(CompletionManagerTest);
+}
+
+@reflectiveTest
+class CompletionManagerTest extends DartCompletionContributorTest {
+  @override
+  DartCompletionContributor createContributor() {
+    return new ImportedReferenceContributor();
+  }
+
+  test_resolveDirectives() async {
+    addSource(
+        '/libA.dart',
+        '''
+library libA;
+/// My class.
+/// Short description.
+///
+/// Longer description.
+class A {}
+''');
+    var libSource = addSource(
+        '/libB.dart',
+        '''
+library libB;
+import "/libA.dart" as foo;
+part '$testFile';
+''');
+    addTestSource('part of libB; main() {^}');
+
+    // Associate part with library
+    context.computeResult(
+        new LibrarySpecificUnit(libSource, testSource), LIBRARY_CYCLE_UNITS);
+
+    // Build the request
+    CompletionRequestImpl baseRequest = new CompletionRequestImpl(
+        context,
+        provider,
+        searchEngine,
+        testSource,
+        completionOffset,
+        new CompletionPerformance());
+    Completer<DartCompletionRequest> requestCompleter =
+        new Completer<DartCompletionRequest>();
+    DartCompletionRequestImpl
+        .from(baseRequest, resultDescriptor: RESOLVED_UNIT1)
+        .then((DartCompletionRequest request) {
+      requestCompleter.complete(request);
+    });
+    request = await performAnalysis(200, requestCompleter);
+
+    // Get the unresolved directives
+    var directives = request.target.unit.directives;
+
+    // Assert that the import does not have an export namespace
+    expect(directives[0].element?.library?.exportNamespace, isNull);
+
+    // Resolve directives
+    var importCompleter = new Completer<List<ImportElement>>();
+    request.resolveImports().then((List<ImportElement> elements) {
+      importCompleter.complete(elements);
+    });
+    List<ImportElement> imports = await performAnalysis(200, importCompleter);
+    expect(imports, hasLength(directives.length + 1));
+
+    ImportElement importNamed(String expectedUri) {
+      return imports.firstWhere((elem) => elem.uri == expectedUri, orElse: () {
+        var importedNames = imports.map((elem) => elem.uri);
+        fail('Failed to find $expectedUri in $importedNames');
+      });
+    }
+    void assertImportedLib(String expectedUri) {
+      ImportElement importElem = importNamed(expectedUri);
+      expect(importElem.importedLibrary.exportNamespace, isNotNull);
+    }
+
+    // Assert that the new imports each have an export namespace
+    assertImportedLib(null /* dart:core */);
+    assertImportedLib('/libA.dart');
+  }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index 167e3ab..73642ea 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -7,7 +7,7 @@
 import 'package:analysis_server/plugin/protocol/protocol.dart';
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/keyword_contributor.dart';
-import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 import 'package:unittest/unittest.dart';
 
@@ -269,6 +269,11 @@
     }
   }
 
+  @override
+  DartCompletionContributor createContributor() {
+    return new KeywordContributor();
+  }
+
   fail_import_partial() async {
     addTestSource('imp^ import "package:foo/foo.dart"; import "bar.dart";');
     await computeSuggestions();
@@ -298,11 +303,6 @@
     assertNotSuggested('class');
   }
 
-  @override
-  DartCompletionContributor createContributor() {
-    return new KeywordContributor();
-  }
-
   test_after_class() async {
     addTestSource('class A {} ^');
     await computeSuggestions();
@@ -1238,13 +1238,6 @@
     assertSuggestKeywords(STMT_START_IN_CLASS, pseudoKeywords: ['await']);
   }
 
-  test_method_body_async_star() async {
-    addTestSource('class A { foo() async* {^}}');
-    await computeSuggestions();
-    assertSuggestKeywords(STMT_START_IN_CLASS,
-        pseudoKeywords: ['await', 'yield', 'yield*']);
-  }
-
   test_method_body_async2() async {
     addTestSource('class A { foo() async => ^}');
     await computeSuggestions();
@@ -1263,6 +1256,13 @@
     assertSuggestKeywords(EXPRESSION_START_INSTANCE, pseudoKeywords: ['await']);
   }
 
+  test_method_body_async_star() async {
+    addTestSource('class A { foo() async* {^}}');
+    await computeSuggestions();
+    assertSuggestKeywords(STMT_START_IN_CLASS,
+        pseudoKeywords: ['await', 'yield', 'yield*']);
+  }
+
   test_method_body_expression1() async {
     addTestSource('class A { foo() {return b == true ? ^}}');
     await computeSuggestions();
diff --git a/pkg/analysis_server/test/services/completion/dart/local_declaration_visitor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_declaration_visitor_test.dart
index f70f720f..5765c68 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_declaration_visitor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_declaration_visitor_test.dart
@@ -5,10 +5,12 @@
 library test.services.completion.local_declaration_visitor_test;
 
 import 'package:analysis_server/src/services/completion/dart/local_declaration_visitor.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 import 'package:unittest/unittest.dart';
 
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 c12f8de..b936392 100644
--- a/pkg/analysis_server/test/services/completion/dart/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/dart/test_all.dart
@@ -9,6 +9,7 @@
 import '../../../utils.dart';
 import 'arglist_contributor_test.dart' as arglist_test;
 import 'combinator_contributor_test.dart' as combinator_test;
+import 'completion_manager_test.dart' as completion_manager;
 import 'common_usage_sorter_test.dart' as common_usage_test;
 import 'field_formal_contributor_test.dart' as field_formal_contributor_test;
 import 'imported_reference_contributor_test.dart' as imported_ref_test;
@@ -34,6 +35,7 @@
   group('dart/completion', () {
     arglist_test.main();
     combinator_test.main();
+    completion_manager.main();
     common_usage_test.main();
     field_formal_contributor_test.main();
     imported_ref_test.main();
diff --git a/pkg/analysis_server/test/socket_server_test.dart b/pkg/analysis_server/test/socket_server_test.dart
index b4e9f46..1175320 100644
--- a/pkg/analysis_server/test/socket_server_test.dart
+++ b/pkg/analysis_server/test/socket_server_test.dart
@@ -12,6 +12,7 @@
 import 'package:analysis_server/src/plugin/server_plugin.dart';
 import 'package:analysis_server/src/socket_server.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
+import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/sdk_io.dart';
 import 'package:plugin/manager.dart';
 import 'package:unittest/unittest.dart';
@@ -111,9 +112,12 @@
     ServerPlugin serverPlugin = new ServerPlugin();
     ExtensionManager manager = new ExtensionManager();
     manager.processPlugins([serverPlugin]);
+    SdkCreator sdkCreator = () =>
+        new DirectoryBasedDartSdk(DirectoryBasedDartSdk.defaultSdkDirectory);
     return new SocketServer(
         new AnalysisServerOptions(),
-        DirectoryBasedDartSdk.defaultSdk,
+        sdkCreator,
+        sdkCreator(),
         InstrumentationService.NULL_SERVICE,
         serverPlugin,
         null,
diff --git a/pkg/analysis_server/test/stress/replay/replay.dart b/pkg/analysis_server/test/stress/replay/replay.dart
index 159944f..6c56047 100644
--- a/pkg/analysis_server/test/stress/replay/replay.dart
+++ b/pkg/analysis_server/test/stress/replay/replay.dart
@@ -11,9 +11,11 @@
 import 'dart:io';
 
 import 'package:analysis_server/plugin/protocol/protocol.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/error.dart' as error;
 import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/util/glob.dart';
 import 'package:args/args.dart';
diff --git a/pkg/analyzer/example/parser_driver.dart b/pkg/analyzer/example/parser_driver.dart
index 2e082b7..c302e41 100644
--- a/pkg/analyzer/example/parser_driver.dart
+++ b/pkg/analyzer/example/parser_driver.dart
@@ -7,9 +7,10 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 
 main(List<String> args) {
   print('working dir ${new File('.').resolveSymbolicLinksSync()}');
diff --git a/pkg/analyzer/example/scanner_driver.dart b/pkg/analyzer/example/scanner_driver.dart
index d403fab..d867f19 100644
--- a/pkg/analyzer/example/scanner_driver.dart
+++ b/pkg/analyzer/example/scanner_driver.dart
@@ -5,7 +5,9 @@
 
 import 'dart:io';
 
-import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 
 main(List<String> args) {
   print('working dir ${new File('.').resolveSymbolicLinksSync()}');
diff --git a/pkg/analyzer/lib/analyzer.dart b/pkg/analyzer/lib/analyzer.dart
index 78de42e..0ac8cf4 100644
--- a/pkg/analyzer/lib/analyzer.dart
+++ b/pkg/analyzer/lib/analyzer.dart
@@ -7,10 +7,11 @@
 import 'dart:io';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/error.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/string_source.dart';
 import 'package:path/path.dart' as pathos;
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 31dd785..598d611 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -36,13 +36,12 @@
  */
 library analyzer.dart.ast.ast;
 
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/element.dart' show AuxiliaryElements;
-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/source.dart' show LineInfo, Source;
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
@@ -537,7 +536,7 @@
    * (either AST nodes or tokens) that make up the contents of this node,
    * including doc comments but excluding other comments.
    */
-  Iterable/*<AstNode | Token>*/ get childEntities;
+  Iterable /*<AstNode | Token>*/ get childEntities;
 
   /**
    * Return the offset of the character immediately following the last character
@@ -592,7 +591,7 @@
    * Use the given [visitor] to visit this node. Return the value returned by
    * the visitor as a result of visiting this node.
    */
-  dynamic /* =E */ accept/*<E>*/(AstVisitor/*<E>*/ visitor);
+  dynamic /* =E */ accept /*<E>*/ (AstVisitor /*<E>*/ visitor);
 
   /**
    * Return the most immediate ancestor of this node for which the [predicate]
@@ -3781,6 +3780,32 @@
    * is no star.
    */
   Token get star;
+
+  /**
+   * If [variable] is a local variable or parameter declared anywhere within
+   * the top level function or method containing this [FunctionBody], return a
+   * boolean indicating whether [variable] is potentially mutated within a
+   * local function other than the function in which it is declared.
+   *
+   * If [variable] is not a local variable or parameter declared within the top
+   * level function or method containing this [FunctionBody], return `false`.
+   *
+   * Throws an exception if resolution has not yet been performed.
+   */
+  bool isPotentiallyMutatedInClosure(VariableElement variable);
+
+  /**
+   * If [variable] is a local variable or parameter declared anywhere within
+   * the top level function or method containing this [FunctionBody], return a
+   * boolean indicating whether [variable] is potentially mutated within the
+   * scope of its declaration.
+   *
+   * If [variable] is not a local variable or parameter declared within the top
+   * level function or method containing this [FunctionBody], return `false`.
+   *
+   * Throws an exception if resolution has not yet been performed.
+   */
+  bool isPotentiallyMutatedInScope(VariableElement variable);
 }
 
 /**
@@ -4500,10 +4525,10 @@
       return allShows1.length - allShows2.length;
     }
     // next ensure that the lists are equivalent
-    if (!javaCollectionContainsAll(allHides1, allHides2)) {
+    if (!allHides1.toSet().containsAll(allHides2)) {
       return -1;
     }
-    if (!javaCollectionContainsAll(allShows1, allShows2)) {
+    if (!allShows1.toSet().containsAll(allShows2)) {
       return -1;
     }
     return 0;
diff --git a/pkg/analyzer/lib/dart/ast/token.dart b/pkg/analyzer/lib/dart/ast/token.dart
new file mode 100644
index 0000000..6560a8e
--- /dev/null
+++ b/pkg/analyzer/lib/dart/ast/token.dart
@@ -0,0 +1,738 @@
+// 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.
+
+/**
+ * Defines the tokens that are produced by the scanner, used by the parser, and
+ * referenced from the [AST structure](ast.dart).
+ */
+library analyzer.dart.ast.token;
+
+import 'dart:collection';
+
+import 'package:analyzer/src/dart/ast/token.dart' show SimpleToken, TokenClass;
+
+/**
+ * The keywords in the Dart programming language.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class Keyword {
+  static const Keyword ABSTRACT = const Keyword._('ABSTRACT', "abstract", true);
+
+  static const Keyword AS = const Keyword._('AS', "as", true);
+
+  static const Keyword ASSERT = const Keyword._('ASSERT', "assert");
+
+  static const Keyword BREAK = const Keyword._('BREAK', "break");
+
+  static const Keyword CASE = const Keyword._('CASE', "case");
+
+  static const Keyword CATCH = const Keyword._('CATCH', "catch");
+
+  static const Keyword CLASS = const Keyword._('CLASS', "class");
+
+  static const Keyword CONST = const Keyword._('CONST', "const");
+
+  static const Keyword CONTINUE = const Keyword._('CONTINUE', "continue");
+
+  static const Keyword DEFAULT = const Keyword._('DEFAULT', "default");
+
+  static const Keyword DEFERRED = const Keyword._('DEFERRED', "deferred", true);
+
+  static const Keyword DO = const Keyword._('DO', "do");
+
+  static const Keyword DYNAMIC = const Keyword._('DYNAMIC', "dynamic", true);
+
+  static const Keyword ELSE = const Keyword._('ELSE', "else");
+
+  static const Keyword ENUM = const Keyword._('ENUM', "enum");
+
+  static const Keyword EXPORT = const Keyword._('EXPORT', "export", true);
+
+  static const Keyword EXTENDS = const Keyword._('EXTENDS', "extends");
+
+  static const Keyword EXTERNAL = const Keyword._('EXTERNAL', "external", true);
+
+  static const Keyword FACTORY = const Keyword._('FACTORY', "factory", true);
+
+  static const Keyword FALSE = const Keyword._('FALSE', "false");
+
+  static const Keyword FINAL = const Keyword._('FINAL', "final");
+
+  static const Keyword FINALLY = const Keyword._('FINALLY', "finally");
+
+  static const Keyword FOR = const Keyword._('FOR', "for");
+
+  static const Keyword GET = const Keyword._('GET', "get", true);
+
+  static const Keyword IF = const Keyword._('IF', "if");
+
+  static const Keyword IMPLEMENTS =
+      const Keyword._('IMPLEMENTS', "implements", true);
+
+  static const Keyword IMPORT = const Keyword._('IMPORT', "import", true);
+
+  static const Keyword IN = const Keyword._('IN', "in");
+
+  static const Keyword IS = const Keyword._('IS', "is");
+
+  static const Keyword LIBRARY = const Keyword._('LIBRARY', "library", true);
+
+  static const Keyword NEW = const Keyword._('NEW', "new");
+
+  static const Keyword NULL = const Keyword._('NULL', "null");
+
+  static const Keyword OPERATOR = const Keyword._('OPERATOR', "operator", true);
+
+  static const Keyword PART = const Keyword._('PART', "part", true);
+
+  static const Keyword RETHROW = const Keyword._('RETHROW', "rethrow");
+
+  static const Keyword RETURN = const Keyword._('RETURN', "return");
+
+  static const Keyword SET = const Keyword._('SET', "set", true);
+
+  static const Keyword STATIC = const Keyword._('STATIC', "static", true);
+
+  static const Keyword SUPER = const Keyword._('SUPER', "super");
+
+  static const Keyword SWITCH = const Keyword._('SWITCH', "switch");
+
+  static const Keyword THIS = const Keyword._('THIS', "this");
+
+  static const Keyword THROW = const Keyword._('THROW', "throw");
+
+  static const Keyword TRUE = const Keyword._('TRUE', "true");
+
+  static const Keyword TRY = const Keyword._('TRY', "try");
+
+  static const Keyword TYPEDEF = const Keyword._('TYPEDEF', "typedef", true);
+
+  static const Keyword VAR = const Keyword._('VAR', "var");
+
+  static const Keyword VOID = const Keyword._('VOID', "void");
+
+  static const Keyword WHILE = const Keyword._('WHILE', "while");
+
+  static const Keyword WITH = const Keyword._('WITH', "with");
+
+  static const List<Keyword> values = const <Keyword>[
+    ABSTRACT,
+    AS,
+    ASSERT,
+    BREAK,
+    CASE,
+    CATCH,
+    CLASS,
+    CONST,
+    CONTINUE,
+    DEFAULT,
+    DEFERRED,
+    DO,
+    DYNAMIC,
+    ELSE,
+    ENUM,
+    EXPORT,
+    EXTENDS,
+    EXTERNAL,
+    FACTORY,
+    FALSE,
+    FINAL,
+    FINALLY,
+    FOR,
+    GET,
+    IF,
+    IMPLEMENTS,
+    IMPORT,
+    IN,
+    IS,
+    LIBRARY,
+    NEW,
+    NULL,
+    OPERATOR,
+    PART,
+    RETHROW,
+    RETURN,
+    SET,
+    STATIC,
+    SUPER,
+    SWITCH,
+    THIS,
+    THROW,
+    TRUE,
+    TRY,
+    TYPEDEF,
+    VAR,
+    VOID,
+    WHILE,
+    WITH,
+  ];
+
+  /**
+   * A table mapping the lexemes of keywords to the corresponding keyword.
+   */
+  static final Map<String, Keyword> keywords = _createKeywordMap();
+
+  /**
+   * The name of the keyword type.
+   */
+  final String name;
+
+  /**
+   * The lexeme for the keyword.
+   */
+  final String syntax;
+
+  /**
+   * A flag indicating whether the keyword is a pseudo-keyword. Pseudo keywords
+   * can be used as identifiers.
+   */
+  final bool isPseudoKeyword;
+
+  /**
+   * Initialize a newly created keyword to have the given [name] and [syntax].
+   * The keyword is a pseudo-keyword if the [isPseudoKeyword] flag is `true`.
+   */
+  const Keyword._(this.name, this.syntax, [this.isPseudoKeyword = false]);
+
+  @override
+  String toString() => name;
+
+  /**
+   * Create a table mapping the lexemes of keywords to the corresponding keyword
+   * and return the table that was created.
+   */
+  static Map<String, Keyword> _createKeywordMap() {
+    LinkedHashMap<String, Keyword> result =
+        new LinkedHashMap<String, Keyword>();
+    for (Keyword keyword in values) {
+      result[keyword.syntax] = keyword;
+    }
+    return result;
+  }
+}
+
+/**
+ * A token that was scanned from the input. Each token knows which tokens
+ * precede and follow it, acting as a link in a doubly linked list of tokens.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class Token {
+  /**
+   * Initialize a newly created token to have the given [type] and [offset].
+   */
+  factory Token(TokenType type, int offset) = SimpleToken;
+
+  /**
+   * Return the offset from the beginning of the file to the character after the
+   * last character of the token.
+   */
+  int get end;
+
+  /**
+   * Return `true` if this token represents an operator.
+   */
+  bool get isOperator;
+
+  /**
+   * Return `true` if this token is a synthetic token. A synthetic token is a
+   * token that was introduced by the parser in order to recover from an error
+   * in the code.
+   */
+  bool get isSynthetic;
+
+  /**
+   * Return `true` if this token represents an operator that can be defined by
+   * users.
+   */
+  bool get isUserDefinableOperator;
+
+  /**
+   * Return the number of characters in the node's source range.
+   */
+  int get length;
+
+  /**
+   * Return the lexeme that represents this token.
+   */
+  String get lexeme;
+
+  /**
+   * Return the next token in the token stream.
+   */
+  Token get next;
+
+  /**
+   * Return the offset from the beginning of the file to the first character in
+   * the token.
+   */
+  int get offset;
+
+  /**
+   * Set the offset from the beginning of the file to the first character in
+   * the token to the given [offset].
+   */
+  void set offset(int offset);
+
+  /**
+   * Return the first comment in the list of comments that precede this token,
+   * or `null` if there are no comments preceding this token. Additional
+   * comments can be reached by following the token stream using [next] until
+   * `null` is returned.
+   *
+   * For example, if the original contents were `/* one */ /* two */ id`, then
+   * the first preceding comment token will have a lexeme of `/* one */` and
+   * the next comment token will have a lexeme of `/* two */`.
+   */
+  Token get precedingComments;
+
+  /**
+   * Return the previous token in the token stream.
+   */
+  Token get previous;
+
+  /**
+   * Set the previous token in the token stream to the given [token].
+   */
+  void set previous(Token token);
+
+  /**
+   * Return the type of the token.
+   */
+  TokenType get type;
+
+  /**
+   * Apply (add) the given [delta] to this token's offset.
+   */
+  void applyDelta(int delta);
+
+  /**
+   * Return a newly created token that is a copy of this token but that is not a
+   * part of any token stream.
+   */
+  Token copy();
+
+  /**
+   * Copy a linked list of comment tokens identical to the given comment tokens.
+   */
+  Token copyComments(Token token);
+
+  /**
+   * Return `true` if this token has any one of the given [types].
+   */
+  bool matchesAny(List<TokenType> types);
+
+  /**
+   * Set the next token in the token stream to the given [token]. This has the
+   * side-effect of setting this token to be the previous token for the given
+   * token. Return the token that was passed in.
+   */
+  Token setNext(Token token);
+
+  /**
+   * Set the next token in the token stream to the given token without changing
+   * which token is the previous token for the given token. Return the token
+   * that was passed in.
+   */
+  Token setNextWithoutSettingPrevious(Token token);
+
+  /**
+   * Return the value of this token. For keyword tokens, this is the keyword
+   * associated with the token, for other tokens it is the lexeme associated
+   * with the token.
+   */
+  Object value();
+
+  /**
+   * Compare the given [tokens] to find the token that appears first in the
+   * source being parsed. That is, return the left-most of all of the tokens.
+   * The list must be non-`null`, but the elements of the list are allowed to be
+   * `null`. Return the token with the smallest offset, or `null` if the list is
+   * empty or if all of the elements of the list are `null`.
+   */
+  static Token lexicallyFirst(List<Token> tokens) {
+    Token first = null;
+    int offset = -1;
+    for (Token token in tokens) {
+      if (token != null && (offset < 0 || token.offset < offset)) {
+        first = token;
+        offset = token.offset;
+      }
+    }
+    return first;
+  }
+}
+
+/**
+ * The types of tokens that can be returned by the scanner.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class TokenType {
+  /**
+   * The type of the token that marks the start or end of the input.
+   */
+  static const TokenType EOF = const _EndOfFileTokenType();
+
+  static const TokenType DOUBLE = const TokenType._('DOUBLE');
+
+  static const TokenType HEXADECIMAL = const TokenType._('HEXADECIMAL');
+
+  static const TokenType IDENTIFIER = const TokenType._('IDENTIFIER');
+
+  static const TokenType INT = const TokenType._('INT');
+
+  static const TokenType KEYWORD = const TokenType._('KEYWORD');
+
+  static const TokenType MULTI_LINE_COMMENT =
+      const TokenType._('MULTI_LINE_COMMENT');
+
+  static const TokenType SCRIPT_TAG = const TokenType._('SCRIPT_TAG');
+
+  static const TokenType SINGLE_LINE_COMMENT =
+      const TokenType._('SINGLE_LINE_COMMENT');
+
+  static const TokenType STRING = const TokenType._('STRING');
+
+  static const TokenType AMPERSAND =
+      const TokenType._('AMPERSAND', TokenClass.BITWISE_AND_OPERATOR, '&');
+
+  static const TokenType AMPERSAND_AMPERSAND = const TokenType._(
+      'AMPERSAND_AMPERSAND', TokenClass.LOGICAL_AND_OPERATOR, '&&');
+
+  static const TokenType AMPERSAND_EQ =
+      const TokenType._('AMPERSAND_EQ', TokenClass.ASSIGNMENT_OPERATOR, '&=');
+
+  static const TokenType AT = const TokenType._('AT', TokenClass.NO_CLASS, '@');
+
+  static const TokenType BANG =
+      const TokenType._('BANG', TokenClass.UNARY_PREFIX_OPERATOR, '!');
+
+  static const TokenType BANG_EQ =
+      const TokenType._('BANG_EQ', TokenClass.EQUALITY_OPERATOR, '!=');
+
+  static const TokenType BAR =
+      const TokenType._('BAR', TokenClass.BITWISE_OR_OPERATOR, '|');
+
+  static const TokenType BAR_BAR =
+      const TokenType._('BAR_BAR', TokenClass.LOGICAL_OR_OPERATOR, '||');
+
+  static const TokenType BAR_EQ =
+      const TokenType._('BAR_EQ', TokenClass.ASSIGNMENT_OPERATOR, '|=');
+
+  static const TokenType COLON =
+      const TokenType._('COLON', TokenClass.NO_CLASS, ':');
+
+  static const TokenType COMMA =
+      const TokenType._('COMMA', TokenClass.NO_CLASS, ',');
+
+  static const TokenType CARET =
+      const TokenType._('CARET', TokenClass.BITWISE_XOR_OPERATOR, '^');
+
+  static const TokenType CARET_EQ =
+      const TokenType._('CARET_EQ', TokenClass.ASSIGNMENT_OPERATOR, '^=');
+
+  static const TokenType CLOSE_CURLY_BRACKET =
+      const TokenType._('CLOSE_CURLY_BRACKET', TokenClass.NO_CLASS, '}');
+
+  static const TokenType CLOSE_PAREN =
+      const TokenType._('CLOSE_PAREN', TokenClass.NO_CLASS, ')');
+
+  static const TokenType CLOSE_SQUARE_BRACKET =
+      const TokenType._('CLOSE_SQUARE_BRACKET', TokenClass.NO_CLASS, ']');
+
+  static const TokenType EQ =
+      const TokenType._('EQ', TokenClass.ASSIGNMENT_OPERATOR, '=');
+
+  static const TokenType EQ_EQ =
+      const TokenType._('EQ_EQ', TokenClass.EQUALITY_OPERATOR, '==');
+
+  static const TokenType FUNCTION =
+      const TokenType._('FUNCTION', TokenClass.NO_CLASS, '=>');
+
+  static const TokenType GT =
+      const TokenType._('GT', TokenClass.RELATIONAL_OPERATOR, '>');
+
+  static const TokenType GT_EQ =
+      const TokenType._('GT_EQ', TokenClass.RELATIONAL_OPERATOR, '>=');
+
+  static const TokenType GT_GT =
+      const TokenType._('GT_GT', TokenClass.SHIFT_OPERATOR, '>>');
+
+  static const TokenType GT_GT_EQ =
+      const TokenType._('GT_GT_EQ', TokenClass.ASSIGNMENT_OPERATOR, '>>=');
+
+  static const TokenType HASH =
+      const TokenType._('HASH', TokenClass.NO_CLASS, '#');
+
+  static const TokenType INDEX =
+      const TokenType._('INDEX', TokenClass.UNARY_POSTFIX_OPERATOR, '[]');
+
+  static const TokenType INDEX_EQ =
+      const TokenType._('INDEX_EQ', TokenClass.UNARY_POSTFIX_OPERATOR, '[]=');
+
+  static const TokenType IS =
+      const TokenType._('IS', TokenClass.RELATIONAL_OPERATOR, 'is');
+
+  static const TokenType LT =
+      const TokenType._('LT', TokenClass.RELATIONAL_OPERATOR, '<');
+
+  static const TokenType LT_EQ =
+      const TokenType._('LT_EQ', TokenClass.RELATIONAL_OPERATOR, '<=');
+
+  static const TokenType LT_LT =
+      const TokenType._('LT_LT', TokenClass.SHIFT_OPERATOR, '<<');
+
+  static const TokenType LT_LT_EQ =
+      const TokenType._('LT_LT_EQ', TokenClass.ASSIGNMENT_OPERATOR, '<<=');
+
+  static const TokenType MINUS =
+      const TokenType._('MINUS', TokenClass.ADDITIVE_OPERATOR, '-');
+
+  static const TokenType MINUS_EQ =
+      const TokenType._('MINUS_EQ', TokenClass.ASSIGNMENT_OPERATOR, '-=');
+
+  static const TokenType MINUS_MINUS =
+      const TokenType._('MINUS_MINUS', TokenClass.UNARY_PREFIX_OPERATOR, '--');
+
+  static const TokenType OPEN_CURLY_BRACKET =
+      const TokenType._('OPEN_CURLY_BRACKET', TokenClass.NO_CLASS, '{');
+
+  static const TokenType OPEN_PAREN =
+      const TokenType._('OPEN_PAREN', TokenClass.UNARY_POSTFIX_OPERATOR, '(');
+
+  static const TokenType OPEN_SQUARE_BRACKET = const TokenType._(
+      'OPEN_SQUARE_BRACKET', TokenClass.UNARY_POSTFIX_OPERATOR, '[');
+
+  static const TokenType PERCENT =
+      const TokenType._('PERCENT', TokenClass.MULTIPLICATIVE_OPERATOR, '%');
+
+  static const TokenType PERCENT_EQ =
+      const TokenType._('PERCENT_EQ', TokenClass.ASSIGNMENT_OPERATOR, '%=');
+
+  static const TokenType PERIOD =
+      const TokenType._('PERIOD', TokenClass.UNARY_POSTFIX_OPERATOR, '.');
+
+  static const TokenType PERIOD_PERIOD =
+      const TokenType._('PERIOD_PERIOD', TokenClass.CASCADE_OPERATOR, '..');
+
+  static const TokenType PLUS =
+      const TokenType._('PLUS', TokenClass.ADDITIVE_OPERATOR, '+');
+
+  static const TokenType PLUS_EQ =
+      const TokenType._('PLUS_EQ', TokenClass.ASSIGNMENT_OPERATOR, '+=');
+
+  static const TokenType PLUS_PLUS =
+      const TokenType._('PLUS_PLUS', TokenClass.UNARY_PREFIX_OPERATOR, '++');
+
+  static const TokenType QUESTION =
+      const TokenType._('QUESTION', TokenClass.CONDITIONAL_OPERATOR, '?');
+
+  static const TokenType QUESTION_PERIOD = const TokenType._(
+      'QUESTION_PERIOD', TokenClass.UNARY_POSTFIX_OPERATOR, '?.');
+
+  static const TokenType QUESTION_QUESTION =
+      const TokenType._('QUESTION_QUESTION', TokenClass.IF_NULL_OPERATOR, '??');
+
+  static const TokenType QUESTION_QUESTION_EQ = const TokenType._(
+      'QUESTION_QUESTION_EQ', TokenClass.ASSIGNMENT_OPERATOR, '??=');
+
+  static const TokenType SEMICOLON =
+      const TokenType._('SEMICOLON', TokenClass.NO_CLASS, ';');
+
+  static const TokenType SLASH =
+      const TokenType._('SLASH', TokenClass.MULTIPLICATIVE_OPERATOR, '/');
+
+  static const TokenType SLASH_EQ =
+      const TokenType._('SLASH_EQ', TokenClass.ASSIGNMENT_OPERATOR, '/=');
+
+  static const TokenType STAR =
+      const TokenType._('STAR', TokenClass.MULTIPLICATIVE_OPERATOR, '*');
+
+  static const TokenType STAR_EQ =
+      const TokenType._('STAR_EQ', TokenClass.ASSIGNMENT_OPERATOR, "*=");
+
+  static const TokenType STRING_INTERPOLATION_EXPRESSION = const TokenType._(
+      'STRING_INTERPOLATION_EXPRESSION', TokenClass.NO_CLASS, '\${');
+
+  static const TokenType STRING_INTERPOLATION_IDENTIFIER = const TokenType._(
+      'STRING_INTERPOLATION_IDENTIFIER', TokenClass.NO_CLASS, '\$');
+
+  static const TokenType TILDE =
+      const TokenType._('TILDE', TokenClass.UNARY_PREFIX_OPERATOR, '~');
+
+  static const TokenType TILDE_SLASH = const TokenType._(
+      'TILDE_SLASH', TokenClass.MULTIPLICATIVE_OPERATOR, '~/');
+
+  static const TokenType TILDE_SLASH_EQ = const TokenType._(
+      'TILDE_SLASH_EQ', TokenClass.ASSIGNMENT_OPERATOR, '~/=');
+
+  static const TokenType BACKPING =
+      const TokenType._('BACKPING', TokenClass.NO_CLASS, '`');
+
+  static const TokenType BACKSLASH =
+      const TokenType._('BACKSLASH', TokenClass.NO_CLASS, '\\');
+
+  static const TokenType PERIOD_PERIOD_PERIOD =
+      const TokenType._('PERIOD_PERIOD_PERIOD', TokenClass.NO_CLASS, '...');
+
+  static const TokenType GENERIC_METHOD_TYPE_LIST =
+      const TokenType._('GENERIC_METHOD_TYPE_LIST');
+
+  static const TokenType GENERIC_METHOD_TYPE_ASSIGN =
+      const TokenType._('GENERIC_METHOD_TYPE_ASSIGN');
+
+  /**
+   * The class of the token.
+   */
+  final TokenClass _tokenClass;
+
+  /**
+   * The name of the token type.
+   */
+  final String name;
+
+  /**
+   * The lexeme that defines this type of token, or `null` if there is more than
+   * one possible lexeme for this type of token.
+   */
+  final String lexeme;
+
+  /**
+   * Initialize a newly created token type to have the given [name],
+   * [_tokenClass] and [lexeme].
+   */
+  const TokenType._(this.name,
+      [this._tokenClass = TokenClass.NO_CLASS, this.lexeme = null]);
+
+  /**
+   * Return `true` if this type of token represents an additive operator.
+   */
+  bool get isAdditiveOperator => _tokenClass == TokenClass.ADDITIVE_OPERATOR;
+
+  /**
+   * Return `true` if this type of token represents an assignment operator.
+   */
+  bool get isAssignmentOperator =>
+      _tokenClass == TokenClass.ASSIGNMENT_OPERATOR;
+
+  /**
+   * Return `true` if this type of token represents an associative operator. An
+   * associative operator is an operator for which the following equality is
+   * true: `(a * b) * c == a * (b * c)`. In other words, if the result of
+   * applying the operator to multiple operands does not depend on the order in
+   * which those applications occur.
+   *
+   * Note: This method considers the logical-and and logical-or operators to be
+   * associative, even though the order in which the application of those
+   * operators can have an effect because evaluation of the right-hand operand
+   * is conditional.
+   */
+  bool get isAssociativeOperator =>
+      this == AMPERSAND ||
+      this == AMPERSAND_AMPERSAND ||
+      this == BAR ||
+      this == BAR_BAR ||
+      this == CARET ||
+      this == PLUS ||
+      this == STAR;
+
+  /**
+   * Return `true` if this type of token represents an equality operator.
+   */
+  bool get isEqualityOperator => _tokenClass == TokenClass.EQUALITY_OPERATOR;
+
+  /**
+   * Return `true` if this type of token represents an increment operator.
+   */
+  bool get isIncrementOperator =>
+      identical(lexeme, '++') || identical(lexeme, '--');
+
+  /**
+   * Return `true` if this type of token represents a multiplicative operator.
+   */
+  bool get isMultiplicativeOperator =>
+      _tokenClass == TokenClass.MULTIPLICATIVE_OPERATOR;
+
+  /**
+   * Return `true` if this token type represents an operator.
+   */
+  bool get isOperator =>
+      _tokenClass != TokenClass.NO_CLASS &&
+      this != OPEN_PAREN &&
+      this != OPEN_SQUARE_BRACKET &&
+      this != PERIOD;
+
+  /**
+   * Return `true` if this type of token represents a relational operator.
+   */
+  bool get isRelationalOperator =>
+      _tokenClass == TokenClass.RELATIONAL_OPERATOR;
+
+  /**
+   * Return `true` if this type of token represents a shift operator.
+   */
+  bool get isShiftOperator => _tokenClass == TokenClass.SHIFT_OPERATOR;
+
+  /**
+   * Return `true` if this type of token represents a unary postfix operator.
+   */
+  bool get isUnaryPostfixOperator =>
+      _tokenClass == TokenClass.UNARY_POSTFIX_OPERATOR;
+
+  /**
+   * Return `true` if this type of token represents a unary prefix operator.
+   */
+  bool get isUnaryPrefixOperator =>
+      _tokenClass == TokenClass.UNARY_PREFIX_OPERATOR;
+
+  /**
+   * Return `true` if this token type represents an operator that can be defined
+   * by users.
+   */
+  bool get isUserDefinableOperator =>
+      identical(lexeme, '==') ||
+      identical(lexeme, '~') ||
+      identical(lexeme, '[]') ||
+      identical(lexeme, '[]=') ||
+      identical(lexeme, '*') ||
+      identical(lexeme, '/') ||
+      identical(lexeme, '%') ||
+      identical(lexeme, '~/') ||
+      identical(lexeme, '+') ||
+      identical(lexeme, '-') ||
+      identical(lexeme, '<<') ||
+      identical(lexeme, '>>') ||
+      identical(lexeme, '>=') ||
+      identical(lexeme, '>') ||
+      identical(lexeme, '<=') ||
+      identical(lexeme, '<') ||
+      identical(lexeme, '&') ||
+      identical(lexeme, '^') ||
+      identical(lexeme, '|');
+
+  /**
+   * Return the precedence of the token, or `0` if the token does not represent
+   * an operator.
+   */
+  int get precedence => _tokenClass.precedence;
+
+  @override
+  String toString() => name;
+}
+
+/**
+ * A token representing the end (either the head or the tail) of a stream of
+ * tokens.
+ */
+class _EndOfFileTokenType extends TokenType {
+  /**
+   * Initialize a newly created token.
+   */
+  const _EndOfFileTokenType() : super._('EOF', TokenClass.NO_CLASS, '');
+
+  @override
+  String toString() => '-eof-';
+}
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index c7e971a..370f53e 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1464,14 +1464,12 @@
    * which the name of this element is visible, or `null` if there is no single
    * range of characters within which the element name is visible.
    *
-   * * For a local variable, this includes everything from the end of the
-   *   variable's initializer to the end of the block that encloses the variable
-   *   declaration.
+   * * For a local variable, this is the source range of the block that
+   *   encloses the variable declaration.
    * * For a parameter, this includes the body of the method or function that
    *   declares the parameter.
-   * * For a local function, this includes everything from the beginning of the
-   *   function's body to the end of the block that encloses the function
-   *   declaration.
+   * * For a local function, this is the source range of the block that
+   *   encloses the variable declaration.
    * * For top-level functions, `null` will be returned because they are
    *   potentially visible in multiple sources.
    */
@@ -1621,9 +1619,13 @@
   LibraryElement get enclosingElement;
 
   /**
-   * Return a list containing all of the libraries that are imported using this
-   * prefix.
+   * Return the empty list.
+   *
+   * Deprecated: this getter was intended to return a list containing all of
+   * the libraries that are imported using this prefix, but it was never
+   * implemented.  Due to lack of demand, it is being removed.
    */
+  @deprecated
   List<LibraryElement> get importedLibraries;
 }
 
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index f49c170..3ff2ce8 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -150,6 +150,15 @@
    */
   DartType substitute2(
       List<DartType> argumentTypes, List<DartType> parameterTypes);
+
+  /**
+   * If this type is a [TypeParameterType], returns its bound if it has one, or
+   * [objectType] otherwise.
+   *
+   * For any other type, returns `this`. Applies recursively -- if the bound is
+   * itself a type parameter, that is resolved too.
+   */
+  DartType resolveToBound(DartType objectType);
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index d0d131d..e931197 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -1497,6 +1497,31 @@
   }
 
   /**
+   * Return a [CompilationUnit] for the given library and unit sources, which
+   * can be incrementally resolved.
+   */
+  CompilationUnit _getIncrementallyResolvableUnit(
+      Source librarySource, Source unitSource) {
+    LibrarySpecificUnit target =
+        new LibrarySpecificUnit(librarySource, unitSource);
+    for (ResultDescriptor result in [
+      RESOLVED_UNIT,
+      RESOLVED_UNIT11,
+      RESOLVED_UNIT10,
+      RESOLVED_UNIT9,
+      RESOLVED_UNIT8,
+      RESOLVED_UNIT7,
+      RESOLVED_UNIT6
+    ]) {
+      CompilationUnit unit = getResult(target, result);
+      if (unit != null) {
+        return unit;
+      }
+    }
+    return null;
+  }
+
+  /**
    * Return a list containing all of the sources known to this context that have
    * the given [kind].
    */
@@ -1843,7 +1868,7 @@
       incrementalResolutionValidation_lastUnitSource = null;
       incrementalResolutionValidation_lastLibrarySource = null;
       incrementalResolutionValidation_lastUnit = null;
-      // prepare the entry
+      // prepare the source entry
       CacheEntry sourceEntry = _cache.get(unitSource);
       if (sourceEntry == null) {
         return false;
@@ -1854,19 +1879,15 @@
         return false;
       }
       Source librarySource = librarySources[0];
+      // prepare the unit entry
       CacheEntry unitEntry =
           _cache.get(new LibrarySpecificUnit(librarySource, unitSource));
       if (unitEntry == null) {
         return false;
       }
-      // prepare the library element
-      LibraryElement libraryElement = getLibraryElement(librarySource);
-      if (libraryElement == null) {
-        return false;
-      }
       // prepare the existing unit
       CompilationUnit oldUnit =
-          getResolvedCompilationUnit2(unitSource, librarySource);
+          _getIncrementallyResolvableUnit(librarySource, unitSource);
       if (oldUnit == null) {
         return false;
       }
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 342d4a6..4a9826e 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -7,8 +7,10 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/token.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';
@@ -16,7 +18,6 @@
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 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_dart.dart';
 
@@ -4721,6 +4722,13 @@
  */
 abstract class FunctionBodyImpl extends AstNodeImpl implements FunctionBody {
   /**
+   * Additional information about local variables and parameters that are
+   * declared within this function body or any enclosing function body.  `null`
+   * if resolution has not yet been performed.
+   */
+  LocalVariableInfo localVariableInfo;
+
+  /**
    * Return `true` if this function body is asynchronous.
    */
   bool get isAsynchronous => false;
@@ -4746,6 +4754,22 @@
    * is no star.
    */
   Token get star => null;
+
+  @override
+  bool isPotentiallyMutatedInClosure(VariableElement variable) {
+    if (localVariableInfo == null) {
+      throw new StateError('Resolution has not yet been performed');
+    }
+    return localVariableInfo.potentiallyMutatedInClosure.contains(variable);
+  }
+
+  @override
+  bool isPotentiallyMutatedInScope(VariableElement variable) {
+    if (localVariableInfo == null) {
+      throw new StateError('Resolution has not yet been performed');
+    }
+    return localVariableInfo.potentiallyMutatedInScope.contains(variable);
+  }
 }
 
 /**
@@ -6556,6 +6580,26 @@
 }
 
 /**
+ * Additional information about local variables within a function or method
+ * produced at resolution time.
+ */
+class LocalVariableInfo {
+  /**
+   * The set of local variables and parameters that are potentially mutated
+   * within a local function other than the function in which they are declared.
+   */
+  final Set<VariableElement> potentiallyMutatedInClosure =
+      new Set<VariableElement>();
+
+  /**
+   * The set of local variables and parameters that are potentiall mutated
+   * within the scope of their declarations.
+   */
+  final Set<VariableElement> potentiallyMutatedInScope =
+      new Set<VariableElement>();
+}
+
+/**
  * A single key/value pair in a map literal.
  *
  * > mapLiteralEntry ::=
diff --git a/pkg/analyzer/lib/src/dart/ast/token.dart b/pkg/analyzer/lib/src/dart/ast/token.dart
new file mode 100644
index 0000000..607df7b
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/ast/token.dart
@@ -0,0 +1,554 @@
+// 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.dart.ast.token;
+
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
+
+/**
+ * The opening half of a grouping pair of tokens. This is used for curly
+ * brackets ('{'), parentheses ('('), and square brackets ('[').
+ */
+class BeginToken extends SimpleToken {
+  /**
+   * The token that corresponds to this token.
+   */
+  Token endToken;
+
+  /**
+   * Initialize a newly created token to have the given [type] at the given
+   * [offset].
+   */
+  BeginToken(TokenType type, int offset) : super(type, offset) {
+    assert(type == TokenType.OPEN_CURLY_BRACKET ||
+        type == TokenType.OPEN_PAREN ||
+        type == TokenType.OPEN_SQUARE_BRACKET ||
+        type == TokenType.STRING_INTERPOLATION_EXPRESSION);
+  }
+
+  @override
+  Token copy() => new BeginToken(type, offset);
+}
+
+/**
+ * A begin token that is preceded by comments.
+ */
+class BeginTokenWithComment extends BeginToken {
+  /**
+   * The first comment in the list of comments that precede this token.
+   */
+  CommentToken _precedingComment;
+
+  /**
+   * Initialize a newly created token to have the given [type] at the given
+   * [offset] and to be preceded by the comments reachable from the given
+   * [comment].
+   */
+  BeginTokenWithComment(TokenType type, int offset, this._precedingComment)
+      : super(type, offset) {
+    _setCommentParent(_precedingComment);
+  }
+
+  @override
+  CommentToken get precedingComments => _precedingComment;
+
+  void set precedingComments(CommentToken comment) {
+    _precedingComment = comment;
+    _setCommentParent(_precedingComment);
+  }
+
+  @override
+  void applyDelta(int delta) {
+    super.applyDelta(delta);
+    Token token = precedingComments;
+    while (token != null) {
+      token.applyDelta(delta);
+      token = token.next;
+    }
+  }
+
+  @override
+  Token copy() =>
+      new BeginTokenWithComment(type, offset, copyComments(precedingComments));
+}
+
+/**
+ * A token representing a comment.
+ */
+class CommentToken extends StringToken {
+  /**
+   * The [Token] that contains this comment.
+   */
+  Token parent;
+
+  /**
+   * Initialize a newly created token to represent a token of the given [type]
+   * with the given [value] at the given [offset].
+   */
+  CommentToken(TokenType type, String value, int offset)
+      : super(type, value, offset);
+
+  @override
+  CommentToken copy() => new CommentToken(type, _value, offset);
+}
+
+/**
+ * A documentation comment token.
+ */
+class DocumentationCommentToken extends CommentToken {
+  /**
+   * The references embedded within the documentation comment.
+   * This list will be empty unless this is a documentation comment that has
+   * references embedded within it.
+   */
+  final List<Token> references = <Token>[];
+
+  /**
+   * Initialize a newly created token to represent a token of the given [type]
+   * with the given [value] at the given [offset].
+   */
+  DocumentationCommentToken(TokenType type, String value, int offset)
+      : super(type, value, offset);
+
+  @override
+  CommentToken copy() {
+    DocumentationCommentToken copy =
+        new DocumentationCommentToken(type, _value, offset);
+    references.forEach((ref) => copy.references.add(ref.copy()));
+    return copy;
+  }
+}
+
+/**
+ * A token representing a keyword in the language.
+ */
+class KeywordToken extends SimpleToken {
+  /**
+   * The keyword being represented by this token.
+   */
+  final Keyword keyword;
+
+  /**
+   * Initialize a newly created token to represent the given [keyword] at the
+   * given [offset].
+   */
+  KeywordToken(this.keyword, int offset) : super(TokenType.KEYWORD, offset);
+
+  @override
+  String get lexeme => keyword.syntax;
+
+  @override
+  Token copy() => new KeywordToken(keyword, offset);
+
+  @override
+  Keyword value() => keyword;
+}
+
+/**
+ * A keyword token that is preceded by comments.
+ */
+class KeywordTokenWithComment extends KeywordToken {
+  /**
+   * The first comment in the list of comments that precede this token.
+   */
+  CommentToken _precedingComment;
+
+  /**
+   * Initialize a newly created token to to represent the given [keyword] at the
+   * given [offset] and to be preceded by the comments reachable from the given
+   * [comment].
+   */
+  KeywordTokenWithComment(Keyword keyword, int offset, this._precedingComment)
+      : super(keyword, offset) {
+    _setCommentParent(_precedingComment);
+  }
+
+  @override
+  CommentToken get precedingComments => _precedingComment;
+
+  void set precedingComments(CommentToken comment) {
+    _precedingComment = comment;
+    _setCommentParent(_precedingComment);
+  }
+
+  @override
+  void applyDelta(int delta) {
+    super.applyDelta(delta);
+    Token token = precedingComments;
+    while (token != null) {
+      token.applyDelta(delta);
+      token = token.next;
+    }
+  }
+
+  @override
+  Token copy() => new KeywordTokenWithComment(
+      keyword, offset, copyComments(precedingComments));
+}
+
+/**
+ * A token that was scanned from the input. Each token knows which tokens
+ * precede and follow it, acting as a link in a doubly linked list of tokens.
+ */
+class SimpleToken implements Token {
+  /**
+   * The type of the token.
+   */
+  @override
+  final TokenType type;
+
+  /**
+   * The offset from the beginning of the file to the first character in the
+   * token.
+   */
+  @override
+  int offset = 0;
+
+  /**
+   * The previous token in the token stream.
+   */
+  @override
+  Token previous;
+
+  /**
+   * The next token in the token stream.
+   */
+  Token _next;
+
+  /**
+   * Initialize a newly created token to have the given [type] and [offset].
+   */
+  SimpleToken(this.type, this.offset);
+
+  @override
+  int get end => offset + length;
+
+  @override
+  bool get isOperator => type.isOperator;
+
+  @override
+  bool get isSynthetic => length == 0;
+
+  @override
+  bool get isUserDefinableOperator => type.isUserDefinableOperator;
+
+  @override
+  int get length => lexeme.length;
+
+  @override
+  String get lexeme => type.lexeme;
+
+  @override
+  Token get next => _next;
+
+  @override
+  CommentToken get precedingComments => null;
+
+  @override
+  void applyDelta(int delta) {
+    offset += delta;
+  }
+
+  @override
+  Token copy() => new Token(type, offset);
+
+  @override
+  Token copyComments(Token token) {
+    if (token == null) {
+      return null;
+    }
+    Token head = token.copy();
+    Token tail = head;
+    token = token.next;
+    while (token != null) {
+      tail = tail.setNext(token.copy());
+      token = token.next;
+    }
+    return head;
+  }
+
+  @override
+  bool matchesAny(List<TokenType> types) {
+    for (TokenType type in types) {
+      if (this.type == type) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @override
+  Token setNext(Token token) {
+    _next = token;
+    token.previous = this;
+    return token;
+  }
+
+  @override
+  Token setNextWithoutSettingPrevious(Token token) {
+    _next = token;
+    return token;
+  }
+
+  @override
+  String toString() => lexeme;
+
+  @override
+  Object value() => type.lexeme;
+
+  /**
+   * Sets the `parent` property to `this` for the given [comment] and all the
+   * next tokens.
+   */
+  void _setCommentParent(CommentToken comment) {
+    while (comment != null) {
+      comment.parent = this;
+      comment = comment.next;
+    }
+  }
+}
+
+/**
+ * A token whose value is independent of it's type.
+ */
+class StringToken extends SimpleToken {
+  /**
+   * The lexeme represented by this token.
+   */
+  String _value;
+
+  /**
+   * Initialize a newly created token to represent a token of the given [type]
+   * with the given [value] at the given [offset].
+   */
+  StringToken(TokenType type, String value, int offset) : super(type, offset) {
+    this._value = StringUtilities.intern(value);
+  }
+
+  @override
+  String get lexeme => _value;
+
+  @override
+  Token copy() => new StringToken(type, _value, offset);
+
+  @override
+  String value() => _value;
+}
+
+/**
+ * A string token that is preceded by comments.
+ */
+class StringTokenWithComment extends StringToken {
+  /**
+   * The first comment in the list of comments that precede this token.
+   */
+  CommentToken _precedingComment;
+
+  /**
+   * Initialize a newly created token to have the given [type] at the given
+   * [offset] and to be preceded by the comments reachable from the given
+   * [comment].
+   */
+  StringTokenWithComment(
+      TokenType type, String value, int offset, this._precedingComment)
+      : super(type, value, offset) {
+    _setCommentParent(_precedingComment);
+  }
+
+  @override
+  CommentToken get precedingComments => _precedingComment;
+
+  void set precedingComments(CommentToken comment) {
+    _precedingComment = comment;
+    _setCommentParent(_precedingComment);
+  }
+
+  @override
+  void applyDelta(int delta) {
+    super.applyDelta(delta);
+    Token token = precedingComments;
+    while (token != null) {
+      token.applyDelta(delta);
+      token = token.next;
+    }
+  }
+
+  @override
+  Token copy() => new StringTokenWithComment(
+      type, lexeme, offset, copyComments(precedingComments));
+}
+
+/**
+ * A token whose value is independent of it's type.
+ */
+class SyntheticStringToken extends StringToken {
+  /**
+   * Initialize a newly created token to represent a token of the given [type]
+   * with the given [value] at the given [offset].
+   */
+  SyntheticStringToken(TokenType type, String value, int offset)
+      : super(type, value, offset);
+
+  @override
+  bool get isSynthetic => true;
+}
+
+/**
+ * The classes (or groups) of tokens with a similar use.
+ */
+class TokenClass {
+  /**
+   * A value used to indicate that the token type is not part of any specific
+   * class of token.
+   */
+  static const TokenClass NO_CLASS = const TokenClass('NO_CLASS');
+
+  /**
+   * A value used to indicate that the token type is an additive operator.
+   */
+  static const TokenClass ADDITIVE_OPERATOR =
+      const TokenClass('ADDITIVE_OPERATOR', 13);
+
+  /**
+   * A value used to indicate that the token type is an assignment operator.
+   */
+  static const TokenClass ASSIGNMENT_OPERATOR =
+      const TokenClass('ASSIGNMENT_OPERATOR', 1);
+
+  /**
+   * A value used to indicate that the token type is a bitwise-and operator.
+   */
+  static const TokenClass BITWISE_AND_OPERATOR =
+      const TokenClass('BITWISE_AND_OPERATOR', 11);
+
+  /**
+   * A value used to indicate that the token type is a bitwise-or operator.
+   */
+  static const TokenClass BITWISE_OR_OPERATOR =
+      const TokenClass('BITWISE_OR_OPERATOR', 9);
+
+  /**
+   * A value used to indicate that the token type is a bitwise-xor operator.
+   */
+  static const TokenClass BITWISE_XOR_OPERATOR =
+      const TokenClass('BITWISE_XOR_OPERATOR', 10);
+
+  /**
+   * A value used to indicate that the token type is a cascade operator.
+   */
+  static const TokenClass CASCADE_OPERATOR =
+      const TokenClass('CASCADE_OPERATOR', 2);
+
+  /**
+   * A value used to indicate that the token type is a conditional operator.
+   */
+  static const TokenClass CONDITIONAL_OPERATOR =
+      const TokenClass('CONDITIONAL_OPERATOR', 3);
+
+  /**
+   * A value used to indicate that the token type is an equality operator.
+   */
+  static const TokenClass EQUALITY_OPERATOR =
+      const TokenClass('EQUALITY_OPERATOR', 7);
+
+  /**
+   * A value used to indicate that the token type is an if-null operator.
+   */
+  static const TokenClass IF_NULL_OPERATOR =
+      const TokenClass('IF_NULL_OPERATOR', 4);
+
+  /**
+   * A value used to indicate that the token type is a logical-and operator.
+   */
+  static const TokenClass LOGICAL_AND_OPERATOR =
+      const TokenClass('LOGICAL_AND_OPERATOR', 6);
+
+  /**
+   * A value used to indicate that the token type is a logical-or operator.
+   */
+  static const TokenClass LOGICAL_OR_OPERATOR =
+      const TokenClass('LOGICAL_OR_OPERATOR', 5);
+
+  /**
+   * A value used to indicate that the token type is a multiplicative operator.
+   */
+  static const TokenClass MULTIPLICATIVE_OPERATOR =
+      const TokenClass('MULTIPLICATIVE_OPERATOR', 14);
+
+  /**
+   * A value used to indicate that the token type is a relational operator.
+   */
+  static const TokenClass RELATIONAL_OPERATOR =
+      const TokenClass('RELATIONAL_OPERATOR', 8);
+
+  /**
+   * A value used to indicate that the token type is a shift operator.
+   */
+  static const TokenClass SHIFT_OPERATOR =
+      const TokenClass('SHIFT_OPERATOR', 12);
+
+  /**
+   * A value used to indicate that the token type is a unary operator.
+   */
+  static const TokenClass UNARY_POSTFIX_OPERATOR =
+      const TokenClass('UNARY_POSTFIX_OPERATOR', 16);
+
+  /**
+   * A value used to indicate that the token type is a unary operator.
+   */
+  static const TokenClass UNARY_PREFIX_OPERATOR =
+      const TokenClass('UNARY_PREFIX_OPERATOR', 15);
+
+  /**
+   * The name of the token class.
+   */
+  final String name;
+
+  /**
+   * The precedence of tokens of this class, or `0` if the such tokens do not
+   * represent an operator.
+   */
+  final int precedence;
+
+  /**
+   * Initialize a newly created class of tokens to have the given [name] and
+   * [precedence].
+   */
+  const TokenClass(this.name, [this.precedence = 0]);
+
+  @override
+  String toString() => name;
+}
+
+/**
+ * A normal token that is preceded by comments.
+ */
+class TokenWithComment extends SimpleToken {
+  /**
+   * The first comment in the list of comments that precede this token.
+   */
+  CommentToken _precedingComment;
+
+  /**
+   * Initialize a newly created token to have the given [type] at the given
+   * [offset] and to be preceded by the comments reachable from the given
+   * [comment].
+   */
+  TokenWithComment(TokenType type, int offset, this._precedingComment)
+      : super(type, offset) {
+    _setCommentParent(_precedingComment);
+  }
+
+  @override
+  CommentToken get precedingComments => _precedingComment;
+
+  void set precedingComments(CommentToken comment) {
+    _precedingComment = comment;
+    _setCommentParent(_precedingComment);
+  }
+
+  @override
+  Token copy() => new TokenWithComment(type, offset, precedingComments);
+}
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 33bc821..05ff07f 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -7,12 +7,13 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/token.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';
 
@@ -216,17 +217,17 @@
   ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) {
     cloneToken(node.abstractKeyword);
     return 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));
+        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
@@ -247,16 +248,12 @@
 
   @override
   CompilationUnit visitCompilationUnit(CompilationUnit node) {
-    ScriptTag scriptTag = cloneNode(node.scriptTag);
-    List<Directive> directives = cloneNodeList(node.directives);
-    List<CompilationUnitMember> declarations = cloneNodeList(node.declarations);
-    Token endToken = cloneToken(node.endToken);
-    Token beginToken = scriptTag?.beginToken ??
-        (directives.isEmpty ? null : directives.first.beginToken) ??
-        (declarations.isEmpty ? null : declarations.first.beginToken) ??
-        endToken;
     CompilationUnit clone = new CompilationUnit(
-        beginToken, scriptTag, directives, declarations, endToken);
+        cloneToken(node.beginToken),
+        cloneNode(node.scriptTag),
+        cloneNodeList(node.directives),
+        cloneNodeList(node.declarations),
+        cloneToken(node.endToken));
     clone.lineInfo = node.lineInfo;
     return clone;
   }
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index 7422233..ef51b61 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -7,6 +7,7 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -16,7 +17,6 @@
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -176,7 +176,7 @@
         exportElement.uri = node.uriContent;
         exportElement.combinators = _buildCombinators(node);
         exportElement.exportedLibrary = exportedLibrary;
-        _setDoc(exportElement, node);
+        setElementDocumentationComment(exportElement, node);
         node.element = exportElement;
         exports.add(exportElement);
         if (exportSourceKindMap[exportedSource] != SourceKind.LIBRARY) {
@@ -218,7 +218,7 @@
         importElement.deferred = node.deferredKeyword != null;
         importElement.combinators = _buildCombinators(node);
         importElement.importedLibrary = importedLibrary;
-        _setDoc(importElement, node);
+        setElementDocumentationComment(importElement, node);
         SimpleIdentifier prefixNode = node.prefix;
         if (prefixNode != null) {
           importElement.prefixOffset = prefixNode.offset;
@@ -272,19 +272,6 @@
   }
 
   /**
-   * If the given [node] has a documentation comment, remember its content
-   * and range into the given [element].
-   */
-  void _setDoc(ElementImpl element, AnnotatedNode node) {
-    Comment comment = node.documentationComment;
-    if (comment != null && comment.isDocumentation) {
-      element.documentationComment =
-          comment.tokens.map((Token t) => t.lexeme).join('\n');
-      element.setDocRange(comment.offset, comment.length);
-    }
-  }
-
-  /**
    * Build the element model representing the combinators declared by
    * the given [directive].
    */
@@ -316,11 +303,6 @@
   ElementHolder _currentHolder;
 
   /**
-   * A flag indicating whether a variable declaration is in the context of a field declaration.
-   */
-  bool _inFieldContext = false;
-
-  /**
    * A flag indicating whether a variable declaration is within the body of a method or function.
    */
   bool _inFunction = false;
@@ -349,18 +331,6 @@
   }
 
   @override
-  Object visitBlock(Block node) {
-    bool wasInField = _inFieldContext;
-    _inFieldContext = false;
-    try {
-      node.visitChildren(this);
-    } finally {
-      _inFieldContext = wasInField;
-    }
-    return null;
-  }
-
-  @override
   Object visitCatchClause(CatchClause node) {
     SimpleIdentifier exceptionParameter = node.exceptionParameter;
     if (exceptionParameter != null) {
@@ -415,7 +385,7 @@
     interfaceType.typeArguments = typeArguments;
     element.type = interfaceType;
     element.typeParameters = typeParameters;
-    _setDoc(element, node);
+    setElementDocumentationComment(element, node);
     element.abstract = node.isAbstract;
     element.accessors = holder.accessors;
     List<ConstructorElement> constructors = holder.constructors;
@@ -466,7 +436,7 @@
     InterfaceTypeImpl interfaceType = new InterfaceTypeImpl(element);
     interfaceType.typeArguments = typeArguments;
     element.type = interfaceType;
-    _setDoc(element, node);
+    setElementDocumentationComment(element, node);
     _currentHolder.addType(element);
     className.staticElement = element;
     holder.validate();
@@ -488,7 +458,7 @@
     ConstructorElementImpl element =
         new ConstructorElementImpl.forNode(constructorName);
     element.metadata = _createElementAnnotations(node.metadata);
-    _setDoc(element, node);
+    setElementDocumentationComment(element, node);
     if (node.externalKeyword != null) {
       element.external = true;
     }
@@ -596,7 +566,7 @@
     ClassElementImpl enumElement = new ClassElementImpl.forNode(enumName);
     enumElement.metadata = _createElementAnnotations(node.metadata);
     enumElement.enum2 = true;
-    _setDoc(enumElement, node);
+    setElementDocumentationComment(enumElement, node);
     InterfaceTypeImpl enumType = new InterfaceTypeImpl(enumElement);
     enumElement.type = enumType;
     // The equivalent code for enums in the spec shows a single constructor,
@@ -616,18 +586,6 @@
   }
 
   @override
-  Object visitFieldDeclaration(FieldDeclaration node) {
-    bool wasInField = _inFieldContext;
-    _inFieldContext = true;
-    try {
-      node.visitChildren(this);
-    } finally {
-      _inFieldContext = wasInField;
-    }
-    return null;
-  }
-
-  @override
   Object visitFieldFormalParameter(FieldFormalParameter node) {
     if (node.parent is! DefaultFormalParameter) {
       SimpleIdentifier parameterName = node.identifier;
@@ -677,7 +635,7 @@
         FunctionElementImpl element =
             new FunctionElementImpl.forNode(functionName);
         element.metadata = _createElementAnnotations(node.metadata);
-        _setDoc(element, node);
+        setElementDocumentationComment(element, node);
         if (node.externalKeyword != null) {
           element.external = true;
         }
@@ -695,9 +653,8 @@
         if (_inFunction) {
           Block enclosingBlock = node.getAncestor((node) => node is Block);
           if (enclosingBlock != null) {
-            int functionEnd = node.offset + node.length;
-            int blockEnd = enclosingBlock.offset + enclosingBlock.length;
-            element.setVisibleRange(functionEnd, blockEnd - functionEnd - 1);
+            element.setVisibleRange(
+                enclosingBlock.offset, enclosingBlock.length);
           }
         }
         if (node.returnType == null) {
@@ -725,7 +682,7 @@
           PropertyAccessorElementImpl getter =
               new PropertyAccessorElementImpl.forNode(propertyNameNode);
           getter.metadata = _createElementAnnotations(node.metadata);
-          _setDoc(getter, node);
+          setElementDocumentationComment(getter, node);
           if (node.externalKeyword != null) {
             getter.external = true;
           }
@@ -752,7 +709,7 @@
           PropertyAccessorElementImpl setter =
               new PropertyAccessorElementImpl.forNode(propertyNameNode);
           setter.metadata = _createElementAnnotations(node.metadata);
-          _setDoc(setter, node);
+          setElementDocumentationComment(setter, node);
           if (node.externalKeyword != null) {
             setter.external = true;
           }
@@ -816,9 +773,7 @@
     if (_inFunction) {
       Block enclosingBlock = node.getAncestor((node) => node is Block);
       if (enclosingBlock != null) {
-        int functionEnd = node.offset + node.length;
-        int blockEnd = enclosingBlock.offset + enclosingBlock.length;
-        element.setVisibleRange(functionEnd, blockEnd - functionEnd - 1);
+        element.setVisibleRange(enclosingBlock.offset, enclosingBlock.length);
       }
     }
     if (_functionTypesToFix != null) {
@@ -843,7 +798,7 @@
     FunctionTypeAliasElementImpl element =
         new FunctionTypeAliasElementImpl.forNode(aliasName);
     element.metadata = _createElementAnnotations(node.metadata);
-    _setDoc(element, node);
+    setElementDocumentationComment(element, node);
     element.parameters = parameters;
     element.typeParameters = typeParameters;
     _createTypeParameterTypes(typeParameters);
@@ -928,7 +883,7 @@
         MethodElementImpl element =
             new MethodElementImpl(nameOfMethod, methodName.offset);
         element.metadata = _createElementAnnotations(node.metadata);
-        _setDoc(element, node);
+        setElementDocumentationComment(element, node);
         element.abstract = node.isAbstract;
         if (node.externalKeyword != null) {
           element.external = true;
@@ -966,7 +921,7 @@
           PropertyAccessorElementImpl getter =
               new PropertyAccessorElementImpl.forNode(propertyNameNode);
           getter.metadata = _createElementAnnotations(node.metadata);
-          _setDoc(getter, node);
+          setElementDocumentationComment(getter, node);
           if (node.externalKeyword != null) {
             getter.external = true;
           }
@@ -993,7 +948,7 @@
           PropertyAccessorElementImpl setter =
               new PropertyAccessorElementImpl.forNode(propertyNameNode);
           setter.metadata = _createElementAnnotations(node.metadata);
-          _setDoc(setter, node);
+          setElementDocumentationComment(setter, node);
           if (node.externalKeyword != null) {
             setter.external = true;
           }
@@ -1127,22 +1082,22 @@
     bool isConst = node.isConst;
     bool isFinal = node.isFinal;
     bool hasInitializer = node.initializer != null;
+    VariableDeclarationList varList = node.parent;
+    FieldDeclaration fieldNode =
+        varList.parent is FieldDeclaration ? varList.parent : null;
     VariableElementImpl element;
-    if (_inFieldContext) {
+    if (fieldNode != null) {
       SimpleIdentifier fieldName = node.name;
       FieldElementImpl field;
-      if ((isConst || isFinal) && hasInitializer) {
+      if ((isConst || isFinal && !fieldNode.isStatic) && hasInitializer) {
         field = new ConstFieldElementImpl.forNode(fieldName);
       } else {
         field = new FieldElementImpl.forNode(fieldName);
       }
       element = field;
-      if (node.parent.parent is FieldDeclaration) {
-        _setDoc(element, node.parent.parent);
-      }
-      if ((node.parent as VariableDeclarationList).type == null) {
-        field.hasImplicitType = true;
-      }
+      field.static = fieldNode.isStatic;
+      setElementDocumentationComment(element, fieldNode);
+      field.hasImplicitType = varList.type == null;
       _currentHolder.addField(field);
       fieldName.staticElement = field;
     } else if (_inFunction) {
@@ -1158,9 +1113,7 @@
       // TODO(brianwilkerson) This isn't right for variables declared in a for
       // loop.
       variable.setVisibleRange(enclosingBlock.offset, enclosingBlock.length);
-      if ((node.parent as VariableDeclarationList).type == null) {
-        variable.hasImplicitType = true;
-      }
+      variable.hasImplicitType = varList.type == null;
       _currentHolder.addLocalVariable(variable);
       variableName.staticElement = element;
     } else {
@@ -1172,12 +1125,10 @@
         variable = new TopLevelVariableElementImpl.forNode(variableName);
       }
       element = variable;
-      if (node.parent.parent is TopLevelVariableDeclaration) {
-        _setDoc(element, node.parent.parent);
+      if (varList.parent is TopLevelVariableDeclaration) {
+        setElementDocumentationComment(element, varList.parent);
       }
-      if ((node.parent as VariableDeclarationList).type == null) {
-        variable.hasImplicitType = true;
-      }
+      variable.hasImplicitType = varList.type == null;
       _currentHolder.addTopLevelVariable(variable);
       variableName.staticElement = element;
     }
@@ -1185,13 +1136,7 @@
     element.final2 = isFinal;
     if (hasInitializer) {
       ElementHolder holder = new ElementHolder();
-      bool wasInFieldContext = _inFieldContext;
-      _inFieldContext = false;
-      try {
-        _visit(holder, node.initializer);
-      } finally {
-        _inFieldContext = wasInFieldContext;
-      }
+      _visit(holder, node.initializer);
       FunctionElementImpl initializer =
           new FunctionElementImpl.forOffset(node.initializer.beginToken.offset);
       initializer.functions = holder.functions;
@@ -1202,10 +1147,6 @@
       holder.validate();
     }
     if (element is PropertyInducingElementImpl) {
-      if (_inFieldContext) {
-        (element as FieldElementImpl).static =
-            (node.parent.parent as FieldDeclaration).isStatic;
-      }
       PropertyAccessorElementImpl getter =
           new PropertyAccessorElementImpl.forVariable(element);
       getter.getter = true;
@@ -1322,47 +1263,28 @@
   }
 
   /**
-   * Return the body of the function that contains the given parameter, or `null` if no
-   * function body could be found.
-   *
-   * @param node the parameter contained in the function whose body is to be returned
-   * @return the body of the function that contains the given parameter
+   * Return the body of the function that contains the given [parameter], or
+   * `null` if no function body could be found.
    */
-  FunctionBody _getFunctionBody(FormalParameter node) {
-    AstNode parent = node.parent;
-    while (parent != null) {
-      if (parent is ConstructorDeclaration) {
-        return parent.body;
-      } else if (parent is FunctionExpression) {
-        return parent.body;
-      } else if (parent is MethodDeclaration) {
-        return parent.body;
-      }
-      parent = parent.parent;
+  FunctionBody _getFunctionBody(FormalParameter parameter) {
+    AstNode parent = parameter?.parent?.parent;
+    if (parent is ConstructorDeclaration) {
+      return parent.body;
+    } else if (parent is FunctionExpression) {
+      return parent.body;
+    } else if (parent is MethodDeclaration) {
+      return parent.body;
     }
     return null;
   }
 
   /**
-   * If the given [node] has a documentation comment, remember its content
-   * and range into the given [element].
-   */
-  void _setDoc(ElementImpl element, AnnotatedNode node) {
-    Comment comment = node.documentationComment;
-    if (comment != null && comment.isDocumentation) {
-      element.documentationComment =
-          comment.tokens.map((Token t) => t.lexeme).join('\n');
-      element.setDocRange(comment.offset, comment.length);
-    }
-  }
-
-  /**
    * Sets the visible source range for formal parameter.
    */
   void _setParameterVisibleRange(
       FormalParameter node, ParameterElementImpl element) {
     FunctionBody body = _getFunctionBody(node);
-    if (body != null) {
+    if (body is BlockFunctionBody || body is ExpressionFunctionBody) {
       element.setVisibleRange(body.offset, body.length);
     }
   }
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 74c0bba..9677e89 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -8,6 +8,7 @@
 import 'dart:math' show min;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/visitor.dart';
@@ -20,7 +21,6 @@
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart' show Keyword;
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_collection.dart';
@@ -1221,7 +1221,7 @@
   ConstFieldElementImpl.forNode(Identifier name) : super.forNode(name);
 
   @override
-  DartObject get constantValue => _result.value;
+  DartObject get constantValue => _result?.value;
 
   @override
   EvaluationResultImpl get evaluationResult => _result;
@@ -1255,7 +1255,7 @@
   ConstLocalVariableElementImpl.forNode(Identifier name) : super.forNode(name);
 
   @override
-  DartObject get constantValue => _result.value;
+  DartObject get constantValue => _result?.value;
 
   @override
   EvaluationResultImpl get evaluationResult => _result;
@@ -1414,7 +1414,7 @@
       : super.forNode(name);
 
   @override
-  DartObject get constantValue => _result.value;
+  DartObject get constantValue => _result?.value;
 
   @override
   EvaluationResultImpl get evaluationResult => _result;
@@ -1473,7 +1473,7 @@
       : super.forNode(name);
 
   @override
-  DartObject get constantValue => _result.value;
+  DartObject get constantValue => _result?.value;
 
   @override
   EvaluationResultImpl get evaluationResult => _result;
@@ -1507,7 +1507,7 @@
   DefaultParameterElementImpl.forNode(Identifier name) : super.forNode(name);
 
   @override
-  DartObject get constantValue => _result.value;
+  DartObject get constantValue => _result?.value;
 
   @override
   EvaluationResultImpl get evaluationResult => _result;
@@ -1610,7 +1610,7 @@
   ElementAnnotationImpl(this.compilationUnit);
 
   @override
-  DartObject get constantValue => evaluationResult.value;
+  DartObject get constantValue => evaluationResult?.value;
 
   @override
   AnalysisContext get context => compilationUnit.library.context;
@@ -4300,11 +4300,6 @@
  */
 class PrefixElementImpl extends ElementImpl implements PrefixElement {
   /**
-   * A list containing all of the libraries that are imported using this prefix.
-   */
-  List<LibraryElement> _importedLibraries = LibraryElement.EMPTY_LIST;
-
-  /**
    * Initialize a newly created method element to have the given [name] and
    * [offset].
    */
@@ -4323,18 +4318,7 @@
   String get identifier => "_${super.identifier}";
 
   @override
-  List<LibraryElement> get importedLibraries => _importedLibraries;
-
-  /**
-   * Set the libraries that are imported using this prefix to the given
-   * [libraries].
-   */
-  void set importedLibraries(List<LibraryElement> libraries) {
-    for (LibraryElement library in libraries) {
-      (library as LibraryElementImpl).enclosingElement = this;
-    }
-    _importedLibraries = libraries;
-  }
+  List<LibraryElement> get importedLibraries => LibraryElement.EMPTY_LIST;
 
   @override
   ElementKind get kind => ElementKind.PREFIX;
@@ -4616,6 +4600,14 @@
   TypeParameterElementImpl(String name, int offset) : super(name, offset);
 
   /**
+   * Initialize a newly created synthetic type parameter element to have the
+   * given [name], and with [synthetic] set to true.
+   */
+  TypeParameterElementImpl.synthetic(String name) : super(name, -1) {
+    synthetic = true;
+  }
+
+  /**
    * Initialize a newly created type parameter element to have the given [name].
    */
   TypeParameterElementImpl.forNode(Identifier name) : super.forNode(name);
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 57cbcb9..558b5ec 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -128,8 +128,7 @@
  * type parameters are known.
  */
 abstract class ExecutableMember extends Member implements ExecutableElement {
-  @override
-  final FunctionType type;
+  FunctionType _type;
 
   /**
    * Initialize a newly created element to represent a callable element (like a
@@ -139,9 +138,7 @@
    */
   ExecutableMember(ExecutableElement baseElement, InterfaceType definingType,
       [FunctionType type])
-      : type = type ??
-            baseElement.type.substitute2(definingType.typeArguments,
-                TypeParameterTypeImpl.getTypes(definingType.typeParameters)),
+      : _type = type,
         super(baseElement, definingType);
 
   @override
@@ -201,6 +198,12 @@
   DartType get returnType => type.returnType;
 
   @override
+  FunctionType get type {
+    return _type ??= baseElement.type.substitute2(definingType.typeArguments,
+        TypeParameterTypeImpl.getTypes(definingType.typeParameters));
+  }
+
+  @override
   List<TypeParameterElement> get typeParameters => baseElement.typeParameters;
 
   @override
@@ -898,6 +901,68 @@
 }
 
 /**
+ * A type parameter defined inside of another parameterized type, where the
+ * values of the enclosing type parameters are known.
+ *
+ * For example:
+ *
+ *     class C<T> {
+ *       S m<S extends T>(S s);
+ *     }
+ *
+ * If we have `C<num>.m` and we ask for the type parameter "S", we should get
+ * `<S extends num>` instead of `<S extends T>`. This is how the parameter
+ * and return types work, see: [FunctionType.parameters],
+ * [FunctionType.returnType], and [ParameterMember].
+ */
+class TypeParameterMember extends Member implements TypeParameterElement {
+  @override
+  final DartType bound;
+
+  TypeParameterMember(
+      TypeParameterElement baseElement, DartType definingType, this.bound)
+      : super(baseElement, definingType);
+
+  @override
+  TypeParameterElement get baseElement =>
+      super.baseElement as TypeParameterElement;
+
+  @override
+  Element get enclosingElement => baseElement.enclosingElement;
+
+  @override
+  TypeParameterType get type => baseElement.type;
+
+  @override
+  accept(ElementVisitor visitor) => visitor.visitTypeParameterElement(this);
+
+  /**
+   * If the given [parameter]'s type is different when any type parameters from
+   * the defining type's declaration are replaced with the actual type
+   * arguments from the [definingType], create a parameter member representing
+   * the given parameter. Return the member that was created, or the base
+   * parameter if no member was created.
+   */
+  static TypeParameterElement from(
+      TypeParameterElement parameter, ParameterizedType definingType) {
+    if (parameter?.bound == null || definingType.typeArguments.isEmpty) {
+      return parameter;
+    }
+
+    DartType bound = parameter.bound;
+    List<DartType> argumentTypes = definingType.typeArguments;
+    List<DartType> parameterTypes =
+        TypeParameterTypeImpl.getTypes(definingType.typeParameters);
+    DartType substitutedBound =
+        bound.substitute2(argumentTypes, parameterTypes);
+    if (bound == substitutedBound) {
+      return parameter;
+    }
+    return new TypeParameterMember(parameter, definingType, substitutedBound);
+  }
+}
+
+/**
  * A variable element defined in a parameterized type where the values of the
  * type parameters are known.
  */
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 1b9c290..cfc076ff 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -6,6 +6,7 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
@@ -13,8 +14,8 @@
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisContext, AnalysisEngine;
 import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/scanner.dart' show Keyword;
 import 'package:analyzer/src/generated/type_system.dart';
+import 'package:analyzer/src/generated/utilities_collection.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
 /**
@@ -144,8 +145,7 @@
   /**
    * Constructor used by [CircularTypeImpl].
    */
-  DynamicTypeImpl._circular()
-      : super(instance.element, Keyword.DYNAMIC.syntax);
+  DynamicTypeImpl._circular() : super(instance.element, Keyword.DYNAMIC.syntax);
 
   @override
   int get hashCode => 1;
@@ -397,15 +397,6 @@
   }
 
   @override
-  List<DartType> get normalParameterTypes {
-    List<DartType> types = <DartType>[];
-    _forEachParameterType(ParameterKind.REQUIRED, (name, type) {
-      types.add(type);
-    });
-    return types;
-  }
-
-  @override
   List<String> get normalParameterNames {
     return baseParameters
         .where((parameter) => parameter.parameterKind == ParameterKind.REQUIRED)
@@ -414,9 +405,9 @@
   }
 
   @override
-  List<DartType> get optionalParameterTypes {
+  List<DartType> get normalParameterTypes {
     List<DartType> types = <DartType>[];
-    _forEachParameterType(ParameterKind.POSITIONAL, (name, type) {
+    _forEachParameterType(ParameterKind.REQUIRED, (name, type) {
       types.add(type);
     });
     return types;
@@ -432,6 +423,15 @@
   }
 
   @override
+  List<DartType> get optionalParameterTypes {
+    List<DartType> types = <DartType>[];
+    _forEachParameterType(ParameterKind.POSITIONAL, (name, type) {
+      types.add(type);
+    });
+    return types;
+  }
+
+  @override
   List<ParameterElement> get parameters {
     List<ParameterElement> baseParameters = this.baseParameters;
     // no parameters, quick return
@@ -487,11 +487,24 @@
 
   @override
   List<TypeParameterElement> get typeFormals {
-    if (_isInstantiated) {
+    if (_isInstantiated || element == null) {
       return TypeParameterElement.EMPTY_LIST;
-    } else {
-      return element?.typeParameters ?? TypeParameterElement.EMPTY_LIST;
     }
+    List<TypeParameterElement> baseTypeFormals = element.typeParameters;
+    int formalCount = baseTypeFormals.length;
+    if (formalCount == 0) {
+      return TypeParameterElement.EMPTY_LIST;
+    }
+
+    // Create type formals with specialized bounds.
+    // For example `<U extends T>` where T comes from an outer scope.
+    List<TypeParameterElement> result =
+        new List<TypeParameterElement>(formalCount);
+
+    for (int i = 0; i < formalCount; i++) {
+      result[i] = TypeParameterMember.from(baseTypeFormals[i], this);
+    }
+    return result;
   }
 
   @override
@@ -501,13 +514,19 @@
       // for this generic function's type variables. Those variables are
       // tracked in [boundTypeParameters].
       _typeParameters = <TypeParameterElement>[];
-      Element e = element?.enclosingElement;
+
+      Element e = element;
       while (e != null) {
+        // If a static method, skip the enclosing class type parameters.
+        if (e is MethodElement && e.isStatic) {
+          e = e.enclosingElement;
+        }
+        e = e.enclosingElement;
         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
@@ -534,28 +553,13 @@
     // To test this, we instantiate both types with the same (unique) type
     // variables, and see if the result is equal.
     if (typeFormals.isNotEmpty) {
-      List<DartType> instantiateTypeArgs = new List<DartType>();
-      List<DartType> variablesThis = new List<DartType>();
-      List<DartType> variablesOther = new List<DartType>();
-      for (int i = 0; i < typeFormals.length; i++) {
-        TypeParameterElement pThis = typeFormals[i];
-        TypeParameterElement pOther = otherType.typeFormals[i];
-        TypeParameterTypeImpl pFresh = new TypeParameterTypeImpl(
-            new TypeParameterElementImpl(pThis.name, -1));
-        instantiateTypeArgs.add(pFresh);
-        variablesThis.add(pThis.type);
-        variablesOther.add(pOther.type);
-        // Check that the bounds are equal after equating the previous
-        // bound variables.
-        if (pThis.bound?.substitute2(instantiateTypeArgs, variablesThis) !=
-            pOther.bound?.substitute2(instantiateTypeArgs, variablesOther)) {
-          return false;
-        }
+      List<DartType> freshVariables =
+          relateTypeFormals(this, otherType, (t, s) => t == s);
+      if (freshVariables == null) {
+        return false;
       }
-      // After instantiation, they will no longer have typeFormals,
-      // so we will continue below.
-      return this.instantiate(instantiateTypeArgs) ==
-          otherType.instantiate(instantiateTypeArgs);
+      return instantiate(freshVariables) ==
+          otherType.instantiate(freshVariables);
     }
 
     return returnType == otherType.returnType &&
@@ -581,8 +585,8 @@
         }
       }
 
-      List<DartType> instantiateTypeArgs = new List<DartType>();
-      List<DartType> variables = new List<DartType>();
+      List<DartType> instantiateTypeArgs = <DartType>[];
+      List<DartType> variables = <DartType>[];
       buffer.write("<");
       for (TypeParameterElement e in typeFormals) {
         if (e != typeFormals[0]) {
@@ -717,49 +721,186 @@
       [bool withDynamic = false, Set<Element> visitedElements]) {
     // Note: visitedElements is only used for breaking recursion in the type
     // hierarchy; we don't use it when recursing into the function type.
-    bool relation = _trivialFunctionRelation(type);
-    if (relation != null) {
-      return relation;
-    }
-
-    return structuralCompare(this, type,
-        (TypeImpl t, TypeImpl s) => t.isMoreSpecificThan(s, withDynamic));
+    return relate(
+        this,
+        type,
+        (DartType t, DartType s) =>
+            (t as TypeImpl).isMoreSpecificThan(s, withDynamic),
+        new TypeSystemImpl().instantiateToBounds);
   }
 
   @override
   bool isSubtypeOf(DartType type) {
-    bool relation = _trivialFunctionRelation(type);
-    if (relation != null) {
-      return relation;
+    return relate(
+        this,
+        type,
+        (DartType t, DartType s) => t.isAssignableTo(s),
+        new TypeSystemImpl().instantiateToBounds);
+  }
+
+  @override
+  TypeImpl pruned(List<FunctionTypeAliasElement> prune) {
+    if (prune == null) {
+      return this;
+    } else if (prune.contains(element)) {
+      // Circularity found.  Prune the type declaration.
+      return new CircularTypeImpl();
+    } else {
+      // There should never be a reason to prune a type that has already been
+      // pruned, since pruning is only done when expanding a function type
+      // alias, and function type aliases are always expanded by starting with
+      // base types.
+      assert(this.prunedTypedefs == null);
+      List<DartType> typeArgs = typeArguments
+          .map((TypeImpl t) => t.pruned(prune))
+          .toList(growable: false);
+      return new FunctionTypeImpl._(
+          element, name, prune, typeArgs, _isInstantiated);
+    }
+  }
+
+  @override
+  DartType substitute2(
+      List<DartType> argumentTypes, List<DartType> parameterTypes,
+      [List<FunctionTypeAliasElement> prune]) {
+    // Pruned types should only ever result from performing type variable
+    // substitution, and it doesn't make sense to substitute again after
+    // substituting once.
+    assert(this.prunedTypedefs == null);
+    if (argumentTypes.length != parameterTypes.length) {
+      throw new IllegalArgumentException(
+          "argumentTypes.length (${argumentTypes.length}) != parameterTypes.length (${parameterTypes.length})");
+    }
+    Element element = this.element;
+    if (prune != null && prune.contains(element)) {
+      // Circularity found.  Prune the type declaration.
+      return new CircularTypeImpl();
+    }
+    if (argumentTypes.length == 0) {
+      return this.pruned(prune);
+    }
+    List<DartType> typeArgs =
+        TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes);
+    return new FunctionTypeImpl._(
+        element, name, prune, typeArgs, _isInstantiated);
+  }
+
+  @override
+  FunctionTypeImpl substitute3(List<DartType> argumentTypes) =>
+      substitute2(argumentTypes, typeArguments);
+
+  /**
+   * Invokes [callback] for each parameter of [kind] with the parameter's [name]
+   * and [type] after any type parameters have been applied.
+   */
+  void _forEachParameterType(
+      ParameterKind kind, callback(String name, DartType type)) {
+    if (baseParameters.isEmpty) {
+      return;
     }
 
-    return structuralCompare(
-        this, type, (TypeImpl t, TypeImpl s) => t.isAssignableTo(s));
+    List<DartType> typeParameters =
+        TypeParameterTypeImpl.getTypes(this.typeParameters);
+    for (ParameterElement parameter in baseParameters) {
+      if (parameter.parameterKind == kind) {
+        TypeImpl type = parameter.type;
+        if (typeArguments.length != 0 &&
+            typeArguments.length == typeParameters.length) {
+          type = type.substitute2(typeArguments, typeParameters, newPrune);
+        } else {
+          type = type.pruned(newPrune);
+        }
+
+        callback(parameter.name, type);
+      }
+    }
+  }
+
+  void _freeVariablesInFunctionType(
+      FunctionType type, Set<TypeParameterType> free) {
+    // Make some fresh variables to avoid capture.
+    List<DartType> typeArgs = DartType.EMPTY_LIST;
+    if (type.typeFormals.isNotEmpty) {
+      typeArgs = new List<DartType>.from(type.typeFormals.map((e) =>
+          new TypeParameterTypeImpl(new TypeParameterElementImpl(e.name, -1))));
+
+      type = type.instantiate(typeArgs);
+    }
+
+    for (ParameterElement p in type.parameters) {
+      _freeVariablesInType(p.type, free);
+    }
+    _freeVariablesInType(type.returnType, free);
+
+    // Remove all of our bound variables.
+    free.removeAll(typeArgs);
+  }
+
+  void _freeVariablesInInterfaceType(
+      InterfaceType type, Set<TypeParameterType> free) {
+    for (DartType typeArg in type.typeArguments) {
+      _freeVariablesInType(typeArg, free);
+    }
+  }
+
+  void _freeVariablesInType(DartType type, Set<TypeParameterType> free) {
+    if (type is TypeParameterType) {
+      free.add(type);
+    } else if (type is FunctionType) {
+      _freeVariablesInFunctionType(type, free);
+    } else if (type is InterfaceType) {
+      _freeVariablesInInterfaceType(type, free);
+    }
   }
 
   /**
-   * Tests if [other] meets any of the easy relation cases for [isSubtypeOf]
-   * and [isMoreSpecificThan].
+   * Given two functions [f1] and [f2] where f1 and f2 are known to be
+   * generic function types (both have type formals), this checks that they
+   * have the same number of formals, and that those formals have bounds
+   * (e.g. `<T extends LowerBound>`) that satisfy [relation].
    *
-   * Returns `true` if the relation is known to hold, `false` if it isn't, or
-   * `null` if it's unknown and a deeper structural comparison is needed.
+   * The return value will be a new list of fresh type variables, that can be
+   * used to instantiate both function types, allowing further comparison.
+   * For example, given `<T>T -> T` and `<U>U -> U` we can instantiate them with
+   * `F` to get `F -> F` and `F -> F`, which we can see are equal.
    */
-  bool _trivialFunctionRelation(DartType other) {
-    // Trivial base cases.
-    if (other == null) {
-      return false;
-    } else if (identical(this, other) ||
-        other.isDynamic ||
-        other.isDartCoreFunction ||
-        other.isObject) {
-      return true;
-    } else if (other is! FunctionType) {
-      return false;
-    } else if (this == other) {
-      return true;
+  static List<DartType> relateTypeFormals(
+      FunctionType f1, FunctionType f2, bool relation(DartType t, DartType s)) {
+    List<TypeParameterElement> params1 = f1.typeFormals;
+    List<TypeParameterElement> params2 = f2.typeFormals;
+    int count = params1.length;
+    if (params2.length != count) {
+      return null;
     }
+    // We build up a substitution matching up the type parameters
+    // from the two types, {variablesFresh/variables1} and
+    // {variablesFresh/variables2}
+    List<DartType> variables1 = <DartType>[];
+    List<DartType> variables2 = <DartType>[];
+    List<DartType> variablesFresh = <DartType>[];
+    for (int i = 0; i < count; i++) {
+      TypeParameterElement p1 = params1[i];
+      TypeParameterElement p2 = params2[i];
+      TypeParameterElementImpl pFresh =
+          new TypeParameterElementImpl.synthetic(p2.name);
 
-    return null;
+      DartType variable1 = p1.type;
+      DartType variable2 = p2.type;
+      DartType variableFresh = new TypeParameterTypeImpl(pFresh);
+
+      variables1.add(variable1);
+      variables2.add(variable2);
+      variablesFresh.add(variableFresh);
+      DartType bound1 = p1.bound ?? DynamicTypeImpl.instance;
+      DartType bound2 = p2.bound ?? DynamicTypeImpl.instance;
+      bound1 = bound1.substitute2(variablesFresh, variables1);
+      bound2 = bound2.substitute2(variablesFresh, variables2);
+      pFresh.bound = bound2;
+      if (!relation(bound2, bound1)) {
+        return null;
+      }
+    }
+    return variablesFresh;
   }
 
   /**
@@ -773,11 +914,45 @@
    *
    * If [returnRelation] is omitted, uses [parameterRelation] for both.
    */
-  static bool structuralCompare(FunctionType t, FunctionType s,
+  static bool relate(
+      FunctionType t,
+      DartType other,
       bool parameterRelation(DartType t, DartType s),
-      [bool returnRelation(DartType t, DartType s)]) {
-    // Test the return types.
+      FunctionType instantiateToBounds(FunctionType t),
+      {bool returnRelation(DartType t, DartType s)}) {
+
     returnRelation ??= parameterRelation;
+
+    // Trivial base cases.
+    if (other == null) {
+      return false;
+    } else if (identical(t, other) ||
+        other.isDynamic ||
+        other.isDartCoreFunction ||
+        other.isObject) {
+      return true;
+    } else if (other is! FunctionType) {
+      return false;
+    }
+
+    // This type cast is safe, because we checked it above.
+    FunctionType s = other as FunctionType;
+    if (t.typeFormals.isNotEmpty) {
+      if (s.typeFormals.isEmpty) {
+        t = instantiateToBounds(t);
+      } else {
+        List<DartType> freshVariables = relateTypeFormals(t, s, returnRelation);
+        if (freshVariables == null) {
+          return false;
+        }
+        t = t.instantiate(freshVariables);
+        s = s.instantiate(freshVariables);
+      }
+    } else if (s.typeFormals.isNotEmpty) {
+      return false;
+    }
+
+    // Test the return types.
     DartType sRetType = s.returnType;
     if (!sRetType.isVoid && !returnRelation(t.returnType, sRetType)) {
       return false;
@@ -848,94 +1023,6 @@
     return true;
   }
 
-  @override
-  TypeImpl pruned(List<FunctionTypeAliasElement> prune) {
-    if (prune == null) {
-      return this;
-    } else if (prune.contains(element)) {
-      // Circularity found.  Prune the type declaration.
-      return new CircularTypeImpl();
-    } else {
-      // There should never be a reason to prune a type that has already been
-      // pruned, since pruning is only done when expanding a function type
-      // alias, and function type aliases are always expanded by starting with
-      // base types.
-      assert(this.prunedTypedefs == null);
-      List<DartType> typeArgs = typeArguments
-          .map((TypeImpl t) => t.pruned(prune))
-          .toList(growable: false);
-      return new FunctionTypeImpl._(
-          element, name, prune, typeArgs, _isInstantiated);
-    }
-  }
-
-  @override
-  DartType substitute2(
-      List<DartType> argumentTypes, List<DartType> parameterTypes,
-      [List<FunctionTypeAliasElement> prune]) {
-    // Pruned types should only ever result from performing type variable
-    // substitution, and it doesn't make sense to substitute again after
-    // substituting once.
-    assert(this.prunedTypedefs == null);
-    if (argumentTypes.length != parameterTypes.length) {
-      throw new IllegalArgumentException(
-          "argumentTypes.length (${argumentTypes.length}) != parameterTypes.length (${parameterTypes.length})");
-    }
-    Element element = this.element;
-    if (prune != null && prune.contains(element)) {
-      // Circularity found.  Prune the type declaration.
-      return new CircularTypeImpl();
-    }
-    if (argumentTypes.length == 0) {
-      return this.pruned(prune);
-    }
-    List<DartType> typeArgs =
-        TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes);
-    return new FunctionTypeImpl._(
-        element, name, prune, typeArgs, _isInstantiated);
-  }
-
-  @override
-  FunctionTypeImpl substitute3(List<DartType> argumentTypes) =>
-      substitute2(argumentTypes, typeArguments);
-
-  void _freeVariablesInFunctionType(
-      FunctionType type, Set<TypeParameterType> free) {
-    // Make some fresh variables to avoid capture.
-    List<DartType> typeArgs = DartType.EMPTY_LIST;
-    if (type.typeFormals.isNotEmpty) {
-      typeArgs = new List<DartType>.from(type.typeFormals.map((e) =>
-          new TypeParameterTypeImpl(new TypeParameterElementImpl(e.name, -1))));
-
-      type = type.instantiate(typeArgs);
-    }
-
-    for (ParameterElement p in type.parameters) {
-      _freeVariablesInType(p.type, free);
-    }
-    _freeVariablesInType(type.returnType, free);
-
-    // Remove all of our bound variables.
-    free.removeAll(typeArgs);
-  }
-
-  void _freeVariablesInInterfaceType(
-      InterfaceType type, Set<TypeParameterType> free) {
-    for (DartType typeArg in type.typeArguments) {
-      _freeVariablesInType(typeArg, free);
-    }
-  }
-
-  void _freeVariablesInType(DartType type, Set<TypeParameterType> free) {
-    if (type is TypeParameterType) {
-      free.add(type);
-    } else if (type is FunctionType) {
-      _freeVariablesInFunctionType(type, free);
-    } else if (type is InterfaceType) {
-      _freeVariablesInInterfaceType(type, free);
-    }
-  }
-
   /**
    * Return `true` if all of the name/type pairs in the first map ([firstTypes])
    * are equal to the corresponding name/type pairs in the second map
@@ -960,33 +1047,6 @@
     }
     return true;
   }
-
-  /**
-   * Invokes [callback] for each parameter of [kind] with the parameter's [name]
-   * and [type] after any type parameters have been applied.
-   */
-  void _forEachParameterType(
-      ParameterKind kind, callback(String name, DartType type)) {
-    if (baseParameters.isEmpty) {
-      return;
-    }
-
-    List<DartType> typeParameters =
-        TypeParameterTypeImpl.getTypes(this.typeParameters);
-    for (ParameterElement parameter in baseParameters) {
-      if (parameter.parameterKind == kind) {
-        TypeImpl type = parameter.type;
-        if (typeArguments.length != 0 &&
-            typeArguments.length == typeParameters.length) {
-          type = type.substitute2(typeArguments, typeParameters, newPrune);
-        } else {
-          type = type.pruned(newPrune);
-        }
-
-        callback(parameter.name, type);
-      }
-    }
-  }
 }
 
 /**
@@ -1636,7 +1696,7 @@
     }
     List<DartType> newTypeArguments = TypeImpl.substitute(
         typeArguments, argumentTypes, parameterTypes, prune);
-    if (JavaArrays.equals(newTypeArguments, typeArguments)) {
+    if (listsEqual(newTypeArguments, typeArguments)) {
       return this;
     }
 
@@ -2172,6 +2232,9 @@
       [List<FunctionTypeAliasElement> prune]);
 
   @override
+  DartType resolveToBound(DartType objectType) => this;
+
+  @override
   String toString() {
     StringBuffer buffer = new StringBuffer();
     appendTo(buffer);
@@ -2337,6 +2400,15 @@
     }
     return types;
   }
+
+  @override
+  DartType resolveToBound(DartType objectType) {
+    if (element.bound == null) {
+      return objectType;
+    }
+
+    return element.bound.resolveToBound(objectType);
+  }
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/dart/scanner/reader.dart b/pkg/analyzer/lib/src/dart/scanner/reader.dart
new file mode 100644
index 0000000..1f5d87d
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/scanner/reader.dart
@@ -0,0 +1,187 @@
+// 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.dart.scanner.reader;
+
+/**
+ * A [CharacterReader] that reads a range of characters from another character
+ * reader.
+ */
+class CharacterRangeReader extends CharacterReader {
+  /**
+   * The reader from which the characters are actually being read.
+   */
+  final CharacterReader baseReader;
+
+  /**
+   * The last character to be read.
+   */
+  final int endIndex;
+
+  /**
+   * Initialize a newly created reader to read the characters from the given
+   * [baseReader] between the [startIndex] inclusive to [endIndex] exclusive.
+   */
+  CharacterRangeReader(this.baseReader, int startIndex, this.endIndex) {
+    baseReader.offset = startIndex - 1;
+  }
+
+  @override
+  int get offset => baseReader.offset;
+
+  @override
+  void set offset(int offset) {
+    baseReader.offset = offset;
+  }
+
+  @override
+  int advance() {
+    if (baseReader.offset + 1 >= endIndex) {
+      return -1;
+    }
+    return baseReader.advance();
+  }
+
+  @override
+  String getString(int start, int endDelta) =>
+      baseReader.getString(start, endDelta);
+
+  @override
+  int peek() {
+    if (baseReader.offset + 1 >= endIndex) {
+      return -1;
+    }
+    return baseReader.peek();
+  }
+}
+
+/**
+ * An object used by the scanner to read the characters to be scanned.
+ */
+abstract class CharacterReader {
+  /**
+   * The current offset relative to the beginning of the source. Return the
+   * initial offset if the scanner has not yet scanned the source code, and one
+   * (1) past the end of the source code if the entire source code has been
+   * scanned.
+   */
+  int get offset;
+
+  /**
+   * Set the current offset relative to the beginning of the source to the given
+   * [offset]. The new offset must be between the initial offset and one (1)
+   * past the end of the source code.
+   */
+  void set offset(int offset);
+
+  /**
+   * Advance the current position and return the character at the new current
+   * position.
+   */
+  int advance();
+
+  /**
+   * Return the substring of the source code between the [start] offset and the
+   * modified current position. The current position is modified by adding the
+   * [endDelta], which is the number of characters after the current location to
+   * be included in the string, or the number of characters before the current
+   * location to be excluded if the offset is negative.
+   */
+  String getString(int start, int endDelta);
+
+  /**
+   * Return the character at the current position without changing the current
+   * position.
+   */
+  int peek();
+}
+
+/**
+ * A [CharacterReader] that reads characters from a character sequence.
+ */
+class CharSequenceReader implements CharacterReader {
+  /**
+   * The sequence from which characters will be read.
+   */
+  final String _sequence;
+
+  /**
+   * The number of characters in the string.
+   */
+  int _stringLength = 0;
+
+  /**
+   * The index, relative to the string, of the last character that was read.
+   */
+  int _charOffset = 0;
+
+  /**
+   * Initialize a newly created reader to read the characters in the given
+   * [_sequence].
+   */
+  CharSequenceReader(this._sequence) {
+    this._stringLength = _sequence.length;
+    this._charOffset = -1;
+  }
+
+  @override
+  int get offset => _charOffset;
+
+  @override
+  void set offset(int offset) {
+    _charOffset = offset;
+  }
+
+  @override
+  int advance() {
+    if (_charOffset + 1 >= _stringLength) {
+      return -1;
+    }
+    return _sequence.codeUnitAt(++_charOffset);
+  }
+
+  @override
+  String getString(int start, int endDelta) =>
+      _sequence.substring(start, _charOffset + 1 + endDelta).toString();
+
+  @override
+  int peek() {
+    if (_charOffset + 1 >= _stringLength) {
+      return -1;
+    }
+    return _sequence.codeUnitAt(_charOffset + 1);
+  }
+}
+
+/**
+ * A [CharacterReader] that reads characters from a character sequence, but adds
+ * a delta when reporting the current character offset so that the character
+ * sequence can be a subsequence from a larger sequence.
+ */
+class SubSequenceReader extends CharSequenceReader {
+  /**
+   * The offset from the beginning of the file to the beginning of the source
+   * being scanned.
+   */
+  final int _offsetDelta;
+
+  /**
+   * Initialize a newly created reader to read the characters in the given
+   * [sequence]. The [_offsetDelta] is the offset from the beginning of the file
+   * to the beginning of the source being scanned
+   */
+  SubSequenceReader(String sequence, this._offsetDelta) : super(sequence);
+
+  @override
+  int get offset => _offsetDelta + super.offset;
+
+  @override
+  void set offset(int offset) {
+    super.offset = offset - _offsetDelta;
+  }
+
+  @override
+  String getString(int start, int endDelta) =>
+      super.getString(start - _offsetDelta, endDelta);
+}
diff --git a/pkg/analyzer/lib/src/dart/scanner/scanner.dart b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
new file mode 100644
index 0000000..7814eb7
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
@@ -0,0 +1,1375 @@
+// 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.dart.scanner.scanner;
+
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/generated/source.dart';
+
+/**
+ * A state in a state machine used to scan keywords.
+ */
+class KeywordState {
+  /**
+   * An empty transition table used by leaf states.
+   */
+  static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>(26);
+
+  /**
+   * The initial state in the state machine.
+   */
+  static final KeywordState KEYWORD_STATE = _createKeywordStateTable();
+
+  /**
+   * A table mapping characters to the states to which those characters will
+   * transition. (The index into the array is the offset from the character
+   * `'a'` to the transitioning character.)
+   */
+  final List<KeywordState> _table;
+
+  /**
+   * The keyword that is recognized by this state, or `null` if this state is
+   * not a terminal state.
+   */
+  Keyword _keyword;
+
+  /**
+   * Initialize a newly created state to have the given transitions and to
+   * recognize the keyword with the given [syntax].
+   */
+  KeywordState(this._table, String syntax) {
+    this._keyword = (syntax == null) ? null : Keyword.keywords[syntax];
+  }
+
+  /**
+   * Return the keyword that was recognized by this state, or `null` if this
+   * state does not recognized a keyword.
+   */
+  Keyword keyword() => _keyword;
+
+  /**
+   * Return the state that follows this state on a transition of the given
+   * [character], or `null` if there is no valid state reachable from this state
+   * with such a transition.
+   */
+  KeywordState next(int character) => _table[character - 0x61];
+
+  /**
+   * Create the next state in the state machine where we have already recognized
+   * the subset of strings in the given array of [strings] starting at the given
+   * [offset] and having the given [length]. All of these strings have a common
+   * prefix and the next character is at the given [start] index.
+   */
+  static KeywordState _computeKeywordStateTable(
+      int start, List<String> strings, int offset, int length) {
+    List<KeywordState> result = new List<KeywordState>(26);
+    assert(length != 0);
+    int chunk = 0x0;
+    int chunkStart = -1;
+    bool isLeaf = false;
+    for (int i = offset; i < offset + length; i++) {
+      if (strings[i].length == start) {
+        isLeaf = true;
+      }
+      if (strings[i].length > start) {
+        int c = strings[i].codeUnitAt(start);
+        if (chunk != c) {
+          if (chunkStart != -1) {
+            result[chunk - 0x61] = _computeKeywordStateTable(
+                start + 1, strings, chunkStart, i - chunkStart);
+          }
+          chunkStart = i;
+          chunk = c;
+        }
+      }
+    }
+    if (chunkStart != -1) {
+      assert(result[chunk - 0x61] == null);
+      result[chunk - 0x61] = _computeKeywordStateTable(
+          start + 1, strings, chunkStart, offset + length - chunkStart);
+    } else {
+      assert(length == 1);
+      return new KeywordState(_EMPTY_TABLE, strings[offset]);
+    }
+    if (isLeaf) {
+      return new KeywordState(result, strings[offset]);
+    } else {
+      return new KeywordState(result, null);
+    }
+  }
+
+  /**
+   * Create and return the initial state in the state machine.
+   */
+  static KeywordState _createKeywordStateTable() {
+    List<Keyword> values = Keyword.values;
+    List<String> strings = new List<String>(values.length);
+    for (int i = 0; i < values.length; i++) {
+      strings[i] = values[i].syntax;
+    }
+    strings.sort();
+    return _computeKeywordStateTable(0, strings, 0, strings.length);
+  }
+}
+
+/**
+ * The class `Scanner` implements a scanner for Dart code.
+ *
+ * The lexical structure of Dart is ambiguous without knowledge of the context
+ * in which a token is being scanned. For example, without context we cannot
+ * determine whether source of the form "<<" should be scanned as a single
+ * left-shift operator or as two left angle brackets. This scanner does not have
+ * any context, so it always resolves such conflicts by scanning the longest
+ * possible token.
+ */
+class Scanner {
+  /**
+   * The source being scanned.
+   */
+  final Source source;
+
+  /**
+   * The reader used to access the characters in the source.
+   */
+  final CharacterReader _reader;
+
+  /**
+   * The error listener that will be informed of any errors that are found
+   * during the scan.
+   */
+  final AnalysisErrorListener _errorListener;
+
+  /**
+   * The flag specifying whether documentation comments should be parsed.
+   */
+  bool _preserveComments = true;
+
+  /**
+   * The token pointing to the head of the linked list of tokens.
+   */
+  Token _tokens;
+
+  /**
+   * The last token that was scanned.
+   */
+  Token _tail;
+
+  /**
+   * The first token in the list of comment tokens found since the last
+   * non-comment token.
+   */
+  Token _firstComment;
+
+  /**
+   * The last token in the list of comment tokens found since the last
+   * non-comment token.
+   */
+  Token _lastComment;
+
+  /**
+   * The index of the first character of the current token.
+   */
+  int _tokenStart = 0;
+
+  /**
+   * A list containing the offsets of the first character of each line in the
+   * source code.
+   */
+  List<int> _lineStarts = new List<int>();
+
+  /**
+   * A list, treated something like a stack, of tokens representing the
+   * beginning of a matched pair. It is used to pair the end tokens with the
+   * begin tokens.
+   */
+  List<BeginToken> _groupingStack = new List<BeginToken>();
+
+  /**
+   * The index of the last item in the [_groupingStack], or `-1` if the stack is
+   * empty.
+   */
+  int _stackEnd = -1;
+
+  /**
+   * A flag indicating whether any unmatched groups were found during the parse.
+   */
+  bool _hasUnmatchedGroups = false;
+
+  /**
+   * A flag indicating whether to parse generic method comments, of the form
+   * `/*=T*/` and `/*<T>*/`.
+   */
+  bool scanGenericMethodComments = false;
+
+  /**
+   * Initialize a newly created scanner to scan characters from the given
+   * [source]. The given character [_reader] will be used to read the characters
+   * in the source. The given [_errorListener] will be informed of any errors
+   * that are found.
+   */
+  Scanner(this.source, this._reader, this._errorListener) {
+    _tokens = new Token(TokenType.EOF, -1);
+    _tokens.setNext(_tokens);
+    _tail = _tokens;
+    _tokenStart = -1;
+    _lineStarts.add(0);
+  }
+
+  /**
+   * Return the first token in the token stream that was scanned.
+   */
+  Token get firstToken => _tokens.next;
+
+  /**
+   * Return `true` if any unmatched groups were found during the parse.
+   */
+  bool get hasUnmatchedGroups => _hasUnmatchedGroups;
+
+  /**
+   * Return an array containing the offsets of the first character of each line
+   * in the source code.
+   */
+  List<int> get lineStarts => _lineStarts;
+
+  /**
+   * Set whether documentation tokens should be preserved.
+   */
+  void set preserveComments(bool preserveComments) {
+    this._preserveComments = preserveComments;
+  }
+
+  /**
+   * Return the last token that was scanned.
+   */
+  Token get tail => _tail;
+
+  /**
+   * Append the given [token] to the end of the token stream being scanned. This
+   * method is intended to be used by subclasses that copy existing tokens and
+   * should not normally be used because it will fail to correctly associate any
+   * comments with the token being passed in.
+   */
+  void appendToken(Token token) {
+    _tail = _tail.setNext(token);
+  }
+
+  int bigSwitch(int next) {
+    _beginToken();
+    if (next == 0xD) {
+      // '\r'
+      next = _reader.advance();
+      if (next == 0xA) {
+        // '\n'
+        next = _reader.advance();
+      }
+      recordStartOfLine();
+      return next;
+    } else if (next == 0xA) {
+      // '\n'
+      next = _reader.advance();
+      recordStartOfLine();
+      return next;
+    } else if (next == 0x9 || next == 0x20) {
+      // '\t' || ' '
+      return _reader.advance();
+    }
+    if (next == 0x72) {
+      // 'r'
+      int peek = _reader.peek();
+      if (peek == 0x22 || peek == 0x27) {
+        // '"' || "'"
+        int start = _reader.offset;
+        return _tokenizeString(_reader.advance(), start, true);
+      }
+    }
+    if (0x61 <= next && next <= 0x7A) {
+      // 'a'-'z'
+      return _tokenizeKeywordOrIdentifier(next, true);
+    }
+    if ((0x41 <= next && next <= 0x5A) || next == 0x5F || next == 0x24) {
+      // 'A'-'Z' || '_' || '$'
+      return _tokenizeIdentifier(next, _reader.offset, true);
+    }
+    if (next == 0x3C) {
+      // '<'
+      return _tokenizeLessThan(next);
+    }
+    if (next == 0x3E) {
+      // '>'
+      return _tokenizeGreaterThan(next);
+    }
+    if (next == 0x3D) {
+      // '='
+      return _tokenizeEquals(next);
+    }
+    if (next == 0x21) {
+      // '!'
+      return _tokenizeExclamation(next);
+    }
+    if (next == 0x2B) {
+      // '+'
+      return _tokenizePlus(next);
+    }
+    if (next == 0x2D) {
+      // '-'
+      return _tokenizeMinus(next);
+    }
+    if (next == 0x2A) {
+      // '*'
+      return _tokenizeMultiply(next);
+    }
+    if (next == 0x25) {
+      // '%'
+      return _tokenizePercent(next);
+    }
+    if (next == 0x26) {
+      // '&'
+      return _tokenizeAmpersand(next);
+    }
+    if (next == 0x7C) {
+      // '|'
+      return _tokenizeBar(next);
+    }
+    if (next == 0x5E) {
+      // '^'
+      return _tokenizeCaret(next);
+    }
+    if (next == 0x5B) {
+      // '['
+      return _tokenizeOpenSquareBracket(next);
+    }
+    if (next == 0x7E) {
+      // '~'
+      return _tokenizeTilde(next);
+    }
+    if (next == 0x5C) {
+      // '\\'
+      _appendTokenOfType(TokenType.BACKSLASH);
+      return _reader.advance();
+    }
+    if (next == 0x23) {
+      // '#'
+      return _tokenizeTag(next);
+    }
+    if (next == 0x28) {
+      // '('
+      _appendBeginToken(TokenType.OPEN_PAREN);
+      return _reader.advance();
+    }
+    if (next == 0x29) {
+      // ')'
+      _appendEndToken(TokenType.CLOSE_PAREN, TokenType.OPEN_PAREN);
+      return _reader.advance();
+    }
+    if (next == 0x2C) {
+      // ','
+      _appendTokenOfType(TokenType.COMMA);
+      return _reader.advance();
+    }
+    if (next == 0x3A) {
+      // ':'
+      _appendTokenOfType(TokenType.COLON);
+      return _reader.advance();
+    }
+    if (next == 0x3B) {
+      // ';'
+      _appendTokenOfType(TokenType.SEMICOLON);
+      return _reader.advance();
+    }
+    if (next == 0x3F) {
+      // '?'
+      return _tokenizeQuestion();
+    }
+    if (next == 0x5D) {
+      // ']'
+      _appendEndToken(
+          TokenType.CLOSE_SQUARE_BRACKET, TokenType.OPEN_SQUARE_BRACKET);
+      return _reader.advance();
+    }
+    if (next == 0x60) {
+      // '`'
+      _appendTokenOfType(TokenType.BACKPING);
+      return _reader.advance();
+    }
+    if (next == 0x7B) {
+      // '{'
+      _appendBeginToken(TokenType.OPEN_CURLY_BRACKET);
+      return _reader.advance();
+    }
+    if (next == 0x7D) {
+      // '}'
+      _appendEndToken(
+          TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET);
+      return _reader.advance();
+    }
+    if (next == 0x2F) {
+      // '/'
+      return _tokenizeSlashOrComment(next);
+    }
+    if (next == 0x40) {
+      // '@'
+      _appendTokenOfType(TokenType.AT);
+      return _reader.advance();
+    }
+    if (next == 0x22 || next == 0x27) {
+      // '"' || "'"
+      return _tokenizeString(next, _reader.offset, false);
+    }
+    if (next == 0x2E) {
+      // '.'
+      return _tokenizeDotOrNumber(next);
+    }
+    if (next == 0x30) {
+      // '0'
+      return _tokenizeHexOrNumber(next);
+    }
+    if (0x31 <= next && next <= 0x39) {
+      // '1'-'9'
+      return _tokenizeNumber(next);
+    }
+    if (next == -1) {
+      // EOF
+      return -1;
+    }
+    _reportError(ScannerErrorCode.ILLEGAL_CHARACTER, [next]);
+    return _reader.advance();
+  }
+
+  /**
+   * Record the fact that we are at the beginning of a new line in the source.
+   */
+  void recordStartOfLine() {
+    _lineStarts.add(_reader.offset);
+  }
+
+  /**
+   * Record that the source begins on the given [line] and [column] at the
+   * current offset as given by the reader. Both the line and the column are
+   * one-based indexes. The line starts for lines before the given line will not
+   * be correct.
+   *
+   * This method must be invoked at most one time and must be invoked before
+   * scanning begins. The values provided must be sensible. The results are
+   * undefined if these conditions are violated.
+   */
+  void setSourceStart(int line, int column) {
+    int offset = _reader.offset;
+    if (line < 1 || column < 1 || offset < 0 || (line + column - 2) >= offset) {
+      return;
+    }
+    for (int i = 2; i < line; i++) {
+      _lineStarts.add(1);
+    }
+    _lineStarts.add(offset - column + 1);
+  }
+
+  /**
+   * Scan the source code to produce a list of tokens representing the source,
+   * and return the first token in the list of tokens that were produced.
+   */
+  Token tokenize() {
+    int next = _reader.advance();
+    while (next != -1) {
+      next = bigSwitch(next);
+    }
+    _appendEofToken();
+    return firstToken;
+  }
+
+  void _appendBeginToken(TokenType type) {
+    BeginToken token;
+    if (_firstComment == null) {
+      token = new BeginToken(type, _tokenStart);
+    } else {
+      token = new BeginTokenWithComment(type, _tokenStart, _firstComment);
+      _firstComment = null;
+      _lastComment = null;
+    }
+    _tail = _tail.setNext(token);
+    _groupingStack.add(token);
+    _stackEnd++;
+  }
+
+  void _appendCommentToken(TokenType type, String value) {
+    CommentToken token = null;
+    TokenType genericComment = _matchGenericMethodCommentType(value);
+    if (genericComment != null) {
+      token = new CommentToken(genericComment, value, _tokenStart);
+    } else if (!_preserveComments) {
+      // Ignore comment tokens if client specified that it doesn't need them.
+      return;
+    } else {
+      // OK, remember comment tokens.
+      if (_isDocumentationComment(value)) {
+        token = new DocumentationCommentToken(type, value, _tokenStart);
+      } else {
+        token = new CommentToken(type, value, _tokenStart);
+      }
+    }
+    if (_firstComment == null) {
+      _firstComment = token;
+      _lastComment = _firstComment;
+    } else {
+      _lastComment = _lastComment.setNext(token);
+    }
+  }
+
+  void _appendEndToken(TokenType type, TokenType beginType) {
+    Token token;
+    if (_firstComment == null) {
+      token = new Token(type, _tokenStart);
+    } else {
+      token = new TokenWithComment(type, _tokenStart, _firstComment);
+      _firstComment = null;
+      _lastComment = null;
+    }
+    _tail = _tail.setNext(token);
+    if (_stackEnd >= 0) {
+      BeginToken begin = _groupingStack[_stackEnd];
+      if (begin.type == beginType) {
+        begin.endToken = token;
+        _groupingStack.removeAt(_stackEnd--);
+      }
+    }
+  }
+
+  void _appendEofToken() {
+    Token eofToken;
+    if (_firstComment == null) {
+      eofToken = new Token(TokenType.EOF, _reader.offset + 1);
+    } else {
+      eofToken = new TokenWithComment(
+          TokenType.EOF, _reader.offset + 1, _firstComment);
+      _firstComment = null;
+      _lastComment = null;
+    }
+    // The EOF token points to itself so that there is always infinite
+    // look-ahead.
+    eofToken.setNext(eofToken);
+    _tail = _tail.setNext(eofToken);
+    if (_stackEnd >= 0) {
+      _hasUnmatchedGroups = true;
+      // TODO(brianwilkerson) Fix the ungrouped tokens?
+    }
+  }
+
+  void _appendKeywordToken(Keyword keyword) {
+    if (_firstComment == null) {
+      _tail = _tail.setNext(new KeywordToken(keyword, _tokenStart));
+    } else {
+      _tail = _tail.setNext(
+          new KeywordTokenWithComment(keyword, _tokenStart, _firstComment));
+      _firstComment = null;
+      _lastComment = null;
+    }
+  }
+
+  void _appendStringToken(TokenType type, String value) {
+    if (_firstComment == null) {
+      _tail = _tail.setNext(new StringToken(type, value, _tokenStart));
+    } else {
+      _tail = _tail.setNext(
+          new StringTokenWithComment(type, value, _tokenStart, _firstComment));
+      _firstComment = null;
+      _lastComment = null;
+    }
+  }
+
+  void _appendStringTokenWithOffset(TokenType type, String value, int offset) {
+    if (_firstComment == null) {
+      _tail = _tail.setNext(new StringToken(type, value, _tokenStart + offset));
+    } else {
+      _tail = _tail.setNext(new StringTokenWithComment(
+          type, value, _tokenStart + offset, _firstComment));
+      _firstComment = null;
+      _lastComment = null;
+    }
+  }
+
+  void _appendTokenOfType(TokenType type) {
+    if (_firstComment == null) {
+      _tail = _tail.setNext(new Token(type, _tokenStart));
+    } else {
+      _tail =
+          _tail.setNext(new TokenWithComment(type, _tokenStart, _firstComment));
+      _firstComment = null;
+      _lastComment = null;
+    }
+  }
+
+  void _appendTokenOfTypeWithOffset(TokenType type, int offset) {
+    if (_firstComment == null) {
+      _tail = _tail.setNext(new Token(type, offset));
+    } else {
+      _tail = _tail.setNext(new TokenWithComment(type, offset, _firstComment));
+      _firstComment = null;
+      _lastComment = null;
+    }
+  }
+
+  void _beginToken() {
+    _tokenStart = _reader.offset;
+  }
+
+  /**
+   * Return the beginning token corresponding to a closing brace that was found
+   * while scanning inside a string interpolation expression. Tokens that cannot
+   * be matched with the closing brace will be dropped from the stack.
+   */
+  BeginToken _findTokenMatchingClosingBraceInInterpolationExpression() {
+    while (_stackEnd >= 0) {
+      BeginToken begin = _groupingStack[_stackEnd];
+      if (begin.type == TokenType.OPEN_CURLY_BRACKET ||
+          begin.type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
+        return begin;
+      }
+      _hasUnmatchedGroups = true;
+      _groupingStack.removeAt(_stackEnd--);
+    }
+    //
+    // We should never get to this point because we wouldn't be inside a string
+    // interpolation expression unless we had previously found the start of the
+    // expression.
+    //
+    return null;
+  }
+
+  /**
+   * Checks if [value] is the start of a generic method type annotation comment.
+   *
+   * This can either be of the form `/*<T>*/` or `/*=T*/`. The token type is
+   * returned, or null if it was not a generic method comment.
+   */
+  TokenType _matchGenericMethodCommentType(String value) {
+    if (scanGenericMethodComments) {
+      // Match /*< and >*/
+      if (StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x3C) &&
+          StringUtilities.endsWith3(value, 0x3E, 0x2A, 0x2F)) {
+        return TokenType.GENERIC_METHOD_TYPE_LIST;
+      }
+      // Match /*=
+      if (StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x3D)) {
+        return TokenType.GENERIC_METHOD_TYPE_ASSIGN;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Report an error at the current offset. The [errorCode] is the error code
+   * indicating the nature of the error. The [arguments] are any arguments
+   * needed to complete the error message
+   */
+  void _reportError(ScannerErrorCode errorCode, [List<Object> arguments]) {
+    _errorListener.onError(
+        new AnalysisError(source, _reader.offset, 1, errorCode, arguments));
+  }
+
+  int _select(int choice, TokenType yesType, TokenType noType) {
+    int next = _reader.advance();
+    if (next == choice) {
+      _appendTokenOfType(yesType);
+      return _reader.advance();
+    } else {
+      _appendTokenOfType(noType);
+      return next;
+    }
+  }
+
+  int _selectWithOffset(
+      int choice, TokenType yesType, TokenType noType, int offset) {
+    int next = _reader.advance();
+    if (next == choice) {
+      _appendTokenOfTypeWithOffset(yesType, offset);
+      return _reader.advance();
+    } else {
+      _appendTokenOfTypeWithOffset(noType, offset);
+      return next;
+    }
+  }
+
+  int _tokenizeAmpersand(int next) {
+    // && &= &
+    next = _reader.advance();
+    if (next == 0x26) {
+      _appendTokenOfType(TokenType.AMPERSAND_AMPERSAND);
+      return _reader.advance();
+    } else if (next == 0x3D) {
+      _appendTokenOfType(TokenType.AMPERSAND_EQ);
+      return _reader.advance();
+    } else {
+      _appendTokenOfType(TokenType.AMPERSAND);
+      return next;
+    }
+  }
+
+  int _tokenizeBar(int next) {
+    // | || |=
+    next = _reader.advance();
+    if (next == 0x7C) {
+      _appendTokenOfType(TokenType.BAR_BAR);
+      return _reader.advance();
+    } else if (next == 0x3D) {
+      _appendTokenOfType(TokenType.BAR_EQ);
+      return _reader.advance();
+    } else {
+      _appendTokenOfType(TokenType.BAR);
+      return next;
+    }
+  }
+
+  int _tokenizeCaret(int next) =>
+      _select(0x3D, TokenType.CARET_EQ, TokenType.CARET);
+
+  int _tokenizeDotOrNumber(int next) {
+    int start = _reader.offset;
+    next = _reader.advance();
+    if (0x30 <= next && next <= 0x39) {
+      return _tokenizeFractionPart(next, start);
+    } else if (0x2E == next) {
+      return _select(
+          0x2E, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PERIOD);
+    } else {
+      _appendTokenOfType(TokenType.PERIOD);
+      return next;
+    }
+  }
+
+  int _tokenizeEquals(int next) {
+    // = == =>
+    next = _reader.advance();
+    if (next == 0x3D) {
+      _appendTokenOfType(TokenType.EQ_EQ);
+      return _reader.advance();
+    } else if (next == 0x3E) {
+      _appendTokenOfType(TokenType.FUNCTION);
+      return _reader.advance();
+    }
+    _appendTokenOfType(TokenType.EQ);
+    return next;
+  }
+
+  int _tokenizeExclamation(int next) {
+    // ! !=
+    next = _reader.advance();
+    if (next == 0x3D) {
+      _appendTokenOfType(TokenType.BANG_EQ);
+      return _reader.advance();
+    }
+    _appendTokenOfType(TokenType.BANG);
+    return next;
+  }
+
+  int _tokenizeExponent(int next) {
+    if (next == 0x2B || next == 0x2D) {
+      next = _reader.advance();
+    }
+    bool hasDigits = false;
+    while (true) {
+      if (0x30 <= next && next <= 0x39) {
+        hasDigits = true;
+      } else {
+        if (!hasDigits) {
+          _reportError(ScannerErrorCode.MISSING_DIGIT);
+        }
+        return next;
+      }
+      next = _reader.advance();
+    }
+  }
+
+  int _tokenizeFractionPart(int next, int start) {
+    bool done = false;
+    bool hasDigit = false;
+    LOOP: while (!done) {
+      if (0x30 <= next && next <= 0x39) {
+        hasDigit = true;
+      } else if (0x65 == next || 0x45 == next) {
+        hasDigit = true;
+        next = _tokenizeExponent(_reader.advance());
+        done = true;
+        continue LOOP;
+      } else {
+        done = true;
+        continue LOOP;
+      }
+      next = _reader.advance();
+    }
+    if (!hasDigit) {
+      _appendStringToken(TokenType.INT, _reader.getString(start, -2));
+      if (0x2E == next) {
+        return _selectWithOffset(0x2E, TokenType.PERIOD_PERIOD_PERIOD,
+            TokenType.PERIOD_PERIOD, _reader.offset - 1);
+      }
+      _appendTokenOfTypeWithOffset(TokenType.PERIOD, _reader.offset - 1);
+      return bigSwitch(next);
+    }
+    _appendStringToken(
+        TokenType.DOUBLE, _reader.getString(start, next < 0 ? 0 : -1));
+    return next;
+  }
+
+  int _tokenizeGreaterThan(int next) {
+    // > >= >> >>=
+    next = _reader.advance();
+    if (0x3D == next) {
+      _appendTokenOfType(TokenType.GT_EQ);
+      return _reader.advance();
+    } else if (0x3E == next) {
+      next = _reader.advance();
+      if (0x3D == next) {
+        _appendTokenOfType(TokenType.GT_GT_EQ);
+        return _reader.advance();
+      } else {
+        _appendTokenOfType(TokenType.GT_GT);
+        return next;
+      }
+    } else {
+      _appendTokenOfType(TokenType.GT);
+      return next;
+    }
+  }
+
+  int _tokenizeHex(int next) {
+    int start = _reader.offset - 1;
+    bool hasDigits = false;
+    while (true) {
+      next = _reader.advance();
+      if ((0x30 <= next && next <= 0x39) ||
+          (0x41 <= next && next <= 0x46) ||
+          (0x61 <= next && next <= 0x66)) {
+        hasDigits = true;
+      } else {
+        if (!hasDigits) {
+          _reportError(ScannerErrorCode.MISSING_HEX_DIGIT);
+        }
+        _appendStringToken(
+            TokenType.HEXADECIMAL, _reader.getString(start, next < 0 ? 0 : -1));
+        return next;
+      }
+    }
+  }
+
+  int _tokenizeHexOrNumber(int next) {
+    int x = _reader.peek();
+    if (x == 0x78 || x == 0x58) {
+      _reader.advance();
+      return _tokenizeHex(x);
+    }
+    return _tokenizeNumber(next);
+  }
+
+  int _tokenizeIdentifier(int next, int start, bool allowDollar) {
+    while ((0x61 <= next && next <= 0x7A) ||
+        (0x41 <= next && next <= 0x5A) ||
+        (0x30 <= next && next <= 0x39) ||
+        next == 0x5F ||
+        (next == 0x24 && allowDollar)) {
+      next = _reader.advance();
+    }
+    _appendStringToken(
+        TokenType.IDENTIFIER, _reader.getString(start, next < 0 ? 0 : -1));
+    return next;
+  }
+
+  int _tokenizeInterpolatedExpression(int next, int start) {
+    _appendBeginToken(TokenType.STRING_INTERPOLATION_EXPRESSION);
+    next = _reader.advance();
+    while (next != -1) {
+      if (next == 0x7D) {
+        BeginToken begin =
+            _findTokenMatchingClosingBraceInInterpolationExpression();
+        if (begin == null) {
+          _beginToken();
+          _appendTokenOfType(TokenType.CLOSE_CURLY_BRACKET);
+          next = _reader.advance();
+          _beginToken();
+          return next;
+        } else if (begin.type == TokenType.OPEN_CURLY_BRACKET) {
+          _beginToken();
+          _appendEndToken(
+              TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET);
+          next = _reader.advance();
+          _beginToken();
+        } else if (begin.type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
+          _beginToken();
+          _appendEndToken(TokenType.CLOSE_CURLY_BRACKET,
+              TokenType.STRING_INTERPOLATION_EXPRESSION);
+          next = _reader.advance();
+          _beginToken();
+          return next;
+        }
+      } else {
+        next = bigSwitch(next);
+      }
+    }
+    return next;
+  }
+
+  int _tokenizeInterpolatedIdentifier(int next, int start) {
+    _appendStringTokenWithOffset(
+        TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 0);
+    if ((0x41 <= next && next <= 0x5A) ||
+        (0x61 <= next && next <= 0x7A) ||
+        next == 0x5F) {
+      _beginToken();
+      next = _tokenizeKeywordOrIdentifier(next, false);
+    }
+    _beginToken();
+    return next;
+  }
+
+  int _tokenizeKeywordOrIdentifier(int next, bool allowDollar) {
+    KeywordState state = KeywordState.KEYWORD_STATE;
+    int start = _reader.offset;
+    while (state != null && 0x61 <= next && next <= 0x7A) {
+      state = state.next(next);
+      next = _reader.advance();
+    }
+    if (state == null || state.keyword() == null) {
+      return _tokenizeIdentifier(next, start, allowDollar);
+    }
+    if ((0x41 <= next && next <= 0x5A) ||
+        (0x30 <= next && next <= 0x39) ||
+        next == 0x5F ||
+        next == 0x24) {
+      return _tokenizeIdentifier(next, start, allowDollar);
+    } else if (next < 128) {
+      _appendKeywordToken(state.keyword());
+      return next;
+    } else {
+      return _tokenizeIdentifier(next, start, allowDollar);
+    }
+  }
+
+  int _tokenizeLessThan(int next) {
+    // < <= << <<=
+    next = _reader.advance();
+    if (0x3D == next) {
+      _appendTokenOfType(TokenType.LT_EQ);
+      return _reader.advance();
+    } else if (0x3C == next) {
+      return _select(0x3D, TokenType.LT_LT_EQ, TokenType.LT_LT);
+    } else {
+      _appendTokenOfType(TokenType.LT);
+      return next;
+    }
+  }
+
+  int _tokenizeMinus(int next) {
+    // - -- -=
+    next = _reader.advance();
+    if (next == 0x2D) {
+      _appendTokenOfType(TokenType.MINUS_MINUS);
+      return _reader.advance();
+    } else if (next == 0x3D) {
+      _appendTokenOfType(TokenType.MINUS_EQ);
+      return _reader.advance();
+    } else {
+      _appendTokenOfType(TokenType.MINUS);
+      return next;
+    }
+  }
+
+  int _tokenizeMultiLineComment(int next) {
+    int nesting = 1;
+    next = _reader.advance();
+    while (true) {
+      if (-1 == next) {
+        _reportError(ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT);
+        _appendCommentToken(
+            TokenType.MULTI_LINE_COMMENT, _reader.getString(_tokenStart, 0));
+        return next;
+      } else if (0x2A == next) {
+        next = _reader.advance();
+        if (0x2F == next) {
+          --nesting;
+          if (0 == nesting) {
+            _appendCommentToken(TokenType.MULTI_LINE_COMMENT,
+                _reader.getString(_tokenStart, 0));
+            return _reader.advance();
+          } else {
+            next = _reader.advance();
+          }
+        }
+      } else if (0x2F == next) {
+        next = _reader.advance();
+        if (0x2A == next) {
+          next = _reader.advance();
+          ++nesting;
+        }
+      } else if (next == 0xD) {
+        next = _reader.advance();
+        if (next == 0xA) {
+          next = _reader.advance();
+        }
+        recordStartOfLine();
+      } else if (next == 0xA) {
+        next = _reader.advance();
+        recordStartOfLine();
+      } else {
+        next = _reader.advance();
+      }
+    }
+  }
+
+  int _tokenizeMultiLineRawString(int quoteChar, int start) {
+    int next = _reader.advance();
+    outer: while (next != -1) {
+      while (next != quoteChar) {
+        if (next == -1) {
+          break outer;
+        } else if (next == 0xD) {
+          next = _reader.advance();
+          if (next == 0xA) {
+            next = _reader.advance();
+          }
+          recordStartOfLine();
+        } else if (next == 0xA) {
+          next = _reader.advance();
+          recordStartOfLine();
+        } else {
+          next = _reader.advance();
+        }
+      }
+      next = _reader.advance();
+      if (next == quoteChar) {
+        next = _reader.advance();
+        if (next == quoteChar) {
+          _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
+          return _reader.advance();
+        }
+      }
+    }
+    _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
+    _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
+    return _reader.advance();
+  }
+
+  int _tokenizeMultiLineString(int quoteChar, int start, bool raw) {
+    if (raw) {
+      return _tokenizeMultiLineRawString(quoteChar, start);
+    }
+    int next = _reader.advance();
+    while (next != -1) {
+      if (next == 0x24) {
+        _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
+        next = _tokenizeStringInterpolation(start);
+        _beginToken();
+        start = _reader.offset;
+        continue;
+      }
+      if (next == quoteChar) {
+        next = _reader.advance();
+        if (next == quoteChar) {
+          next = _reader.advance();
+          if (next == quoteChar) {
+            _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
+            return _reader.advance();
+          }
+        }
+        continue;
+      }
+      if (next == 0x5C) {
+        next = _reader.advance();
+        if (next == -1) {
+          break;
+        }
+        if (next == 0xD) {
+          next = _reader.advance();
+          if (next == 0xA) {
+            next = _reader.advance();
+          }
+          recordStartOfLine();
+        } else if (next == 0xA) {
+          recordStartOfLine();
+          next = _reader.advance();
+        } else {
+          next = _reader.advance();
+        }
+      } else if (next == 0xD) {
+        next = _reader.advance();
+        if (next == 0xA) {
+          next = _reader.advance();
+        }
+        recordStartOfLine();
+      } else if (next == 0xA) {
+        recordStartOfLine();
+        next = _reader.advance();
+      } else {
+        next = _reader.advance();
+      }
+    }
+    _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
+    if (start == _reader.offset) {
+      _appendStringTokenWithOffset(TokenType.STRING, "", 1);
+    } else {
+      _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
+    }
+    return _reader.advance();
+  }
+
+  int _tokenizeMultiply(int next) =>
+      _select(0x3D, TokenType.STAR_EQ, TokenType.STAR);
+
+  int _tokenizeNumber(int next) {
+    int start = _reader.offset;
+    while (true) {
+      next = _reader.advance();
+      if (0x30 <= next && next <= 0x39) {
+        continue;
+      } else if (next == 0x2E) {
+        return _tokenizeFractionPart(_reader.advance(), start);
+      } else if (next == 0x65 || next == 0x45) {
+        return _tokenizeFractionPart(next, start);
+      } else {
+        _appendStringToken(
+            TokenType.INT, _reader.getString(start, next < 0 ? 0 : -1));
+        return next;
+      }
+    }
+  }
+
+  int _tokenizeOpenSquareBracket(int next) {
+    // [ []  []=
+    next = _reader.advance();
+    if (next == 0x5D) {
+      return _select(0x3D, TokenType.INDEX_EQ, TokenType.INDEX);
+    } else {
+      _appendBeginToken(TokenType.OPEN_SQUARE_BRACKET);
+      return next;
+    }
+  }
+
+  int _tokenizePercent(int next) =>
+      _select(0x3D, TokenType.PERCENT_EQ, TokenType.PERCENT);
+
+  int _tokenizePlus(int next) {
+    // + ++ +=
+    next = _reader.advance();
+    if (0x2B == next) {
+      _appendTokenOfType(TokenType.PLUS_PLUS);
+      return _reader.advance();
+    } else if (0x3D == next) {
+      _appendTokenOfType(TokenType.PLUS_EQ);
+      return _reader.advance();
+    } else {
+      _appendTokenOfType(TokenType.PLUS);
+      return next;
+    }
+  }
+
+  int _tokenizeQuestion() {
+    // ? ?. ?? ??=
+    int next = _reader.advance();
+    if (next == 0x2E) {
+      // '.'
+      _appendTokenOfType(TokenType.QUESTION_PERIOD);
+      return _reader.advance();
+    } else if (next == 0x3F) {
+      // '?'
+      next = _reader.advance();
+      if (next == 0x3D) {
+        // '='
+        _appendTokenOfType(TokenType.QUESTION_QUESTION_EQ);
+        return _reader.advance();
+      } else {
+        _appendTokenOfType(TokenType.QUESTION_QUESTION);
+        return next;
+      }
+    } else {
+      _appendTokenOfType(TokenType.QUESTION);
+      return next;
+    }
+  }
+
+  int _tokenizeSingleLineComment(int next) {
+    while (true) {
+      next = _reader.advance();
+      if (-1 == next) {
+        _appendCommentToken(
+            TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, 0));
+        return next;
+      } else if (0xA == next || 0xD == next) {
+        _appendCommentToken(
+            TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, -1));
+        return next;
+      }
+    }
+  }
+
+  int _tokenizeSingleLineRawString(int next, int quoteChar, int start) {
+    next = _reader.advance();
+    while (next != -1) {
+      if (next == quoteChar) {
+        _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
+        return _reader.advance();
+      } else if (next == 0xD || next == 0xA) {
+        _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
+        _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
+        return _reader.advance();
+      }
+      next = _reader.advance();
+    }
+    _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
+    _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
+    return _reader.advance();
+  }
+
+  int _tokenizeSingleLineString(int next, int quoteChar, int start) {
+    while (next != quoteChar) {
+      if (next == 0x5C) {
+        next = _reader.advance();
+      } else if (next == 0x24) {
+        _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
+        next = _tokenizeStringInterpolation(start);
+        _beginToken();
+        start = _reader.offset;
+        continue;
+      }
+      if (next <= 0xD && (next == 0xA || next == 0xD || next == -1)) {
+        _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
+        if (start == _reader.offset) {
+          _appendStringTokenWithOffset(TokenType.STRING, "", 1);
+        } else if (next == -1) {
+          _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
+        } else {
+          _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
+        }
+        return _reader.advance();
+      }
+      next = _reader.advance();
+    }
+    _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
+    return _reader.advance();
+  }
+
+  int _tokenizeSlashOrComment(int next) {
+    next = _reader.advance();
+    if (0x2A == next) {
+      return _tokenizeMultiLineComment(next);
+    } else if (0x2F == next) {
+      return _tokenizeSingleLineComment(next);
+    } else if (0x3D == next) {
+      _appendTokenOfType(TokenType.SLASH_EQ);
+      return _reader.advance();
+    } else {
+      _appendTokenOfType(TokenType.SLASH);
+      return next;
+    }
+  }
+
+  int _tokenizeString(int next, int start, bool raw) {
+    int quoteChar = next;
+    next = _reader.advance();
+    if (quoteChar == next) {
+      next = _reader.advance();
+      if (quoteChar == next) {
+        // Multiline string.
+        return _tokenizeMultiLineString(quoteChar, start, raw);
+      } else {
+        // Empty string.
+        _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
+        return next;
+      }
+    }
+    if (raw) {
+      return _tokenizeSingleLineRawString(next, quoteChar, start);
+    } else {
+      return _tokenizeSingleLineString(next, quoteChar, start);
+    }
+  }
+
+  int _tokenizeStringInterpolation(int start) {
+    _beginToken();
+    int next = _reader.advance();
+    if (next == 0x7B) {
+      return _tokenizeInterpolatedExpression(next, start);
+    } else {
+      return _tokenizeInterpolatedIdentifier(next, start);
+    }
+  }
+
+  int _tokenizeTag(int next) {
+    // # or #!.*[\n\r]
+    if (_reader.offset == 0) {
+      if (_reader.peek() == 0x21) {
+        do {
+          next = _reader.advance();
+        } while (next != 0xA && next != 0xD && next > 0);
+        _appendStringToken(
+            TokenType.SCRIPT_TAG, _reader.getString(_tokenStart, 0));
+        return next;
+      }
+    }
+    _appendTokenOfType(TokenType.HASH);
+    return _reader.advance();
+  }
+
+  int _tokenizeTilde(int next) {
+    // ~ ~/ ~/=
+    next = _reader.advance();
+    if (next == 0x2F) {
+      return _select(0x3D, TokenType.TILDE_SLASH_EQ, TokenType.TILDE_SLASH);
+    } else {
+      _appendTokenOfType(TokenType.TILDE);
+      return next;
+    }
+  }
+
+  /**
+   * Checks if [value] is a single-line or multi-line comment.
+   */
+  static bool _isDocumentationComment(String value) {
+    return StringUtilities.startsWith3(value, 0, 0x2F, 0x2F, 0x2F) ||
+        StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x2A);
+  }
+}
+
+/**
+ * The error codes used for errors detected by the scanner.
+ */
+class ScannerErrorCode extends ErrorCode {
+  static const ScannerErrorCode ILLEGAL_CHARACTER =
+      const ScannerErrorCode('ILLEGAL_CHARACTER', "Illegal character {0}");
+
+  static const ScannerErrorCode MISSING_DIGIT =
+      const ScannerErrorCode('MISSING_DIGIT', "Decimal digit expected");
+
+  static const ScannerErrorCode MISSING_HEX_DIGIT =
+      const ScannerErrorCode('MISSING_HEX_DIGIT', "Hexidecimal digit expected");
+
+  static const ScannerErrorCode MISSING_QUOTE =
+      const ScannerErrorCode('MISSING_QUOTE', "Expected quote (' or \")");
+
+  static const ScannerErrorCode UNABLE_GET_CONTENT = const ScannerErrorCode(
+      'UNABLE_GET_CONTENT', "Unable to get content: {0}");
+
+  static const ScannerErrorCode UNTERMINATED_MULTI_LINE_COMMENT =
+      const ScannerErrorCode(
+          'UNTERMINATED_MULTI_LINE_COMMENT', "Unterminated multi-line comment");
+
+  static const ScannerErrorCode UNTERMINATED_STRING_LITERAL =
+      const ScannerErrorCode(
+          'UNTERMINATED_STRING_LITERAL', "Unterminated string literal");
+
+  /**
+   * Initialize a newly created error code to have the given [name]. The message
+   * associated with the error will be created from the given [message]
+   * template. The correction associated with the error will be created from the
+   * given [correction] template.
+   */
+  const ScannerErrorCode(String name, String message, [String correction])
+      : super(name, message, correction);
+
+  @override
+  ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
+
+  @override
+  ErrorType get type => ErrorType.SYNTACTIC_ERROR;
+}
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index 7123029..b2d1e0d 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -7,6 +7,7 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -21,7 +22,6 @@
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
-import 'package:analyzer/src/generated/scanner.dart' show Token, TokenType;
 import 'package:analyzer/src/generated/source.dart' show Source;
 import 'package:analyzer/src/generated/type_system.dart'
     show TypeSystem, TypeSystemImpl;
@@ -31,12 +31,12 @@
 import 'package:analyzer/src/task/dart.dart';
 
 ConstructorElementImpl _getConstructorImpl(ConstructorElement constructor) {
-  if (constructor is ConstructorElementHandle) {
-    constructor = (constructor as ConstructorElementHandle).actualElement;
-  }
   while (constructor is ConstructorMember) {
     constructor = (constructor as ConstructorMember).baseElement;
   }
+  if (constructor is ConstructorElementHandle) {
+    constructor = (constructor as ConstructorElementHandle).actualElement;
+  }
   return constructor;
 }
 
@@ -1248,8 +1248,8 @@
   /**
    * The elements and AST nodes whose constant values need to be computed.
    */
-  HashSet<ConstantEvaluationTarget> constantsToCompute =
-      new HashSet<ConstantEvaluationTarget>();
+  List<ConstantEvaluationTarget> constantsToCompute =
+      <ConstantEvaluationTarget>[];
 
   /**
    * True if instance variables marked as "final" should be treated as "const".
diff --git a/pkg/analyzer/lib/src/generated/element_handle.dart b/pkg/analyzer/lib/src/generated/element_handle.dart
index 03f9137..84b4bdc 100644
--- a/pkg/analyzer/lib/src/generated/element_handle.dart
+++ b/pkg/analyzer/lib/src/generated/element_handle.dart
@@ -915,7 +915,7 @@
       super.enclosingElement as LibraryElement;
 
   @override
-  List<LibraryElement> get importedLibraries => actualElement.importedLibraries;
+  List<LibraryElement> get importedLibraries => LibraryElement.EMPTY_LIST;
 
   @override
   ElementKind get kind => ElementKind.PREFIX;
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index b5cddef..c3c343b 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -7,6 +7,7 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -17,7 +18,6 @@
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart' as sc;
 
 /**
  * An object used by instances of [ResolverVisitor] to resolve references within
@@ -149,10 +149,10 @@
 
   @override
   Object visitAssignmentExpression(AssignmentExpression node) {
-    sc.Token operator = node.operator;
-    sc.TokenType operatorType = operator.type;
-    if (operatorType != sc.TokenType.EQ &&
-        operatorType != sc.TokenType.QUESTION_QUESTION_EQ) {
+    Token operator = node.operator;
+    TokenType operatorType = operator.type;
+    if (operatorType != TokenType.EQ &&
+        operatorType != TokenType.QUESTION_QUESTION_EQ) {
       operatorType = _operatorFromCompoundAssignment(operatorType);
       Expression leftHandSide = node.leftHandSide;
       if (leftHandSide != null) {
@@ -188,11 +188,11 @@
 
   @override
   Object visitBinaryExpression(BinaryExpression node) {
-    sc.Token operator = node.operator;
+    Token operator = node.operator;
     if (operator.isUserDefinableOperator) {
       _resolveBinaryExpression(node, operator.lexeme);
-    } else if (operator.type == sc.TokenType.BANG_EQ) {
-      _resolveBinaryExpression(node, sc.TokenType.EQ_EQ.lexeme);
+    } else if (operator.type == TokenType.BANG_EQ) {
+      _resolveBinaryExpression(node, TokenType.EQ_EQ.lexeme);
     }
     return null;
   }
@@ -494,8 +494,8 @@
     Expression target = node.realTarget;
     DartType staticType = _getStaticType(target);
     DartType propagatedType = _getPropagatedType(target);
-    String getterMethodName = sc.TokenType.INDEX.lexeme;
-    String setterMethodName = sc.TokenType.INDEX_EQ.lexeme;
+    String getterMethodName = TokenType.INDEX.lexeme;
+    String setterMethodName = TokenType.INDEX_EQ.lexeme;
     bool isInGetterContext = node.inGetterContext();
     bool isInSetterContext = node.inSetterContext();
     if (isInGetterContext && isInSetterContext) {
@@ -612,7 +612,7 @@
       propagatedElement = null;
     } else if (methodName.name == FunctionElement.LOAD_LIBRARY_NAME &&
         _isDeferredPrefix(target)) {
-      if (node.operator.type == sc.TokenType.QUESTION_PERIOD) {
+      if (node.operator.type == TokenType.QUESTION_PERIOD) {
         _resolver.reportErrorForNode(
             CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
             target,
@@ -630,7 +630,7 @@
       // hierarchy, instead we just look for the member in the type only.  This
       // does not apply to conditional method invocation (i.e. 'C?.m(...)').
       //
-      bool isConditional = node.operator.type == sc.TokenType.QUESTION_PERIOD;
+      bool isConditional = node.operator.type == TokenType.QUESTION_PERIOD;
       ClassElementImpl typeReference = getTypeReference(target);
       if (typeReference != null) {
         if (node.isCascaded) {
@@ -934,11 +934,11 @@
 
   @override
   Object visitPrefixExpression(PrefixExpression node) {
-    sc.Token operator = node.operator;
-    sc.TokenType operatorType = operator.type;
+    Token operator = node.operator;
+    TokenType operatorType = operator.type;
     if (operatorType.isUserDefinableOperator ||
-        operatorType == sc.TokenType.PLUS_PLUS ||
-        operatorType == sc.TokenType.MINUS_MINUS) {
+        operatorType == TokenType.PLUS_PLUS ||
+        operatorType == TokenType.MINUS_MINUS) {
       Expression operand = node.operand;
       String methodName = _getPrefixOperator(node);
       DartType staticType = _getStaticType(operand);
@@ -1300,8 +1300,8 @@
                 propagatedType.element, methodName, true, false);
     if (shouldReportMissingMember_static ||
         shouldReportMissingMember_propagated) {
-      sc.Token leftBracket = expression.leftBracket;
-      sc.Token rightBracket = expression.rightBracket;
+      Token leftBracket = expression.leftBracket;
+      Token rightBracket = expression.rightBracket;
       ErrorCode errorCode;
       if (shouldReportMissingMember_static) {
         if (target is SuperExpression) {
@@ -1451,21 +1451,21 @@
    * Return the name of the method invoked by the given postfix [expression].
    */
   String _getPostfixOperator(PostfixExpression expression) =>
-      (expression.operator.type == sc.TokenType.PLUS_PLUS)
-          ? sc.TokenType.PLUS.lexeme
-          : sc.TokenType.MINUS.lexeme;
+      (expression.operator.type == TokenType.PLUS_PLUS)
+          ? TokenType.PLUS.lexeme
+          : TokenType.MINUS.lexeme;
 
   /**
    * Return the name of the method invoked by the given postfix [expression].
    */
   String _getPrefixOperator(PrefixExpression expression) {
-    sc.Token operator = expression.operator;
-    sc.TokenType operatorType = operator.type;
-    if (operatorType == sc.TokenType.PLUS_PLUS) {
-      return sc.TokenType.PLUS.lexeme;
-    } else if (operatorType == sc.TokenType.MINUS_MINUS) {
-      return sc.TokenType.MINUS.lexeme;
-    } else if (operatorType == sc.TokenType.MINUS) {
+    Token operator = expression.operator;
+    TokenType operatorType = operator.type;
+    if (operatorType == TokenType.PLUS_PLUS) {
+      return TokenType.PLUS.lexeme;
+    } else if (operatorType == TokenType.MINUS_MINUS) {
+      return TokenType.MINUS.lexeme;
+    } else if (operatorType == TokenType.MINUS) {
       return "unary-";
     } else {
       return operator.lexeme;
@@ -1519,12 +1519,13 @@
 
       NodeList<TypeName> arguments = typeArguments?.arguments;
       if (arguments != null && arguments.length != parameters.length) {
-        // Wrong number of type arguments. Ignore them
-        arguments = null;
         _resolver.reportErrorForNode(
             StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
             node,
             [type, parameters.length, arguments?.length ?? 0]);
+
+        // Wrong number of type arguments. Ignore them.
+        arguments = null;
       }
       if (parameters.isNotEmpty) {
         if (arguments == null) {
@@ -1746,30 +1747,30 @@
    * Return the binary operator that is invoked by the given compound assignment
    * [operator].
    */
-  sc.TokenType _operatorFromCompoundAssignment(sc.TokenType operator) {
+  TokenType _operatorFromCompoundAssignment(TokenType operator) {
     while (true) {
-      if (operator == sc.TokenType.AMPERSAND_EQ) {
-        return sc.TokenType.AMPERSAND;
-      } else if (operator == sc.TokenType.BAR_EQ) {
-        return sc.TokenType.BAR;
-      } else if (operator == sc.TokenType.CARET_EQ) {
-        return sc.TokenType.CARET;
-      } else if (operator == sc.TokenType.GT_GT_EQ) {
-        return sc.TokenType.GT_GT;
-      } else if (operator == sc.TokenType.LT_LT_EQ) {
-        return sc.TokenType.LT_LT;
-      } else if (operator == sc.TokenType.MINUS_EQ) {
-        return sc.TokenType.MINUS;
-      } else if (operator == sc.TokenType.PERCENT_EQ) {
-        return sc.TokenType.PERCENT;
-      } else if (operator == sc.TokenType.PLUS_EQ) {
-        return sc.TokenType.PLUS;
-      } else if (operator == sc.TokenType.SLASH_EQ) {
-        return sc.TokenType.SLASH;
-      } else if (operator == sc.TokenType.STAR_EQ) {
-        return sc.TokenType.STAR;
-      } else if (operator == sc.TokenType.TILDE_SLASH_EQ) {
-        return sc.TokenType.TILDE_SLASH;
+      if (operator == TokenType.AMPERSAND_EQ) {
+        return TokenType.AMPERSAND;
+      } else if (operator == TokenType.BAR_EQ) {
+        return TokenType.BAR;
+      } else if (operator == TokenType.CARET_EQ) {
+        return TokenType.CARET;
+      } else if (operator == TokenType.GT_GT_EQ) {
+        return TokenType.GT_GT;
+      } else if (operator == TokenType.LT_LT_EQ) {
+        return TokenType.LT_LT;
+      } else if (operator == TokenType.MINUS_EQ) {
+        return TokenType.MINUS;
+      } else if (operator == TokenType.PERCENT_EQ) {
+        return TokenType.PERCENT;
+      } else if (operator == TokenType.PLUS_EQ) {
+        return TokenType.PLUS;
+      } else if (operator == TokenType.SLASH_EQ) {
+        return TokenType.SLASH;
+      } else if (operator == TokenType.STAR_EQ) {
+        return TokenType.STAR;
+      } else if (operator == TokenType.TILDE_SLASH_EQ) {
+        return TokenType.TILDE_SLASH;
       } else {
         // Internal error: Unmapped assignment operator.
         AnalysisEngine.instance.logger.logError(
@@ -1837,7 +1838,7 @@
    * message.
    */
   void _recordUndefinedToken(Element declaringElement, ErrorCode errorCode,
-      sc.Token token, List<Object> arguments) {
+      Token token, List<Object> arguments) {
     if (_doesntHaveProxy(declaringElement)) {
       _resolver.reportErrorForToken(errorCode, token, arguments);
     }
@@ -2424,26 +2425,15 @@
    * If the given [type] is a type parameter, resolve it to the type that should
    * be used when looking up members. Otherwise, return the original type.
    */
-  DartType _resolveTypeParameter(DartType type) {
-    if (type is TypeParameterType) {
-      DartType bound = type.element.bound;
-      if (bound == null) {
-        return _resolver.typeProvider.objectType;
-      }
-      return bound;
-    }
-    return type;
-  }
+  DartType _resolveTypeParameter(DartType type) =>
+      type?.resolveToBound(_resolver.typeProvider.objectType);
 
   /**
    * Return `true` if we should report an error as a result of looking up a
    * [member] in the given [type] and not finding any member.
    */
   bool _shouldReportMissingMember(DartType type, Element member) {
-    if (member != null || type == null || type.isDynamic || type.isBottom) {
-      return false;
-    }
-    return true;
+    return member == null && type != null && !type.isDynamic && !type.isBottom;
   }
 
   /**
@@ -2563,7 +2553,7 @@
   SyntheticIdentifier(this.name, this.targetIdentifier);
 
   @override
-  sc.Token get beginToken => null;
+  Token get beginToken => null;
 
   @override
   Element get bestElement => null;
@@ -2577,7 +2567,7 @@
   }
 
   @override
-  sc.Token get endToken => null;
+  Token get endToken => null;
 
   @override
   int get length => targetIdentifier.length;
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index b27c42e..c3aa019 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -881,8 +881,8 @@
     if (fileName == null) {
       return false;
     }
-    return javaStringEqualsIgnoreCase(
-        FileNameUtilities.getExtension(fileName), SUFFIX_DART);
+    String extension = FileNameUtilities.getExtension(fileName).toLowerCase();
+    return extension == SUFFIX_DART;
   }
 
   /**
@@ -892,9 +892,8 @@
     if (fileName == null) {
       return false;
     }
-    String extension = FileNameUtilities.getExtension(fileName);
-    return javaStringEqualsIgnoreCase(extension, SUFFIX_HTML) ||
-        javaStringEqualsIgnoreCase(extension, SUFFIX_HTM);
+    String extension = FileNameUtilities.getExtension(fileName).toLowerCase();
+    return extension == SUFFIX_HTML || extension == SUFFIX_HTM;
   }
 }
 
@@ -1123,6 +1122,19 @@
    * Return `true` if strong mode analysis should be used.
    */
   bool get strongMode;
+
+  /**
+   * Return an integer encoding of the values of the options that need to be the
+   * same across all of the contexts associated with partitions that are to be
+   * shared by a single analysis context.
+   */
+  int encodeCrossContextOptions();
+
+  /**
+   * Set the values of the cross-context options to match those in the given set
+   * of [options].
+   */
+  void setCrossContextOptionsFrom(AnalysisOptions options);
 }
 
 /**
@@ -1135,6 +1147,14 @@
    */
   static const int DEFAULT_CACHE_SIZE = 64;
 
+  static const int ENABLE_ASSERT_FLAG = 0x01;
+  static const int ENABLE_ASYNC_FLAG = 0x02;
+  static const int ENABLE_GENERIC_METHODS_FLAG = 0x04;
+  static const int ENABLE_STRICT_CALL_CHECKS_FLAG = 0x08;
+  static const int ENABLE_STRONG_MODE_FLAG = 0x10;
+  static const int ENABLE_STRONG_MODE_HINTS_FLAG = 0x20;
+  static const int ENABLE_SUPER_MIXINS_FLAG = 0x40;
+
   /**
    * A predicate indicating whether analysis is to parse and analyze function
    * bodies.
@@ -1308,6 +1328,29 @@
     _analyzeFunctionBodiesPredicate = value;
   }
 
+  @override
+  int encodeCrossContextOptions() =>
+      (enableAssertMessage ? ENABLE_ASSERT_FLAG : 0) |
+      (enableAsync ? ENABLE_ASYNC_FLAG : 0) |
+      (enableGenericMethods ? ENABLE_GENERIC_METHODS_FLAG : 0) |
+      (enableStrictCallChecks ? ENABLE_STRICT_CALL_CHECKS_FLAG : 0) |
+      (strongMode ? ENABLE_STRONG_MODE_FLAG : 0) |
+      (strongModeHints ? ENABLE_STRONG_MODE_HINTS_FLAG : 0) |
+      (enableSuperMixins ? ENABLE_SUPER_MIXINS_FLAG : 0);
+
+  @override
+  void setCrossContextOptionsFrom(AnalysisOptions options) {
+    enableAssertMessage = options.enableAssertMessage;
+    enableAsync = options.enableAsync;
+    enableGenericMethods = options.enableGenericMethods;
+    enableStrictCallChecks = options.enableStrictCallChecks;
+    enableSuperMixins = options.enableSuperMixins;
+    strongMode = options.strongMode;
+    if (options is AnalysisOptionsImpl) {
+      strongModeHints = options.strongModeHints;
+    }
+  }
+
   /**
    * Predicate used for [analyzeFunctionBodiesPredicate] when
    * [analyzeFunctionBodies] is set to `true`.
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index fe21b9d..938aa23 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -7,13 +7,13 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart' show AstNode;
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/source/error_processor.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart' show ScannerErrorCode;
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
-import 'package:analyzer/src/generated/scanner.dart'
-    show ScannerErrorCode, Token;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/model.dart';
 import 'package:analyzer/task/model.dart';
@@ -5640,7 +5640,8 @@
    * 0: the name of the constant that is missing
    */
   static const StaticWarningCode MISSING_ENUM_CONSTANT_IN_SWITCH =
-      const StaticWarningCode('MISSING_ENUM_CONSTANT_IN_SWITCH',
+      const StaticWarningCode(
+          'MISSING_ENUM_CONSTANT_IN_SWITCH',
           "Missing case clause for '{0}'",
           "Add a case clause for the missing constant or add a default clause.");
 
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 4cb96b4..5de25974 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -8,6 +8,8 @@
 import "dart:math" as math;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -22,7 +24,6 @@
 import 'package:analyzer/src/generated/parser.dart'
     show Parser, ParserErrorCode;
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart' as sc;
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk, SdkLibrary;
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
@@ -328,11 +329,11 @@
 
   @override
   Object visitAssignmentExpression(AssignmentExpression node) {
-    sc.TokenType operatorType = node.operator.type;
+    TokenType operatorType = node.operator.type;
     Expression lhs = node.leftHandSide;
     Expression rhs = node.rightHandSide;
-    if (operatorType == sc.TokenType.EQ ||
-        operatorType == sc.TokenType.QUESTION_QUESTION_EQ) {
+    if (operatorType == TokenType.EQ ||
+        operatorType == TokenType.QUESTION_QUESTION_EQ) {
       _checkForInvalidAssignment(lhs, rhs);
     } else {
       _checkForInvalidCompoundAssignment(node, lhs, rhs);
@@ -353,10 +354,10 @@
 
   @override
   Object visitBinaryExpression(BinaryExpression node) {
-    sc.Token operator = node.operator;
-    sc.TokenType type = operator.type;
-    if (type == sc.TokenType.AMPERSAND_AMPERSAND ||
-        type == sc.TokenType.BAR_BAR) {
+    Token operator = node.operator;
+    TokenType type = operator.type;
+    if (type == TokenType.AMPERSAND_AMPERSAND ||
+        type == TokenType.BAR_BAR) {
       String lexeme = operator.lexeme;
       _checkForAssignability(node.leftOperand, _boolType,
           StaticTypeWarningCode.NON_BOOL_OPERAND, [lexeme]);
@@ -947,9 +948,9 @@
 
   @override
   Object visitPrefixExpression(PrefixExpression node) {
-    sc.TokenType operatorType = node.operator.type;
+    TokenType operatorType = node.operator.type;
     Expression operand = node.operand;
-    if (operatorType == sc.TokenType.BANG) {
+    if (operatorType == TokenType.BANG) {
       _checkForNonBoolNegationExpression(operand);
     } else if (operatorType.isIncrementOperator) {
       _checkForAssignmentToFinal(operand);
@@ -2169,8 +2170,8 @@
    */
   bool _checkForBuiltInIdentifierAsName(
       SimpleIdentifier identifier, ErrorCode errorCode) {
-    sc.Token token = identifier.token;
-    if (token.type == sc.TokenType.KEYWORD) {
+    Token token = identifier.token;
+    if (token.type == TokenType.KEYWORD) {
       _errorReporter
           .reportErrorForNode(errorCode, identifier, [identifier.name]);
       return true;
@@ -2831,8 +2832,8 @@
     if (type.element.isAbstract) {
       ConstructorElement element = expression.staticElement;
       if (element != null && !element.isFactory) {
-        if ((expression.keyword as sc.KeywordToken).keyword ==
-            sc.Keyword.CONST) {
+        if ((expression.keyword as KeywordToken).keyword ==
+            Keyword.CONST) {
           _errorReporter.reportErrorForNode(
               StaticWarningCode.CONST_WITH_ABSTRACT_CLASS, typeName);
         } else {
@@ -3981,7 +3982,7 @@
    */
   bool _checkForInvalidModifierOnBody(
       FunctionBody body, CompileTimeErrorCode errorCode) {
-    sc.Token keyword = body.keyword;
+    Token keyword = body.keyword;
     if (keyword != null) {
       _errorReporter.reportErrorForToken(errorCode, keyword, [keyword.lexeme]);
       return true;
@@ -5852,7 +5853,7 @@
     int count = directives.length;
     if (count > 1) {
       for (int i = 0; i < count; i++) {
-        sc.Token deferredToken = directives[i].deferredKeyword;
+        Token deferredToken = directives[i].deferredKeyword;
         if (deferredToken != null) {
           _errorReporter.reportErrorForToken(
               CompileTimeErrorCode.SHARED_DEFERRED_PREFIX, deferredToken);
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index b19b4b1..f102201 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -8,14 +8,18 @@
 import 'dart:math' as math;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/visitor.dart';
 import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/builder.dart';
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
@@ -25,7 +29,6 @@
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/task/dart.dart';
@@ -2049,9 +2052,9 @@
 /**
  * Adjusts the location of each Element that moved.
  *
- * Since operator== and hashCode of an Element are based
- * on the element location, we also need to remove each
- * moved element from the cache to avoid a memory leak.
+ * Since `==` and `hashCode` of a local variable or function Element are based
+ * on the element name offsets, we also need to remove these elements from the
+ * cache to avoid a memory leak. TODO(scheglov) fix and remove this
  */
 class _ElementOffsetUpdater extends GeneralizingElementVisitor {
   final int updateOffset;
@@ -2065,7 +2068,13 @@
     // name offset
     int nameOffset = element.nameOffset;
     if (nameOffset > updateOffset) {
-      cache.remove(element);
+      // TODO(scheglov) make sure that we don't put local variables
+      // and functions into the cache at all.
+      if (element is LocalVariableElement ||
+          element is FunctionElement &&
+              element.enclosingElement is ExecutableElement) {
+        cache.remove(element);
+      }
       (element as ElementImpl).nameOffset = nameOffset + updateDelta;
       if (element is ConstVariableElement) {
         ConstVariableElement constVariable = element as ConstVariableElement;
diff --git a/pkg/analyzer/lib/src/generated/incremental_scanner.dart b/pkg/analyzer/lib/src/generated/incremental_scanner.dart
index 6f4abee..ae34471 100644
--- a/pkg/analyzer/lib/src/generated/incremental_scanner.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_scanner.dart
@@ -6,9 +6,11 @@
 
 import "dart:math" as math;
 
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_collection.dart' show TokenMap;
 
@@ -203,8 +205,8 @@
    */
   bool _equalTokens(Token oldToken, Token newToken) =>
       oldToken.type == newToken.type &&
-          oldToken.length == newToken.length &&
-          oldToken.lexeme == newToken.lexeme;
+      oldToken.length == newToken.length &&
+      oldToken.lexeme == newToken.lexeme;
 
   /**
    * Given a [token], return the EOF token that follows the token.
diff --git a/pkg/analyzer/lib/src/generated/java_core.dart b/pkg/analyzer/lib/src/generated/java_core.dart
index fd684ed..d28dd98 100644
--- a/pkg/analyzer/lib/src/generated/java_core.dart
+++ b/pkg/analyzer/lib/src/generated/java_core.dart
@@ -4,8 +4,6 @@
 
 library analyzer.src.generated.java_core;
 
-const int LONG_MAX_VALUE = 0x7fffffffffffffff;
-
 final Stopwatch nanoTimeStopwatch = new Stopwatch();
 
 /**
@@ -17,6 +15,8 @@
  */
 String format(String pattern,
     [arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7]) {
+  // TODO(rnystrom): This is not used by analyzer, but is called by
+  // analysis_server. Move this code there and remove it from here.
   return formatList(pattern, [arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7]);
 }
 
@@ -41,35 +41,6 @@
   });
 }
 
-bool javaCollectionContainsAll(Iterable list, Iterable c) {
-  return c.fold(true, (bool prev, e) => prev && list.contains(e));
-}
-
-javaListSet(List list, int index, newValue) {
-  var oldValue = list[index];
-  list[index] = newValue;
-  return oldValue;
-}
-
-bool javaSetEquals(Set a, Set b) {
-  return a.containsAll(b) && b.containsAll(a);
-}
-
-bool javaStringEqualsIgnoreCase(String a, String b) {
-  return a.toLowerCase() == b.toLowerCase();
-}
-
-bool javaStringRegionMatches(
-    String t, int toffset, String o, int ooffset, int len) {
-  if (toffset < 0) return false;
-  if (ooffset < 0) return false;
-  var tend = toffset + len;
-  var oend = ooffset + len;
-  if (tend > t.length) return false;
-  if (oend > o.length) return false;
-  return t.substring(toffset, tend) == o.substring(ooffset, oend);
-}
-
 /// Parses given string to [Uri], throws [URISyntaxException] if invalid.
 Uri parseUriWithException(String str) {
   Uri uri;
@@ -130,6 +101,7 @@
   static const int MIN_SUPPLEMENTARY_CODE_POINT = 0x010000;
   static const int MIN_LOW_SURROGATE = 0xDC00;
   static const int MIN_HIGH_SURROGATE = 0xD800;
+
   static int digit(int codePoint, int radix) {
     if (radix != 16) {
       throw new ArgumentError("only radix == 16 is supported");
@@ -146,29 +118,15 @@
     return -1;
   }
 
-  static bool isDigit(int c) {
-    return c >= 0x30 && c <= 0x39;
-  }
+  static bool isDigit(int c) => c >= 0x30 && c <= 0x39;
 
-  static bool isLetter(int c) {
-    return c >= 0x41 && c <= 0x5A || c >= 0x61 && c <= 0x7A;
-  }
+  static bool isLetter(int c) =>
+      c >= 0x41 && c <= 0x5A || c >= 0x61 && c <= 0x7A;
 
-  static bool isLetterOrDigit(int c) {
-    return isLetter(c) || isDigit(c);
-  }
+  static bool isLetterOrDigit(int c) => isLetter(c) || isDigit(c);
 
-  static bool isLowerCase(int c) {
-    return c >= 0x61 && c <= 0x7A;
-  }
-
-  static bool isUpperCase(int c) {
-    return c >= 0x41 && c <= 0x5A;
-  }
-
-  static bool isWhitespace(int c) {
-    return c == 0x09 || c == 0x20 || c == 0x0A || c == 0x0D;
-  }
+  static bool isWhitespace(int c) =>
+      c == 0x09 || c == 0x20 || c == 0x0A || c == 0x0D;
 
   static String toChars(int codePoint) {
     if (codePoint < 0 || codePoint > MAX_CODE_POINT) {
@@ -182,20 +140,6 @@
     int c1 = (offset & 0x3ff) + MIN_LOW_SURROGATE;
     return new String.fromCharCodes([c0, c1]);
   }
-
-  static int toLowerCase(int c) {
-    if (c >= 0x41 && c <= 0x5A) {
-      return 0x61 + (c - 0x41);
-    }
-    return c;
-  }
-
-  static int toUpperCase(int c) {
-    if (c >= 0x61 && c <= 0x7A) {
-      return 0x41 + (c - 0x61);
-    }
-    return c;
-  }
 }
 
 abstract class Enum<E extends Enum> implements Comparable<E> {
@@ -220,23 +164,9 @@
 }
 
 class JavaArrays {
-  static bool equals(List a, List b) {
-    if (identical(a, b)) {
-      return true;
-    }
-    if (a.length != b.length) {
-      return false;
-    }
-    var len = a.length;
-    for (int i = 0; i < len; i++) {
-      if (a[i] != b[i]) {
-        return false;
-      }
-    }
-    return true;
-  }
-
   static int makeHashCode(List a) {
+    // TODO(rnystrom): This is not used by analyzer, but is called by
+    // analysis_server. Move this code there and remove it from here.
     if (a == null) {
       return 0;
     }
@@ -292,10 +222,6 @@
     if (fromIndex < 0) fromIndex = 0;
     return target.lastIndexOf(str, fromIndex);
   }
-
-  static bool startsWithBefore(String s, String other, int start) {
-    return s.indexOf(other, start) != -1;
-  }
 }
 
 class JavaSystem {
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 7a39b04..ad18d2c 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -8,9 +8,13 @@
 import "dart:math" as math;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisEngine, AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/error.dart';
@@ -18,7 +22,6 @@
     as shared_messages;
 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/source.dart';
 import 'package:analyzer/src/generated/utilities_collection.dart' show TokenMap;
 import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -7049,7 +7052,8 @@
             _peek().matchesAny([
               TokenType.OPEN_PAREN,
               TokenType.OPEN_CURLY_BRACKET,
-              TokenType.FUNCTION
+              TokenType.FUNCTION,
+              TokenType.LT
             ])) {
           return _parseFunctionDeclarationStatementAfterReturnType(
               commentAndMetadata, returnType);
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index ecfe204..fab4ed1 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -7,10 +7,13 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/visitor.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart';
@@ -23,7 +26,6 @@
 import 'package:analyzer/src/generated/error_verifier.dart';
 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/source.dart';
 import 'package:analyzer/src/generated/static_type_analyzer.dart';
 import 'package:analyzer/src/generated/type_system.dart';
@@ -2302,6 +2304,7 @@
     if (node.parent is! FunctionDeclaration) {
       FunctionElement element = _findAtOffset(
           _enclosingExecutable.functions, node, node.beginToken.offset);
+      _expectedElements.remove(element);
       node.element = element;
     }
     ExecutableElement outerExecutable = _enclosingExecutable;
@@ -3270,12 +3273,14 @@
     List<DartObjectImpl> constantValues = new List<DartObjectImpl>();
     int constantCount = constants.length;
     for (int i = 0; i < constantCount; i++) {
-      SimpleIdentifier constantName = constants[i].name;
+      EnumConstantDeclaration constant = constants[i];
+      SimpleIdentifier constantName = constant.name;
       FieldElementImpl constantField =
           new ConstFieldElementImpl.forNode(constantName);
       constantField.static = true;
       constantField.const3 = true;
       constantField.type = enumType;
+      setElementDocumentationComment(constantField, constant);
       //
       // Create a value for the constant.
       //
@@ -4001,6 +4006,7 @@
  * An [AstVisitor] that fills [UsedLocalElements].
  */
 class GatherUsedLocalElementsVisitor extends RecursiveAstVisitor {
+  final List<Element> definedElements = <Element>[];
   final UsedLocalElements usedElements = new UsedLocalElements();
 
   final LibraryElement _enclosingLibrary;
@@ -4070,10 +4076,13 @@
 
   @override
   visitSimpleIdentifier(SimpleIdentifier node) {
+    Element element = node.staticElement;
     if (node.inDeclarationContext()) {
+      if (element != null) {
+        definedElements.add(element);
+      }
       return;
     }
-    Element element = node.staticElement;
     bool isIdentifierRead = _isReadIdentifier(node);
     if (element is LocalVariableElement) {
       if (isIdentifierRead) {
@@ -7293,6 +7302,48 @@
   }
 
   /**
+   * Given a downward inference type [fnType], and the declared
+   * [typeParameterList] for a function expression, determines if we can enable
+   * downward inference and if so, returns the function type to use for
+   * inference.
+   *
+   * This will return null if inference is not possible. This happens when
+   * there is no way we can find a subtype of the function type, given the
+   * provided type parameter list.
+   */
+  FunctionType matchFunctionTypeParameters(
+      TypeParameterList typeParameterList, FunctionType fnType) {
+    if (typeParameterList == null) {
+      if (fnType.typeFormals.isEmpty) {
+        return fnType;
+      }
+
+      // A non-generic function cannot be a subtype of a generic one.
+      return null;
+    }
+
+    NodeList<TypeParameter> typeParameters = typeParameterList.typeParameters;
+    if (fnType.typeFormals.isEmpty) {
+      // TODO(jmesserly): this is a legal subtype. We don't currently infer
+      // here, but we could.  This is similar to
+      // StrongTypeSystemImpl.inferFunctionTypeInstantiation, but we don't
+      // have the FunctionType yet for the current node, so it's not quite
+      // straightforward to apply.
+      return null;
+    }
+
+    if (fnType.typeFormals.length != typeParameters.length) {
+      // A subtype cannot have different number of type formals.
+      return null;
+    }
+
+    // Same number of type formals. Instantiate the function type so its
+    // parameter and return type are in terms of the surrounding context.
+    return fnType.instantiate(
+        typeParameters.map((t) => t.name.staticElement.type).toList());
+  }
+
+  /**
    * If it is appropriate to do so, override the current type of the static and propagated elements
    * associated with the given expression with the given type. Generally speaking, it is appropriate
    * if the given type is more specific than the current type.
@@ -8076,12 +8127,16 @@
       try {
         DartType functionType = InferenceContext.getType(node);
         if (functionType is FunctionType) {
-          _inferFormalParameterList(node.parameters, functionType);
-          DartType returnType = _computeReturnOrYieldType(
-              functionType.returnType,
-              _enclosingFunction.isGenerator,
-              _enclosingFunction.isAsynchronous);
-          InferenceContext.setType(node.body, returnType);
+          functionType =
+              matchFunctionTypeParameters(node.typeParameters, functionType);
+          if (functionType is FunctionType) {
+            _inferFormalParameterList(node.parameters, functionType);
+            DartType returnType = _computeReturnOrYieldType(
+                functionType.returnType,
+                _enclosingFunction.isGenerator,
+                _enclosingFunction.isAsynchronous);
+            InferenceContext.setType(node.body, returnType);
+          }
         }
         super.visitFunctionExpression(node);
       } finally {
@@ -11513,7 +11568,7 @@
       if (element is MultiplyDefinedElement) {
         _setElement(typeName, element);
       } else {
-        _setElement(typeName, _dynamicType.element);
+        _setElement(typeName, null);
       }
       typeName.staticType = _undefinedType;
       node.type = _undefinedType;
@@ -11578,7 +11633,7 @@
               StaticWarningCode.NOT_A_TYPE, typeName, [typeName.name]);
         }
       }
-      _setElement(typeName, _dynamicType.element);
+      _setElement(typeName, null);
       typeName.staticType = _dynamicType;
       node.type = _dynamicType;
       return null;
@@ -12080,18 +12135,25 @@
     return types;
   }
 
+  /**
+   * If the given [element] is not `null`, set `staticElement` of the
+   * [typeName] to it.  If the [typeName] is a prefixed identifier, and the
+   * prefix can be resolved to a not `null` element, set also the
+   * `staticElement` of the prefix.
+   */
   void _setElement(Identifier typeName, Element element) {
-    if (element != null) {
-      if (typeName is SimpleIdentifier) {
+    if (typeName is SimpleIdentifier) {
+      if (element != null) {
         typeName.staticElement = element;
-      } else if (typeName is PrefixedIdentifier) {
-        PrefixedIdentifier identifier = typeName;
-        identifier.identifier.staticElement = element;
-        SimpleIdentifier prefix = identifier.prefix;
-        Element prefixElement = nameScope.lookup(prefix, definingLibrary);
-        if (prefixElement != null) {
-          prefix.staticElement = prefixElement;
-        }
+      }
+    } else if (typeName is PrefixedIdentifier) {
+      if (element != null) {
+        typeName.identifier.staticElement = element;
+      }
+      SimpleIdentifier prefix = typeName.prefix;
+      Element prefixElement = nameScope.lookup(prefix, definingLibrary);
+      if (prefixElement != null) {
+        prefix.staticElement = prefixElement;
       }
     }
   }
@@ -12148,7 +12210,7 @@
  * structure looking for cases of [HintCode.UNUSED_ELEMENT],
  * [HintCode.UNUSED_FIELD], [HintCode.UNUSED_LOCAL_VARIABLE], etc.
  */
-class UnusedLocalElementsVerifier extends RecursiveElementVisitor {
+class UnusedLocalElementsVerifier extends SimpleElementVisitor {
   /**
    * The error listener to which errors will be reported.
    */
@@ -12398,6 +12460,11 @@
   ExecutableElement _enclosingFunction;
 
   /**
+   * Information about local variables in the enclosing function or method.
+   */
+  LocalVariableInfo _localVariableInfo;
+
+  /**
    * Initialize a newly created visitor to resolve the nodes in an AST node.
    *
    * [definingLibrary] is the element for the library containing the node being
@@ -12419,15 +12486,35 @@
             nameScope: nameScope);
 
   @override
+  Object visitConstructorDeclaration(ConstructorDeclaration node) {
+    ExecutableElement outerFunction = _enclosingFunction;
+    LocalVariableInfo outerLocalVariableInfo = _localVariableInfo;
+    try {
+      _localVariableInfo ??= new LocalVariableInfo();
+      (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
+      _enclosingFunction = node.element;
+      return super.visitConstructorDeclaration(node);
+    } finally {
+      _localVariableInfo = outerLocalVariableInfo;
+      _enclosingFunction = outerFunction;
+    }
+  }
+
+  @override
   Object visitExportDirective(ExportDirective node) => null;
 
   @override
   Object visitFunctionDeclaration(FunctionDeclaration node) {
     ExecutableElement outerFunction = _enclosingFunction;
+    LocalVariableInfo outerLocalVariableInfo = _localVariableInfo;
     try {
+      _localVariableInfo ??= new LocalVariableInfo();
+      (node.functionExpression.body as FunctionBodyImpl).localVariableInfo =
+          _localVariableInfo;
       _enclosingFunction = node.element;
       return super.visitFunctionDeclaration(node);
     } finally {
+      _localVariableInfo = outerLocalVariableInfo;
       _enclosingFunction = outerFunction;
     }
   }
@@ -12436,10 +12523,14 @@
   Object visitFunctionExpression(FunctionExpression node) {
     if (node.parent is! FunctionDeclaration) {
       ExecutableElement outerFunction = _enclosingFunction;
+      LocalVariableInfo outerLocalVariableInfo = _localVariableInfo;
       try {
+        _localVariableInfo ??= new LocalVariableInfo();
+        (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
         _enclosingFunction = node.element;
         return super.visitFunctionExpression(node);
       } finally {
+        _localVariableInfo = outerLocalVariableInfo;
         _enclosingFunction = outerFunction;
       }
     } else {
@@ -12453,10 +12544,14 @@
   @override
   Object visitMethodDeclaration(MethodDeclaration node) {
     ExecutableElement outerFunction = _enclosingFunction;
+    LocalVariableInfo outerLocalVariableInfo = _localVariableInfo;
     try {
+      _localVariableInfo ??= new LocalVariableInfo();
+      (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
       _enclosingFunction = node.element;
       return super.visitMethodDeclaration(node);
     } finally {
+      _localVariableInfo = outerLocalVariableInfo;
       _enclosingFunction = outerFunction;
     }
   }
@@ -12508,8 +12603,10 @@
           element as LocalVariableElementImpl;
       if (node.inSetterContext()) {
         variableImpl.markPotentiallyMutatedInScope();
+        _localVariableInfo.potentiallyMutatedInScope.add(element);
         if (element.enclosingElement != _enclosingFunction) {
           variableImpl.markPotentiallyMutatedInClosure();
+          _localVariableInfo.potentiallyMutatedInClosure.add(element);
         }
       }
     } else if (kind == ElementKind.PARAMETER) {
@@ -12517,11 +12614,13 @@
       if (node.inSetterContext()) {
         ParameterElementImpl parameterImpl = element as ParameterElementImpl;
         parameterImpl.markPotentiallyMutatedInScope();
+        _localVariableInfo.potentiallyMutatedInScope.add(element);
         // If we are in some closure, check if it is not the same as where
         // variable is declared.
         if (_enclosingFunction != null &&
             (element.enclosingElement != _enclosingFunction)) {
           parameterImpl.markPotentiallyMutatedInClosure();
+          _localVariableInfo.potentiallyMutatedInClosure.add(element);
         }
       }
     }
diff --git a/pkg/analyzer/lib/src/generated/scanner.dart b/pkg/analyzer/lib/src/generated/scanner.dart
index 3fc2113..5a2e2c0 100644
--- a/pkg/analyzer/lib/src/generated/scanner.dart
+++ b/pkg/analyzer/lib/src/generated/scanner.dart
@@ -2,2715 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+@deprecated
 library analyzer.src.generated.scanner;
 
-import 'dart:collection';
-
-import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/source.dart';
-
-/**
- * The opening half of a grouping pair of tokens. This is used for curly
- * brackets ('{'), parentheses ('('), and square brackets ('[').
- */
-class BeginToken extends Token {
-  /**
-   * The token that corresponds to this token.
-   */
-  Token endToken;
-
-  /**
-   * Initialize a newly created token to have the given [type] at the given
-   * [offset].
-   */
-  BeginToken(TokenType type, int offset) : super(type, offset) {
-    assert(type == TokenType.OPEN_CURLY_BRACKET ||
-        type == TokenType.OPEN_PAREN ||
-        type == TokenType.OPEN_SQUARE_BRACKET ||
-        type == TokenType.STRING_INTERPOLATION_EXPRESSION);
-  }
-
-  @override
-  Token copy() => new BeginToken(type, offset);
-}
-
-/**
- * A begin token that is preceded by comments.
- */
-class BeginTokenWithComment extends BeginToken {
-  /**
-   * The first comment in the list of comments that precede this token.
-   */
-  CommentToken _precedingComment;
-
-  /**
-   * Initialize a newly created token to have the given [type] at the given
-   * [offset] and to be preceded by the comments reachable from the given
-   * [comment].
-   */
-  BeginTokenWithComment(TokenType type, int offset, this._precedingComment)
-      : super(type, offset) {
-    _setCommentParent(_precedingComment);
-  }
-
-  CommentToken get precedingComments => _precedingComment;
-
-  void set precedingComments(CommentToken comment) {
-    _precedingComment = comment;
-    _setCommentParent(_precedingComment);
-  }
-
-  @override
-  void applyDelta(int delta) {
-    super.applyDelta(delta);
-    Token token = precedingComments;
-    while (token != null) {
-      token.applyDelta(delta);
-      token = token.next;
-    }
-  }
-
-  @override
-  Token copy() =>
-      new BeginTokenWithComment(type, offset, copyComments(precedingComments));
-}
-
-/**
- * A [CharacterReader] that reads a range of characters from another character
- * reader.
- */
-class CharacterRangeReader extends CharacterReader {
-  /**
-   * The reader from which the characters are actually being read.
-   */
-  final CharacterReader baseReader;
-
-  /**
-   * The last character to be read.
-   */
-  final int endIndex;
-
-  /**
-   * Initialize a newly created reader to read the characters from the given
-   * [baseReader] between the [startIndex] inclusive to [endIndex] exclusive.
-   */
-  CharacterRangeReader(this.baseReader, int startIndex, this.endIndex) {
-    baseReader.offset = startIndex - 1;
-  }
-
-  @override
-  int get offset => baseReader.offset;
-
-  @override
-  void set offset(int offset) {
-    baseReader.offset = offset;
-  }
-
-  @override
-  int advance() {
-    if (baseReader.offset + 1 >= endIndex) {
-      return -1;
-    }
-    return baseReader.advance();
-  }
-
-  @override
-  String getString(int start, int endDelta) =>
-      baseReader.getString(start, endDelta);
-
-  @override
-  int peek() {
-    if (baseReader.offset + 1 >= endIndex) {
-      return -1;
-    }
-    return baseReader.peek();
-  }
-}
-
-/**
- * An object used by the scanner to read the characters to be scanned.
- */
-abstract class CharacterReader {
-  /**
-   * The current offset relative to the beginning of the source. Return the
-   * initial offset if the scanner has not yet scanned the source code, and one
-   * (1) past the end of the source code if the entire source code has been
-   * scanned.
-   */
-  int get offset;
-
-  /**
-   * Set the current offset relative to the beginning of the source to the given
-   * [offset]. The new offset must be between the initial offset and one (1)
-   * past the end of the source code.
-   */
-  void set offset(int offset);
-
-  /**
-   * Advance the current position and return the character at the new current
-   * position.
-   */
-  int advance();
-
-  /**
-   * Return the substring of the source code between the [start] offset and the
-   * modified current position. The current position is modified by adding the
-   * [endDelta], which is the number of characters after the current location to
-   * be included in the string, or the number of characters before the current
-   * location to be excluded if the offset is negative.
-   */
-  String getString(int start, int endDelta);
-
-  /**
-   * Return the character at the current position without changing the current
-   * position.
-   */
-  int peek();
-}
-
-/**
- * A [CharacterReader] that reads characters from a character sequence.
- */
-class CharSequenceReader implements CharacterReader {
-  /**
-   * The sequence from which characters will be read.
-   */
-  final String _sequence;
-
-  /**
-   * The number of characters in the string.
-   */
-  int _stringLength = 0;
-
-  /**
-   * The index, relative to the string, of the last character that was read.
-   */
-  int _charOffset = 0;
-
-  /**
-   * Initialize a newly created reader to read the characters in the given
-   * [_sequence].
-   */
-  CharSequenceReader(this._sequence) {
-    this._stringLength = _sequence.length;
-    this._charOffset = -1;
-  }
-
-  @override
-  int get offset => _charOffset;
-
-  @override
-  void set offset(int offset) {
-    _charOffset = offset;
-  }
-
-  @override
-  int advance() {
-    if (_charOffset + 1 >= _stringLength) {
-      return -1;
-    }
-    return _sequence.codeUnitAt(++_charOffset);
-  }
-
-  @override
-  String getString(int start, int endDelta) =>
-      _sequence.substring(start, _charOffset + 1 + endDelta).toString();
-
-  @override
-  int peek() {
-    if (_charOffset + 1 >= _stringLength) {
-      return -1;
-    }
-    return _sequence.codeUnitAt(_charOffset + 1);
-  }
-}
-
-/**
- * A token representing a comment.
- */
-class CommentToken extends StringToken {
-  /**
-   * The [Token] that contains this comment.
-   */
-  Token parent;
-
-  /**
-   * Initialize a newly created token to represent a token of the given [type]
-   * with the given [value] at the given [offset].
-   */
-  CommentToken(TokenType type, String value, int offset)
-      : super(type, value, offset);
-
-  @override
-  CommentToken copy() => new CommentToken(type, _value, offset);
-}
-
-/**
- * A documentation comment token.
- */
-class DocumentationCommentToken extends CommentToken {
-  /**
-   * The references embedded within the documentation comment.
-   * This list will be empty unless this is a documentation comment that has
-   * references embedded within it.
-   */
-  final List<Token> references = <Token>[];
-
-  /**
-   * Initialize a newly created token to represent a token of the given [type]
-   * with the given [value] at the given [offset].
-   */
-  DocumentationCommentToken(TokenType type, String value, int offset)
-      : super(type, value, offset);
-
-  @override
-  CommentToken copy() {
-    DocumentationCommentToken copy =
-        new DocumentationCommentToken(type, _value, offset);
-    references.forEach((ref) => copy.references.add(ref.copy()));
-    return copy;
-  }
-}
-
-/**
- * The keywords in the Dart programming language.
- */
-class Keyword {
-  static const Keyword ASSERT = const Keyword('ASSERT', "assert");
-
-  static const Keyword BREAK = const Keyword('BREAK', "break");
-
-  static const Keyword CASE = const Keyword('CASE', "case");
-
-  static const Keyword CATCH = const Keyword('CATCH', "catch");
-
-  static const Keyword CLASS = const Keyword('CLASS', "class");
-
-  static const Keyword CONST = const Keyword('CONST', "const");
-
-  static const Keyword CONTINUE = const Keyword('CONTINUE', "continue");
-
-  static const Keyword DEFAULT = const Keyword('DEFAULT', "default");
-
-  static const Keyword DO = const Keyword('DO', "do");
-
-  static const Keyword ELSE = const Keyword('ELSE', "else");
-
-  static const Keyword ENUM = const Keyword('ENUM', "enum");
-
-  static const Keyword EXTENDS = const Keyword('EXTENDS', "extends");
-
-  static const Keyword FALSE = const Keyword('FALSE', "false");
-
-  static const Keyword FINAL = const Keyword('FINAL', "final");
-
-  static const Keyword FINALLY = const Keyword('FINALLY', "finally");
-
-  static const Keyword FOR = const Keyword('FOR', "for");
-
-  static const Keyword IF = const Keyword('IF', "if");
-
-  static const Keyword IN = const Keyword('IN', "in");
-
-  static const Keyword IS = const Keyword('IS', "is");
-
-  static const Keyword NEW = const Keyword('NEW', "new");
-
-  static const Keyword NULL = const Keyword('NULL', "null");
-
-  static const Keyword RETHROW = const Keyword('RETHROW', "rethrow");
-
-  static const Keyword RETURN = const Keyword('RETURN', "return");
-
-  static const Keyword SUPER = const Keyword('SUPER', "super");
-
-  static const Keyword SWITCH = const Keyword('SWITCH', "switch");
-
-  static const Keyword THIS = const Keyword('THIS', "this");
-
-  static const Keyword THROW = const Keyword('THROW', "throw");
-
-  static const Keyword TRUE = const Keyword('TRUE', "true");
-
-  static const Keyword TRY = const Keyword('TRY', "try");
-
-  static const Keyword VAR = const Keyword('VAR', "var");
-
-  static const Keyword VOID = const Keyword('VOID', "void");
-
-  static const Keyword WHILE = const Keyword('WHILE', "while");
-
-  static const Keyword WITH = const Keyword('WITH', "with");
-
-  static const Keyword ABSTRACT = const Keyword('ABSTRACT', "abstract", true);
-
-  static const Keyword AS = const Keyword('AS', "as", true);
-
-  static const Keyword DEFERRED = const Keyword('DEFERRED', "deferred", true);
-
-  static const Keyword DYNAMIC = const Keyword('DYNAMIC', "dynamic", true);
-
-  static const Keyword EXPORT = const Keyword('EXPORT', "export", true);
-
-  static const Keyword EXTERNAL = const Keyword('EXTERNAL', "external", true);
-
-  static const Keyword FACTORY = const Keyword('FACTORY', "factory", true);
-
-  static const Keyword GET = const Keyword('GET', "get", true);
-
-  static const Keyword IMPLEMENTS =
-      const Keyword('IMPLEMENTS', "implements", true);
-
-  static const Keyword IMPORT = const Keyword('IMPORT', "import", true);
-
-  static const Keyword LIBRARY = const Keyword('LIBRARY', "library", true);
-
-  static const Keyword OPERATOR = const Keyword('OPERATOR', "operator", true);
-
-  static const Keyword PART = const Keyword('PART', "part", true);
-
-  static const Keyword SET = const Keyword('SET', "set", true);
-
-  static const Keyword STATIC = const Keyword('STATIC', "static", true);
-
-  static const Keyword TYPEDEF = const Keyword('TYPEDEF', "typedef", true);
-
-  static const List<Keyword> values = const [
-    ASSERT,
-    BREAK,
-    CASE,
-    CATCH,
-    CLASS,
-    CONST,
-    CONTINUE,
-    DEFAULT,
-    DO,
-    ELSE,
-    ENUM,
-    EXTENDS,
-    FALSE,
-    FINAL,
-    FINALLY,
-    FOR,
-    IF,
-    IN,
-    IS,
-    NEW,
-    NULL,
-    RETHROW,
-    RETURN,
-    SUPER,
-    SWITCH,
-    THIS,
-    THROW,
-    TRUE,
-    TRY,
-    VAR,
-    VOID,
-    WHILE,
-    WITH,
-    ABSTRACT,
-    AS,
-    DEFERRED,
-    DYNAMIC,
-    EXPORT,
-    EXTERNAL,
-    FACTORY,
-    GET,
-    IMPLEMENTS,
-    IMPORT,
-    LIBRARY,
-    OPERATOR,
-    PART,
-    SET,
-    STATIC,
-    TYPEDEF
-  ];
-
-  /**
-   * A table mapping the lexemes of keywords to the corresponding keyword.
-   */
-  static final Map<String, Keyword> keywords = _createKeywordMap();
-
-  /**
-   * The name of the keyword type.
-   */
-  final String name;
-
-  /**
-   * The lexeme for the keyword.
-   */
-  final String syntax;
-
-  /**
-   * A flag indicating whether the keyword is a pseudo-keyword. Pseudo keywords
-   * can be used as identifiers.
-   */
-  final bool isPseudoKeyword;
-
-  /**
-   * Initialize a newly created keyword to have the given [name] and [syntax].
-   * The keyword is a pseudo-keyword if the [isPseudoKeyword] flag is `true`.
-   */
-  const Keyword(this.name, this.syntax, [this.isPseudoKeyword = false]);
-
-  @override
-  String toString() => name;
-
-  /**
-   * Create a table mapping the lexemes of keywords to the corresponding keyword
-   * and return the table that was created.
-   */
-  static Map<String, Keyword> _createKeywordMap() {
-    LinkedHashMap<String, Keyword> result =
-        new LinkedHashMap<String, Keyword>();
-    for (Keyword keyword in values) {
-      result[keyword.syntax] = keyword;
-    }
-    return result;
-  }
-}
-
-/**
- * A state in a state machine used to scan keywords.
- */
-class KeywordState {
-  /**
-   * An empty transition table used by leaf states.
-   */
-  static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>(26);
-
-  /**
-   * The initial state in the state machine.
-   */
-  static final KeywordState KEYWORD_STATE = _createKeywordStateTable();
-
-  /**
-   * A table mapping characters to the states to which those characters will
-   * transition. (The index into the array is the offset from the character
-   * `'a'` to the transitioning character.)
-   */
-  final List<KeywordState> _table;
-
-  /**
-   * The keyword that is recognized by this state, or `null` if this state is
-   * not a terminal state.
-   */
-  Keyword _keyword;
-
-  /**
-   * Initialize a newly created state to have the given transitions and to
-   * recognize the keyword with the given [syntax].
-   */
-  KeywordState(this._table, String syntax) {
-    this._keyword = (syntax == null) ? null : Keyword.keywords[syntax];
-  }
-
-  /**
-   * Return the keyword that was recognized by this state, or `null` if this
-   * state does not recognized a keyword.
-   */
-  Keyword keyword() => _keyword;
-
-  /**
-   * Return the state that follows this state on a transition of the given
-   * [character], or `null` if there is no valid state reachable from this state
-   * with such a transition.
-   */
-  KeywordState next(int character) => _table[character - 0x61];
-
-  /**
-   * Create the next state in the state machine where we have already recognized
-   * the subset of strings in the given array of [strings] starting at the given
-   * [offset] and having the given [length]. All of these strings have a common
-   * prefix and the next character is at the given [start] index.
-   */
-  static KeywordState _computeKeywordStateTable(
-      int start, List<String> strings, int offset, int length) {
-    List<KeywordState> result = new List<KeywordState>(26);
-    assert(length != 0);
-    int chunk = 0x0;
-    int chunkStart = -1;
-    bool isLeaf = false;
-    for (int i = offset; i < offset + length; i++) {
-      if (strings[i].length == start) {
-        isLeaf = true;
-      }
-      if (strings[i].length > start) {
-        int c = strings[i].codeUnitAt(start);
-        if (chunk != c) {
-          if (chunkStart != -1) {
-            result[chunk - 0x61] = _computeKeywordStateTable(
-                start + 1, strings, chunkStart, i - chunkStart);
-          }
-          chunkStart = i;
-          chunk = c;
-        }
-      }
-    }
-    if (chunkStart != -1) {
-      assert(result[chunk - 0x61] == null);
-      result[chunk - 0x61] = _computeKeywordStateTable(
-          start + 1, strings, chunkStart, offset + length - chunkStart);
-    } else {
-      assert(length == 1);
-      return new KeywordState(_EMPTY_TABLE, strings[offset]);
-    }
-    if (isLeaf) {
-      return new KeywordState(result, strings[offset]);
-    } else {
-      return new KeywordState(result, null);
-    }
-  }
-
-  /**
-   * Create and return the initial state in the state machine.
-   */
-  static KeywordState _createKeywordStateTable() {
-    List<Keyword> values = Keyword.values;
-    List<String> strings = new List<String>(values.length);
-    for (int i = 0; i < values.length; i++) {
-      strings[i] = values[i].syntax;
-    }
-    strings.sort();
-    return _computeKeywordStateTable(0, strings, 0, strings.length);
-  }
-}
-
-/**
- * A token representing a keyword in the language.
- */
-class KeywordToken extends Token {
-  /**
-   * The keyword being represented by this token.
-   */
-  final Keyword keyword;
-
-  /**
-   * Initialize a newly created token to represent the given [keyword] at the
-   * given [offset].
-   */
-  KeywordToken(this.keyword, int offset) : super(TokenType.KEYWORD, offset);
-
-  @override
-  String get lexeme => keyword.syntax;
-
-  @override
-  Token copy() => new KeywordToken(keyword, offset);
-
-  @override
-  Keyword value() => keyword;
-}
-
-/**
- * A keyword token that is preceded by comments.
- */
-class KeywordTokenWithComment extends KeywordToken {
-  /**
-   * The first comment in the list of comments that precede this token.
-   */
-  CommentToken _precedingComment;
-
-  /**
-   * Initialize a newly created token to to represent the given [keyword] at the
-   * given [offset] and to be preceded by the comments reachable from the given
-   * [comment].
-   */
-  KeywordTokenWithComment(Keyword keyword, int offset, this._precedingComment)
-      : super(keyword, offset) {
-    _setCommentParent(_precedingComment);
-  }
-
-  CommentToken get precedingComments => _precedingComment;
-
-  void set precedingComments(CommentToken comment) {
-    _precedingComment = comment;
-    _setCommentParent(_precedingComment);
-  }
-
-  @override
-  void applyDelta(int delta) {
-    super.applyDelta(delta);
-    Token token = precedingComments;
-    while (token != null) {
-      token.applyDelta(delta);
-      token = token.next;
-    }
-  }
-
-  @override
-  Token copy() => new KeywordTokenWithComment(
-      keyword, offset, copyComments(precedingComments));
-}
-
-/**
- * The class `Scanner` implements a scanner for Dart code.
- *
- * The lexical structure of Dart is ambiguous without knowledge of the context
- * in which a token is being scanned. For example, without context we cannot
- * determine whether source of the form "<<" should be scanned as a single
- * left-shift operator or as two left angle brackets. This scanner does not have
- * any context, so it always resolves such conflicts by scanning the longest
- * possible token.
- */
-class Scanner {
-  /**
-   * The source being scanned.
-   */
-  final Source source;
-
-  /**
-   * The reader used to access the characters in the source.
-   */
-  final CharacterReader _reader;
-
-  /**
-   * The error listener that will be informed of any errors that are found
-   * during the scan.
-   */
-  final AnalysisErrorListener _errorListener;
-
-  /**
-   * The flag specifying whether documentation comments should be parsed.
-   */
-  bool _preserveComments = true;
-
-  /**
-   * The token pointing to the head of the linked list of tokens.
-   */
-  Token _tokens;
-
-  /**
-   * The last token that was scanned.
-   */
-  Token _tail;
-
-  /**
-   * The first token in the list of comment tokens found since the last
-   * non-comment token.
-   */
-  Token _firstComment;
-
-  /**
-   * The last token in the list of comment tokens found since the last
-   * non-comment token.
-   */
-  Token _lastComment;
-
-  /**
-   * The index of the first character of the current token.
-   */
-  int _tokenStart = 0;
-
-  /**
-   * A list containing the offsets of the first character of each line in the
-   * source code.
-   */
-  List<int> _lineStarts = new List<int>();
-
-  /**
-   * A list, treated something like a stack, of tokens representing the
-   * beginning of a matched pair. It is used to pair the end tokens with the
-   * begin tokens.
-   */
-  List<BeginToken> _groupingStack = new List<BeginToken>();
-
-  /**
-   * The index of the last item in the [_groupingStack], or `-1` if the stack is
-   * empty.
-   */
-  int _stackEnd = -1;
-
-  /**
-   * A flag indicating whether any unmatched groups were found during the parse.
-   */
-  bool _hasUnmatchedGroups = false;
-
-  /**
-   * A flag indicating whether to parse generic method comments, of the form
-   * `/*=T*/` and `/*<T>*/`.
-   */
-  bool scanGenericMethodComments = false;
-
-  /**
-   * Initialize a newly created scanner to scan characters from the given
-   * [source]. The given character [_reader] will be used to read the characters
-   * in the source. The given [_errorListener] will be informed of any errors
-   * that are found.
-   */
-  Scanner(this.source, this._reader, this._errorListener) {
-    _tokens = new Token(TokenType.EOF, -1);
-    _tokens.setNext(_tokens);
-    _tail = _tokens;
-    _tokenStart = -1;
-    _lineStarts.add(0);
-  }
-
-  /**
-   * Return the first token in the token stream that was scanned.
-   */
-  Token get firstToken => _tokens.next;
-
-  /**
-   * Return `true` if any unmatched groups were found during the parse.
-   */
-  bool get hasUnmatchedGroups => _hasUnmatchedGroups;
-
-  /**
-   * Return an array containing the offsets of the first character of each line
-   * in the source code.
-   */
-  List<int> get lineStarts => _lineStarts;
-
-  /**
-   * Set whether documentation tokens should be preserved.
-   */
-  void set preserveComments(bool preserveComments) {
-    this._preserveComments = preserveComments;
-  }
-
-  /**
-   * Return the last token that was scanned.
-   */
-  Token get tail => _tail;
-
-  /**
-   * Append the given [token] to the end of the token stream being scanned. This
-   * method is intended to be used by subclasses that copy existing tokens and
-   * should not normally be used because it will fail to correctly associate any
-   * comments with the token being passed in.
-   */
-  void appendToken(Token token) {
-    _tail = _tail.setNext(token);
-  }
-
-  int bigSwitch(int next) {
-    _beginToken();
-    if (next == 0xD) {
-      // '\r'
-      next = _reader.advance();
-      if (next == 0xA) {
-        // '\n'
-        next = _reader.advance();
-      }
-      recordStartOfLine();
-      return next;
-    } else if (next == 0xA) {
-      // '\n'
-      next = _reader.advance();
-      recordStartOfLine();
-      return next;
-    } else if (next == 0x9 || next == 0x20) {
-      // '\t' || ' '
-      return _reader.advance();
-    }
-    if (next == 0x72) {
-      // 'r'
-      int peek = _reader.peek();
-      if (peek == 0x22 || peek == 0x27) {
-        // '"' || "'"
-        int start = _reader.offset;
-        return _tokenizeString(_reader.advance(), start, true);
-      }
-    }
-    if (0x61 <= next && next <= 0x7A) {
-      // 'a'-'z'
-      return _tokenizeKeywordOrIdentifier(next, true);
-    }
-    if ((0x41 <= next && next <= 0x5A) || next == 0x5F || next == 0x24) {
-      // 'A'-'Z' || '_' || '$'
-      return _tokenizeIdentifier(next, _reader.offset, true);
-    }
-    if (next == 0x3C) {
-      // '<'
-      return _tokenizeLessThan(next);
-    }
-    if (next == 0x3E) {
-      // '>'
-      return _tokenizeGreaterThan(next);
-    }
-    if (next == 0x3D) {
-      // '='
-      return _tokenizeEquals(next);
-    }
-    if (next == 0x21) {
-      // '!'
-      return _tokenizeExclamation(next);
-    }
-    if (next == 0x2B) {
-      // '+'
-      return _tokenizePlus(next);
-    }
-    if (next == 0x2D) {
-      // '-'
-      return _tokenizeMinus(next);
-    }
-    if (next == 0x2A) {
-      // '*'
-      return _tokenizeMultiply(next);
-    }
-    if (next == 0x25) {
-      // '%'
-      return _tokenizePercent(next);
-    }
-    if (next == 0x26) {
-      // '&'
-      return _tokenizeAmpersand(next);
-    }
-    if (next == 0x7C) {
-      // '|'
-      return _tokenizeBar(next);
-    }
-    if (next == 0x5E) {
-      // '^'
-      return _tokenizeCaret(next);
-    }
-    if (next == 0x5B) {
-      // '['
-      return _tokenizeOpenSquareBracket(next);
-    }
-    if (next == 0x7E) {
-      // '~'
-      return _tokenizeTilde(next);
-    }
-    if (next == 0x5C) {
-      // '\\'
-      _appendTokenOfType(TokenType.BACKSLASH);
-      return _reader.advance();
-    }
-    if (next == 0x23) {
-      // '#'
-      return _tokenizeTag(next);
-    }
-    if (next == 0x28) {
-      // '('
-      _appendBeginToken(TokenType.OPEN_PAREN);
-      return _reader.advance();
-    }
-    if (next == 0x29) {
-      // ')'
-      _appendEndToken(TokenType.CLOSE_PAREN, TokenType.OPEN_PAREN);
-      return _reader.advance();
-    }
-    if (next == 0x2C) {
-      // ','
-      _appendTokenOfType(TokenType.COMMA);
-      return _reader.advance();
-    }
-    if (next == 0x3A) {
-      // ':'
-      _appendTokenOfType(TokenType.COLON);
-      return _reader.advance();
-    }
-    if (next == 0x3B) {
-      // ';'
-      _appendTokenOfType(TokenType.SEMICOLON);
-      return _reader.advance();
-    }
-    if (next == 0x3F) {
-      // '?'
-      return _tokenizeQuestion();
-    }
-    if (next == 0x5D) {
-      // ']'
-      _appendEndToken(
-          TokenType.CLOSE_SQUARE_BRACKET, TokenType.OPEN_SQUARE_BRACKET);
-      return _reader.advance();
-    }
-    if (next == 0x60) {
-      // '`'
-      _appendTokenOfType(TokenType.BACKPING);
-      return _reader.advance();
-    }
-    if (next == 0x7B) {
-      // '{'
-      _appendBeginToken(TokenType.OPEN_CURLY_BRACKET);
-      return _reader.advance();
-    }
-    if (next == 0x7D) {
-      // '}'
-      _appendEndToken(
-          TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET);
-      return _reader.advance();
-    }
-    if (next == 0x2F) {
-      // '/'
-      return _tokenizeSlashOrComment(next);
-    }
-    if (next == 0x40) {
-      // '@'
-      _appendTokenOfType(TokenType.AT);
-      return _reader.advance();
-    }
-    if (next == 0x22 || next == 0x27) {
-      // '"' || "'"
-      return _tokenizeString(next, _reader.offset, false);
-    }
-    if (next == 0x2E) {
-      // '.'
-      return _tokenizeDotOrNumber(next);
-    }
-    if (next == 0x30) {
-      // '0'
-      return _tokenizeHexOrNumber(next);
-    }
-    if (0x31 <= next && next <= 0x39) {
-      // '1'-'9'
-      return _tokenizeNumber(next);
-    }
-    if (next == -1) {
-      // EOF
-      return -1;
-    }
-    _reportError(ScannerErrorCode.ILLEGAL_CHARACTER, [next]);
-    return _reader.advance();
-  }
-
-  /**
-   * Record the fact that we are at the beginning of a new line in the source.
-   */
-  void recordStartOfLine() {
-    _lineStarts.add(_reader.offset);
-  }
-
-  /**
-   * Record that the source begins on the given [line] and [column] at the
-   * current offset as given by the reader. Both the line and the column are
-   * one-based indexes. The line starts for lines before the given line will not
-   * be correct.
-   *
-   * This method must be invoked at most one time and must be invoked before
-   * scanning begins. The values provided must be sensible. The results are
-   * undefined if these conditions are violated.
-   */
-  void setSourceStart(int line, int column) {
-    int offset = _reader.offset;
-    if (line < 1 || column < 1 || offset < 0 || (line + column - 2) >= offset) {
-      return;
-    }
-    for (int i = 2; i < line; i++) {
-      _lineStarts.add(1);
-    }
-    _lineStarts.add(offset - column + 1);
-  }
-
-  /**
-   * Scan the source code to produce a list of tokens representing the source,
-   * and return the first token in the list of tokens that were produced.
-   */
-  Token tokenize() {
-    int next = _reader.advance();
-    while (next != -1) {
-      next = bigSwitch(next);
-    }
-    _appendEofToken();
-    return firstToken;
-  }
-
-  void _appendBeginToken(TokenType type) {
-    BeginToken token;
-    if (_firstComment == null) {
-      token = new BeginToken(type, _tokenStart);
-    } else {
-      token = new BeginTokenWithComment(type, _tokenStart, _firstComment);
-      _firstComment = null;
-      _lastComment = null;
-    }
-    _tail = _tail.setNext(token);
-    _groupingStack.add(token);
-    _stackEnd++;
-  }
-
-  void _appendCommentToken(TokenType type, String value) {
-    CommentToken token = null;
-    TokenType genericComment = _matchGenericMethodCommentType(value);
-    if (genericComment != null) {
-      token = new CommentToken(genericComment, value, _tokenStart);
-    } else if (!_preserveComments) {
-      // Ignore comment tokens if client specified that it doesn't need them.
-      return;
-    } else {
-      // OK, remember comment tokens.
-      if (_isDocumentationComment(value)) {
-        token = new DocumentationCommentToken(type, value, _tokenStart);
-      } else {
-        token = new CommentToken(type, value, _tokenStart);
-      }
-    }
-    if (_firstComment == null) {
-      _firstComment = token;
-      _lastComment = _firstComment;
-    } else {
-      _lastComment = _lastComment.setNext(token);
-    }
-  }
-
-  void _appendEndToken(TokenType type, TokenType beginType) {
-    Token token;
-    if (_firstComment == null) {
-      token = new Token(type, _tokenStart);
-    } else {
-      token = new TokenWithComment(type, _tokenStart, _firstComment);
-      _firstComment = null;
-      _lastComment = null;
-    }
-    _tail = _tail.setNext(token);
-    if (_stackEnd >= 0) {
-      BeginToken begin = _groupingStack[_stackEnd];
-      if (begin.type == beginType) {
-        begin.endToken = token;
-        _groupingStack.removeAt(_stackEnd--);
-      }
-    }
-  }
-
-  void _appendEofToken() {
-    Token eofToken;
-    if (_firstComment == null) {
-      eofToken = new Token(TokenType.EOF, _reader.offset + 1);
-    } else {
-      eofToken = new TokenWithComment(
-          TokenType.EOF, _reader.offset + 1, _firstComment);
-      _firstComment = null;
-      _lastComment = null;
-    }
-    // The EOF token points to itself so that there is always infinite
-    // look-ahead.
-    eofToken.setNext(eofToken);
-    _tail = _tail.setNext(eofToken);
-    if (_stackEnd >= 0) {
-      _hasUnmatchedGroups = true;
-      // TODO(brianwilkerson) Fix the ungrouped tokens?
-    }
-  }
-
-  void _appendKeywordToken(Keyword keyword) {
-    if (_firstComment == null) {
-      _tail = _tail.setNext(new KeywordToken(keyword, _tokenStart));
-    } else {
-      _tail = _tail.setNext(
-          new KeywordTokenWithComment(keyword, _tokenStart, _firstComment));
-      _firstComment = null;
-      _lastComment = null;
-    }
-  }
-
-  void _appendStringToken(TokenType type, String value) {
-    if (_firstComment == null) {
-      _tail = _tail.setNext(new StringToken(type, value, _tokenStart));
-    } else {
-      _tail = _tail.setNext(
-          new StringTokenWithComment(type, value, _tokenStart, _firstComment));
-      _firstComment = null;
-      _lastComment = null;
-    }
-  }
-
-  void _appendStringTokenWithOffset(TokenType type, String value, int offset) {
-    if (_firstComment == null) {
-      _tail = _tail.setNext(new StringToken(type, value, _tokenStart + offset));
-    } else {
-      _tail = _tail.setNext(new StringTokenWithComment(
-          type, value, _tokenStart + offset, _firstComment));
-      _firstComment = null;
-      _lastComment = null;
-    }
-  }
-
-  void _appendTokenOfType(TokenType type) {
-    if (_firstComment == null) {
-      _tail = _tail.setNext(new Token(type, _tokenStart));
-    } else {
-      _tail =
-          _tail.setNext(new TokenWithComment(type, _tokenStart, _firstComment));
-      _firstComment = null;
-      _lastComment = null;
-    }
-  }
-
-  void _appendTokenOfTypeWithOffset(TokenType type, int offset) {
-    if (_firstComment == null) {
-      _tail = _tail.setNext(new Token(type, offset));
-    } else {
-      _tail = _tail.setNext(new TokenWithComment(type, offset, _firstComment));
-      _firstComment = null;
-      _lastComment = null;
-    }
-  }
-
-  void _beginToken() {
-    _tokenStart = _reader.offset;
-  }
-
-  /**
-   * Return the beginning token corresponding to a closing brace that was found
-   * while scanning inside a string interpolation expression. Tokens that cannot
-   * be matched with the closing brace will be dropped from the stack.
-   */
-  BeginToken _findTokenMatchingClosingBraceInInterpolationExpression() {
-    while (_stackEnd >= 0) {
-      BeginToken begin = _groupingStack[_stackEnd];
-      if (begin.type == TokenType.OPEN_CURLY_BRACKET ||
-          begin.type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
-        return begin;
-      }
-      _hasUnmatchedGroups = true;
-      _groupingStack.removeAt(_stackEnd--);
-    }
-    //
-    // We should never get to this point because we wouldn't be inside a string
-    // interpolation expression unless we had previously found the start of the
-    // expression.
-    //
-    return null;
-  }
-
-  /**
-   * Checks if [value] is the start of a generic method type annotation comment.
-   *
-   * This can either be of the form `/*<T>*/` or `/*=T*/`. The token type is
-   * returned, or null if it was not a generic method comment.
-   */
-  TokenType _matchGenericMethodCommentType(String value) {
-    if (scanGenericMethodComments) {
-      // Match /*< and >*/
-      if (StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x3C) &&
-          StringUtilities.endsWith3(value, 0x3E, 0x2A, 0x2F)) {
-        return TokenType.GENERIC_METHOD_TYPE_LIST;
-      }
-      // Match /*=
-      if (StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x3D)) {
-        return TokenType.GENERIC_METHOD_TYPE_ASSIGN;
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Report an error at the current offset. The [errorCode] is the error code
-   * indicating the nature of the error. The [arguments] are any arguments
-   * needed to complete the error message
-   */
-  void _reportError(ScannerErrorCode errorCode, [List<Object> arguments]) {
-    _errorListener.onError(
-        new AnalysisError(source, _reader.offset, 1, errorCode, arguments));
-  }
-
-  int _select(int choice, TokenType yesType, TokenType noType) {
-    int next = _reader.advance();
-    if (next == choice) {
-      _appendTokenOfType(yesType);
-      return _reader.advance();
-    } else {
-      _appendTokenOfType(noType);
-      return next;
-    }
-  }
-
-  int _selectWithOffset(
-      int choice, TokenType yesType, TokenType noType, int offset) {
-    int next = _reader.advance();
-    if (next == choice) {
-      _appendTokenOfTypeWithOffset(yesType, offset);
-      return _reader.advance();
-    } else {
-      _appendTokenOfTypeWithOffset(noType, offset);
-      return next;
-    }
-  }
-
-  int _tokenizeAmpersand(int next) {
-    // && &= &
-    next = _reader.advance();
-    if (next == 0x26) {
-      _appendTokenOfType(TokenType.AMPERSAND_AMPERSAND);
-      return _reader.advance();
-    } else if (next == 0x3D) {
-      _appendTokenOfType(TokenType.AMPERSAND_EQ);
-      return _reader.advance();
-    } else {
-      _appendTokenOfType(TokenType.AMPERSAND);
-      return next;
-    }
-  }
-
-  int _tokenizeBar(int next) {
-    // | || |=
-    next = _reader.advance();
-    if (next == 0x7C) {
-      _appendTokenOfType(TokenType.BAR_BAR);
-      return _reader.advance();
-    } else if (next == 0x3D) {
-      _appendTokenOfType(TokenType.BAR_EQ);
-      return _reader.advance();
-    } else {
-      _appendTokenOfType(TokenType.BAR);
-      return next;
-    }
-  }
-
-  int _tokenizeCaret(int next) =>
-      _select(0x3D, TokenType.CARET_EQ, TokenType.CARET);
-
-  int _tokenizeDotOrNumber(int next) {
-    int start = _reader.offset;
-    next = _reader.advance();
-    if (0x30 <= next && next <= 0x39) {
-      return _tokenizeFractionPart(next, start);
-    } else if (0x2E == next) {
-      return _select(
-          0x2E, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PERIOD);
-    } else {
-      _appendTokenOfType(TokenType.PERIOD);
-      return next;
-    }
-  }
-
-  int _tokenizeEquals(int next) {
-    // = == =>
-    next = _reader.advance();
-    if (next == 0x3D) {
-      _appendTokenOfType(TokenType.EQ_EQ);
-      return _reader.advance();
-    } else if (next == 0x3E) {
-      _appendTokenOfType(TokenType.FUNCTION);
-      return _reader.advance();
-    }
-    _appendTokenOfType(TokenType.EQ);
-    return next;
-  }
-
-  int _tokenizeExclamation(int next) {
-    // ! !=
-    next = _reader.advance();
-    if (next == 0x3D) {
-      _appendTokenOfType(TokenType.BANG_EQ);
-      return _reader.advance();
-    }
-    _appendTokenOfType(TokenType.BANG);
-    return next;
-  }
-
-  int _tokenizeExponent(int next) {
-    if (next == 0x2B || next == 0x2D) {
-      next = _reader.advance();
-    }
-    bool hasDigits = false;
-    while (true) {
-      if (0x30 <= next && next <= 0x39) {
-        hasDigits = true;
-      } else {
-        if (!hasDigits) {
-          _reportError(ScannerErrorCode.MISSING_DIGIT);
-        }
-        return next;
-      }
-      next = _reader.advance();
-    }
-  }
-
-  int _tokenizeFractionPart(int next, int start) {
-    bool done = false;
-    bool hasDigit = false;
-    LOOP: while (!done) {
-      if (0x30 <= next && next <= 0x39) {
-        hasDigit = true;
-      } else if (0x65 == next || 0x45 == next) {
-        hasDigit = true;
-        next = _tokenizeExponent(_reader.advance());
-        done = true;
-        continue LOOP;
-      } else {
-        done = true;
-        continue LOOP;
-      }
-      next = _reader.advance();
-    }
-    if (!hasDigit) {
-      _appendStringToken(TokenType.INT, _reader.getString(start, -2));
-      if (0x2E == next) {
-        return _selectWithOffset(0x2E, TokenType.PERIOD_PERIOD_PERIOD,
-            TokenType.PERIOD_PERIOD, _reader.offset - 1);
-      }
-      _appendTokenOfTypeWithOffset(TokenType.PERIOD, _reader.offset - 1);
-      return bigSwitch(next);
-    }
-    _appendStringToken(
-        TokenType.DOUBLE, _reader.getString(start, next < 0 ? 0 : -1));
-    return next;
-  }
-
-  int _tokenizeGreaterThan(int next) {
-    // > >= >> >>=
-    next = _reader.advance();
-    if (0x3D == next) {
-      _appendTokenOfType(TokenType.GT_EQ);
-      return _reader.advance();
-    } else if (0x3E == next) {
-      next = _reader.advance();
-      if (0x3D == next) {
-        _appendTokenOfType(TokenType.GT_GT_EQ);
-        return _reader.advance();
-      } else {
-        _appendTokenOfType(TokenType.GT_GT);
-        return next;
-      }
-    } else {
-      _appendTokenOfType(TokenType.GT);
-      return next;
-    }
-  }
-
-  int _tokenizeHex(int next) {
-    int start = _reader.offset - 1;
-    bool hasDigits = false;
-    while (true) {
-      next = _reader.advance();
-      if ((0x30 <= next && next <= 0x39) ||
-          (0x41 <= next && next <= 0x46) ||
-          (0x61 <= next && next <= 0x66)) {
-        hasDigits = true;
-      } else {
-        if (!hasDigits) {
-          _reportError(ScannerErrorCode.MISSING_HEX_DIGIT);
-        }
-        _appendStringToken(
-            TokenType.HEXADECIMAL, _reader.getString(start, next < 0 ? 0 : -1));
-        return next;
-      }
-    }
-  }
-
-  int _tokenizeHexOrNumber(int next) {
-    int x = _reader.peek();
-    if (x == 0x78 || x == 0x58) {
-      _reader.advance();
-      return _tokenizeHex(x);
-    }
-    return _tokenizeNumber(next);
-  }
-
-  int _tokenizeIdentifier(int next, int start, bool allowDollar) {
-    while ((0x61 <= next && next <= 0x7A) ||
-        (0x41 <= next && next <= 0x5A) ||
-        (0x30 <= next && next <= 0x39) ||
-        next == 0x5F ||
-        (next == 0x24 && allowDollar)) {
-      next = _reader.advance();
-    }
-    _appendStringToken(
-        TokenType.IDENTIFIER, _reader.getString(start, next < 0 ? 0 : -1));
-    return next;
-  }
-
-  int _tokenizeInterpolatedExpression(int next, int start) {
-    _appendBeginToken(TokenType.STRING_INTERPOLATION_EXPRESSION);
-    next = _reader.advance();
-    while (next != -1) {
-      if (next == 0x7D) {
-        BeginToken begin =
-            _findTokenMatchingClosingBraceInInterpolationExpression();
-        if (begin == null) {
-          _beginToken();
-          _appendTokenOfType(TokenType.CLOSE_CURLY_BRACKET);
-          next = _reader.advance();
-          _beginToken();
-          return next;
-        } else if (begin.type == TokenType.OPEN_CURLY_BRACKET) {
-          _beginToken();
-          _appendEndToken(
-              TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET);
-          next = _reader.advance();
-          _beginToken();
-        } else if (begin.type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
-          _beginToken();
-          _appendEndToken(TokenType.CLOSE_CURLY_BRACKET,
-              TokenType.STRING_INTERPOLATION_EXPRESSION);
-          next = _reader.advance();
-          _beginToken();
-          return next;
-        }
-      } else {
-        next = bigSwitch(next);
-      }
-    }
-    return next;
-  }
-
-  int _tokenizeInterpolatedIdentifier(int next, int start) {
-    _appendStringTokenWithOffset(
-        TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 0);
-    if ((0x41 <= next && next <= 0x5A) ||
-        (0x61 <= next && next <= 0x7A) ||
-        next == 0x5F) {
-      _beginToken();
-      next = _tokenizeKeywordOrIdentifier(next, false);
-    }
-    _beginToken();
-    return next;
-  }
-
-  int _tokenizeKeywordOrIdentifier(int next, bool allowDollar) {
-    KeywordState state = KeywordState.KEYWORD_STATE;
-    int start = _reader.offset;
-    while (state != null && 0x61 <= next && next <= 0x7A) {
-      state = state.next(next);
-      next = _reader.advance();
-    }
-    if (state == null || state.keyword() == null) {
-      return _tokenizeIdentifier(next, start, allowDollar);
-    }
-    if ((0x41 <= next && next <= 0x5A) ||
-        (0x30 <= next && next <= 0x39) ||
-        next == 0x5F ||
-        next == 0x24) {
-      return _tokenizeIdentifier(next, start, allowDollar);
-    } else if (next < 128) {
-      _appendKeywordToken(state.keyword());
-      return next;
-    } else {
-      return _tokenizeIdentifier(next, start, allowDollar);
-    }
-  }
-
-  int _tokenizeLessThan(int next) {
-    // < <= << <<=
-    next = _reader.advance();
-    if (0x3D == next) {
-      _appendTokenOfType(TokenType.LT_EQ);
-      return _reader.advance();
-    } else if (0x3C == next) {
-      return _select(0x3D, TokenType.LT_LT_EQ, TokenType.LT_LT);
-    } else {
-      _appendTokenOfType(TokenType.LT);
-      return next;
-    }
-  }
-
-  int _tokenizeMinus(int next) {
-    // - -- -=
-    next = _reader.advance();
-    if (next == 0x2D) {
-      _appendTokenOfType(TokenType.MINUS_MINUS);
-      return _reader.advance();
-    } else if (next == 0x3D) {
-      _appendTokenOfType(TokenType.MINUS_EQ);
-      return _reader.advance();
-    } else {
-      _appendTokenOfType(TokenType.MINUS);
-      return next;
-    }
-  }
-
-  int _tokenizeMultiLineComment(int next) {
-    int nesting = 1;
-    next = _reader.advance();
-    while (true) {
-      if (-1 == next) {
-        _reportError(ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT);
-        _appendCommentToken(
-            TokenType.MULTI_LINE_COMMENT, _reader.getString(_tokenStart, 0));
-        return next;
-      } else if (0x2A == next) {
-        next = _reader.advance();
-        if (0x2F == next) {
-          --nesting;
-          if (0 == nesting) {
-            _appendCommentToken(TokenType.MULTI_LINE_COMMENT,
-                _reader.getString(_tokenStart, 0));
-            return _reader.advance();
-          } else {
-            next = _reader.advance();
-          }
-        }
-      } else if (0x2F == next) {
-        next = _reader.advance();
-        if (0x2A == next) {
-          next = _reader.advance();
-          ++nesting;
-        }
-      } else if (next == 0xD) {
-        next = _reader.advance();
-        if (next == 0xA) {
-          next = _reader.advance();
-        }
-        recordStartOfLine();
-      } else if (next == 0xA) {
-        next = _reader.advance();
-        recordStartOfLine();
-      } else {
-        next = _reader.advance();
-      }
-    }
-  }
-
-  int _tokenizeMultiLineRawString(int quoteChar, int start) {
-    int next = _reader.advance();
-    outer: while (next != -1) {
-      while (next != quoteChar) {
-        if (next == -1) {
-          break outer;
-        } else if (next == 0xD) {
-          next = _reader.advance();
-          if (next == 0xA) {
-            next = _reader.advance();
-          }
-          recordStartOfLine();
-        } else if (next == 0xA) {
-          next = _reader.advance();
-          recordStartOfLine();
-        } else {
-          next = _reader.advance();
-        }
-      }
-      next = _reader.advance();
-      if (next == quoteChar) {
-        next = _reader.advance();
-        if (next == quoteChar) {
-          _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
-          return _reader.advance();
-        }
-      }
-    }
-    _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
-    _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
-    return _reader.advance();
-  }
-
-  int _tokenizeMultiLineString(int quoteChar, int start, bool raw) {
-    if (raw) {
-      return _tokenizeMultiLineRawString(quoteChar, start);
-    }
-    int next = _reader.advance();
-    while (next != -1) {
-      if (next == 0x24) {
-        _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
-        next = _tokenizeStringInterpolation(start);
-        _beginToken();
-        start = _reader.offset;
-        continue;
-      }
-      if (next == quoteChar) {
-        next = _reader.advance();
-        if (next == quoteChar) {
-          next = _reader.advance();
-          if (next == quoteChar) {
-            _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
-            return _reader.advance();
-          }
-        }
-        continue;
-      }
-      if (next == 0x5C) {
-        next = _reader.advance();
-        if (next == -1) {
-          break;
-        }
-        if (next == 0xD) {
-          next = _reader.advance();
-          if (next == 0xA) {
-            next = _reader.advance();
-          }
-          recordStartOfLine();
-        } else if (next == 0xA) {
-          recordStartOfLine();
-          next = _reader.advance();
-        } else {
-          next = _reader.advance();
-        }
-      } else if (next == 0xD) {
-        next = _reader.advance();
-        if (next == 0xA) {
-          next = _reader.advance();
-        }
-        recordStartOfLine();
-      } else if (next == 0xA) {
-        recordStartOfLine();
-        next = _reader.advance();
-      } else {
-        next = _reader.advance();
-      }
-    }
-    _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
-    if (start == _reader.offset) {
-      _appendStringTokenWithOffset(TokenType.STRING, "", 1);
-    } else {
-      _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
-    }
-    return _reader.advance();
-  }
-
-  int _tokenizeMultiply(int next) =>
-      _select(0x3D, TokenType.STAR_EQ, TokenType.STAR);
-
-  int _tokenizeNumber(int next) {
-    int start = _reader.offset;
-    while (true) {
-      next = _reader.advance();
-      if (0x30 <= next && next <= 0x39) {
-        continue;
-      } else if (next == 0x2E) {
-        return _tokenizeFractionPart(_reader.advance(), start);
-      } else if (next == 0x65 || next == 0x45) {
-        return _tokenizeFractionPart(next, start);
-      } else {
-        _appendStringToken(
-            TokenType.INT, _reader.getString(start, next < 0 ? 0 : -1));
-        return next;
-      }
-    }
-  }
-
-  int _tokenizeOpenSquareBracket(int next) {
-    // [ []  []=
-    next = _reader.advance();
-    if (next == 0x5D) {
-      return _select(0x3D, TokenType.INDEX_EQ, TokenType.INDEX);
-    } else {
-      _appendBeginToken(TokenType.OPEN_SQUARE_BRACKET);
-      return next;
-    }
-  }
-
-  int _tokenizePercent(int next) =>
-      _select(0x3D, TokenType.PERCENT_EQ, TokenType.PERCENT);
-
-  int _tokenizePlus(int next) {
-    // + ++ +=
-    next = _reader.advance();
-    if (0x2B == next) {
-      _appendTokenOfType(TokenType.PLUS_PLUS);
-      return _reader.advance();
-    } else if (0x3D == next) {
-      _appendTokenOfType(TokenType.PLUS_EQ);
-      return _reader.advance();
-    } else {
-      _appendTokenOfType(TokenType.PLUS);
-      return next;
-    }
-  }
-
-  int _tokenizeQuestion() {
-    // ? ?. ?? ??=
-    int next = _reader.advance();
-    if (next == 0x2E) {
-      // '.'
-      _appendTokenOfType(TokenType.QUESTION_PERIOD);
-      return _reader.advance();
-    } else if (next == 0x3F) {
-      // '?'
-      next = _reader.advance();
-      if (next == 0x3D) {
-        // '='
-        _appendTokenOfType(TokenType.QUESTION_QUESTION_EQ);
-        return _reader.advance();
-      } else {
-        _appendTokenOfType(TokenType.QUESTION_QUESTION);
-        return next;
-      }
-    } else {
-      _appendTokenOfType(TokenType.QUESTION);
-      return next;
-    }
-  }
-
-  int _tokenizeSingleLineComment(int next) {
-    while (true) {
-      next = _reader.advance();
-      if (-1 == next) {
-        _appendCommentToken(
-            TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, 0));
-        return next;
-      } else if (0xA == next || 0xD == next) {
-        _appendCommentToken(
-            TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, -1));
-        return next;
-      }
-    }
-  }
-
-  int _tokenizeSingleLineRawString(int next, int quoteChar, int start) {
-    next = _reader.advance();
-    while (next != -1) {
-      if (next == quoteChar) {
-        _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
-        return _reader.advance();
-      } else if (next == 0xD || next == 0xA) {
-        _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
-        _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
-        return _reader.advance();
-      }
-      next = _reader.advance();
-    }
-    _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
-    _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
-    return _reader.advance();
-  }
-
-  int _tokenizeSingleLineString(int next, int quoteChar, int start) {
-    while (next != quoteChar) {
-      if (next == 0x5C) {
-        next = _reader.advance();
-      } else if (next == 0x24) {
-        _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
-        next = _tokenizeStringInterpolation(start);
-        _beginToken();
-        start = _reader.offset;
-        continue;
-      }
-      if (next <= 0xD && (next == 0xA || next == 0xD || next == -1)) {
-        _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
-        if (start == _reader.offset) {
-          _appendStringTokenWithOffset(TokenType.STRING, "", 1);
-        } else if (next == -1) {
-          _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
-        } else {
-          _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
-        }
-        return _reader.advance();
-      }
-      next = _reader.advance();
-    }
-    _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
-    return _reader.advance();
-  }
-
-  int _tokenizeSlashOrComment(int next) {
-    next = _reader.advance();
-    if (0x2A == next) {
-      return _tokenizeMultiLineComment(next);
-    } else if (0x2F == next) {
-      return _tokenizeSingleLineComment(next);
-    } else if (0x3D == next) {
-      _appendTokenOfType(TokenType.SLASH_EQ);
-      return _reader.advance();
-    } else {
-      _appendTokenOfType(TokenType.SLASH);
-      return next;
-    }
-  }
-
-  int _tokenizeString(int next, int start, bool raw) {
-    int quoteChar = next;
-    next = _reader.advance();
-    if (quoteChar == next) {
-      next = _reader.advance();
-      if (quoteChar == next) {
-        // Multiline string.
-        return _tokenizeMultiLineString(quoteChar, start, raw);
-      } else {
-        // Empty string.
-        _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
-        return next;
-      }
-    }
-    if (raw) {
-      return _tokenizeSingleLineRawString(next, quoteChar, start);
-    } else {
-      return _tokenizeSingleLineString(next, quoteChar, start);
-    }
-  }
-
-  int _tokenizeStringInterpolation(int start) {
-    _beginToken();
-    int next = _reader.advance();
-    if (next == 0x7B) {
-      return _tokenizeInterpolatedExpression(next, start);
-    } else {
-      return _tokenizeInterpolatedIdentifier(next, start);
-    }
-  }
-
-  int _tokenizeTag(int next) {
-    // # or #!.*[\n\r]
-    if (_reader.offset == 0) {
-      if (_reader.peek() == 0x21) {
-        do {
-          next = _reader.advance();
-        } while (next != 0xA && next != 0xD && next > 0);
-        _appendStringToken(
-            TokenType.SCRIPT_TAG, _reader.getString(_tokenStart, 0));
-        return next;
-      }
-    }
-    _appendTokenOfType(TokenType.HASH);
-    return _reader.advance();
-  }
-
-  int _tokenizeTilde(int next) {
-    // ~ ~/ ~/=
-    next = _reader.advance();
-    if (next == 0x2F) {
-      return _select(0x3D, TokenType.TILDE_SLASH_EQ, TokenType.TILDE_SLASH);
-    } else {
-      _appendTokenOfType(TokenType.TILDE);
-      return next;
-    }
-  }
-
-  /**
-   * Checks if [value] is a single-line or multi-line comment.
-   */
-  static bool _isDocumentationComment(String value) {
-    return StringUtilities.startsWith3(value, 0, 0x2F, 0x2F, 0x2F) ||
-        StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x2A);
-  }
-}
-
-/**
- * The error codes used for errors detected by the scanner.
- */
-class ScannerErrorCode extends ErrorCode {
-  static const ScannerErrorCode ILLEGAL_CHARACTER =
-      const ScannerErrorCode('ILLEGAL_CHARACTER', "Illegal character {0}");
-
-  static const ScannerErrorCode MISSING_DIGIT =
-      const ScannerErrorCode('MISSING_DIGIT', "Decimal digit expected");
-
-  static const ScannerErrorCode MISSING_HEX_DIGIT =
-      const ScannerErrorCode('MISSING_HEX_DIGIT', "Hexidecimal digit expected");
-
-  static const ScannerErrorCode MISSING_QUOTE =
-      const ScannerErrorCode('MISSING_QUOTE', "Expected quote (' or \")");
-
-  static const ScannerErrorCode UNABLE_GET_CONTENT = const ScannerErrorCode(
-      'UNABLE_GET_CONTENT', "Unable to get content: {0}");
-
-  static const ScannerErrorCode UNTERMINATED_MULTI_LINE_COMMENT =
-      const ScannerErrorCode(
-          'UNTERMINATED_MULTI_LINE_COMMENT', "Unterminated multi-line comment");
-
-  static const ScannerErrorCode UNTERMINATED_STRING_LITERAL =
-      const ScannerErrorCode(
-          'UNTERMINATED_STRING_LITERAL', "Unterminated string literal");
-
-  /**
-   * Initialize a newly created error code to have the given [name]. The message
-   * associated with the error will be created from the given [message]
-   * template. The correction associated with the error will be created from the
-   * given [correction] template.
-   */
-  const ScannerErrorCode(String name, String message, [String correction])
-      : super(name, message, correction);
-
-  @override
-  ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
-
-  @override
-  ErrorType get type => ErrorType.SYNTACTIC_ERROR;
-}
-
-/**
- * A token whose value is independent of it's type.
- */
-class StringToken extends Token {
-  /**
-   * The lexeme represented by this token.
-   */
-  String _value;
-
-  /**
-   * Initialize a newly created token to represent a token of the given [type]
-   * with the given [value] at the given [offset].
-   */
-  StringToken(TokenType type, String value, int offset) : super(type, offset) {
-    this._value = StringUtilities.intern(value);
-  }
-
-  @override
-  String get lexeme => _value;
-
-  @override
-  Token copy() => new StringToken(type, _value, offset);
-
-  @override
-  String value() => _value;
-}
-
-/**
- * A string token that is preceded by comments.
- */
-class StringTokenWithComment extends StringToken {
-  /**
-   * The first comment in the list of comments that precede this token.
-   */
-  CommentToken _precedingComment;
-
-  /**
-   * Initialize a newly created token to have the given [type] at the given
-   * [offset] and to be preceded by the comments reachable from the given
-   * [comment].
-   */
-  StringTokenWithComment(
-      TokenType type, String value, int offset, this._precedingComment)
-      : super(type, value, offset) {
-    _setCommentParent(_precedingComment);
-  }
-
-  CommentToken get precedingComments => _precedingComment;
-
-  void set precedingComments(CommentToken comment) {
-    _precedingComment = comment;
-    _setCommentParent(_precedingComment);
-  }
-
-  @override
-  void applyDelta(int delta) {
-    super.applyDelta(delta);
-    Token token = precedingComments;
-    while (token != null) {
-      token.applyDelta(delta);
-      token = token.next;
-    }
-  }
-
-  @override
-  Token copy() => new StringTokenWithComment(
-      type, lexeme, offset, copyComments(precedingComments));
-}
-
-/**
- * A [CharacterReader] that reads characters from a character sequence, but adds
- * a delta when reporting the current character offset so that the character
- * sequence can be a subsequence from a larger sequence.
- */
-class SubSequenceReader extends CharSequenceReader {
-  /**
-   * The offset from the beginning of the file to the beginning of the source
-   * being scanned.
-   */
-  final int _offsetDelta;
-
-  /**
-   * Initialize a newly created reader to read the characters in the given
-   * [sequence]. The [_offsetDelta] is the offset from the beginning of the file
-   * to the beginning of the source being scanned
-   */
-  SubSequenceReader(String sequence, this._offsetDelta) : super(sequence);
-
-  @override
-  int get offset => _offsetDelta + super.offset;
-
-  @override
-  void set offset(int offset) {
-    super.offset = offset - _offsetDelta;
-  }
-
-  @override
-  String getString(int start, int endDelta) =>
-      super.getString(start - _offsetDelta, endDelta);
-}
-
-/**
- * A token whose value is independent of it's type.
- */
-class SyntheticStringToken extends StringToken {
-  /**
-   * Initialize a newly created token to represent a token of the given [type]
-   * with the given [value] at the given [offset].
-   */
-  SyntheticStringToken(TokenType type, String value, int offset)
-      : super(type, value, offset);
-
-  @override
-  bool get isSynthetic => true;
-}
-
-/**
- * A token that was scanned from the input. Each token knows which tokens
- * precede and follow it, acting as a link in a doubly linked list of tokens.
- */
-class Token {
-  /**
-   * The type of the token.
-   */
-  final TokenType type;
-
-  /**
-   * The offset from the beginning of the file to the first character in the
-   * token.
-   */
-  int offset = 0;
-
-  /**
-   * The previous token in the token stream.
-   */
-  Token previous;
-
-  /**
-   * The next token in the token stream.
-   */
-  Token _next;
-
-  /**
-   * Initialize a newly created token to have the given [type] and [offset].
-   */
-  Token(this.type, this.offset);
-
-  /**
-   * Return the offset from the beginning of the file to the character after the
-   * last character of the token.
-   */
-  int get end => offset + length;
-
-  /**
-   * Return `true` if this token represents an operator.
-   */
-  bool get isOperator => type.isOperator;
-
-  /**
-   * Return `true` if this token is a synthetic token. A synthetic token is a
-   * token that was introduced by the parser in order to recover from an error
-   * in the code.
-   */
-  bool get isSynthetic => length == 0;
-
-  /**
-   * Return `true` if this token represents an operator that can be defined by
-   * users.
-   */
-  bool get isUserDefinableOperator => type.isUserDefinableOperator;
-
-  /**
-   * Return the number of characters in the node's source range.
-   */
-  int get length => lexeme.length;
-
-  /**
-   * Return the lexeme that represents this token.
-   */
-  String get lexeme => type.lexeme;
-
-  /**
-   * Return the next token in the token stream.
-   */
-  Token get next => _next;
-
-  /**
-   * Return the first comment in the list of comments that precede this token,
-   * or `null` if there are no comments preceding this token. Additional
-   * comments can be reached by following the token stream using [next] until
-   * `null` is returned.
-   *
-   * For example, if the original contents were `/* one */ /* two */ id`, then
-   * the first preceding comment token will have a lexeme of `/* one */` and
-   * the next comment token will have a lexeme of `/* two */`.
-   */
-  CommentToken get precedingComments => null;
-
-  /**
-   * Apply (add) the given [delta] to this token's offset.
-   */
-  void applyDelta(int delta) {
-    offset += delta;
-  }
-
-  /**
-   * Return a newly created token that is a copy of this token but that is not a
-   * part of any token stream.
-   */
-  Token copy() => new Token(type, offset);
-
-  /**
-   * Copy a linked list of comment tokens identical to the given comment tokens.
-   */
-  Token copyComments(Token token) {
-    if (token == null) {
-      return null;
-    }
-    Token head = token.copy();
-    Token tail = head;
-    token = token.next;
-    while (token != null) {
-      tail = tail.setNext(token.copy());
-      token = token.next;
-    }
-    return head;
-  }
-
-  /**
-   * Return `true` if this token has any one of the given [types].
-   */
-  bool matchesAny(List<TokenType> types) {
-    for (TokenType type in types) {
-      if (this.type == type) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Set the next token in the token stream to the given [token]. This has the
-   * side-effect of setting this token to be the previous token for the given
-   * token. Return the token that was passed in.
-   */
-  Token setNext(Token token) {
-    _next = token;
-    token.previous = this;
-    return token;
-  }
-
-  /**
-   * Set the next token in the token stream to the given token without changing
-   * which token is the previous token for the given token. Return the token
-   * that was passed in.
-   */
-  Token setNextWithoutSettingPrevious(Token token) {
-    _next = token;
-    return token;
-  }
-
-  @override
-  String toString() => lexeme;
-
-  /**
-   * Return the value of this token. For keyword tokens, this is the keyword
-   * associated with the token, for other tokens it is the lexeme associated
-   * with the token.
-   */
-  Object value() => type.lexeme;
-
-  /**
-   * Sets the `parent` property to `this` for the given [comment] and all the
-   * next tokens.
-   */
-  void _setCommentParent(CommentToken comment) {
-    while (comment != null) {
-      comment.parent = this;
-      comment = comment.next;
-    }
-  }
-
-  /**
-   * Compare the given [tokens] to find the token that appears first in the
-   * source being parsed. That is, return the left-most of all of the tokens.
-   * The list must be non-`null`, but the elements of the list are allowed to be
-   * `null`. Return the token with the smallest offset, or `null` if the list is
-   * empty or if all of the elements of the list are `null`.
-   */
-  static Token lexicallyFirst(List<Token> tokens) {
-    Token first = null;
-    int offset = -1;
-    for (Token token in tokens) {
-      if (token != null && (offset < 0 || token.offset < offset)) {
-        first = token;
-        offset = token.offset;
-      }
-    }
-    return first;
-  }
-}
-
-/**
- * The classes (or groups) of tokens with a similar use.
- */
-class TokenClass {
-  /**
-   * A value used to indicate that the token type is not part of any specific
-   * class of token.
-   */
-  static const TokenClass NO_CLASS = const TokenClass('NO_CLASS');
-
-  /**
-   * A value used to indicate that the token type is an additive operator.
-   */
-  static const TokenClass ADDITIVE_OPERATOR =
-      const TokenClass('ADDITIVE_OPERATOR', 13);
-
-  /**
-   * A value used to indicate that the token type is an assignment operator.
-   */
-  static const TokenClass ASSIGNMENT_OPERATOR =
-      const TokenClass('ASSIGNMENT_OPERATOR', 1);
-
-  /**
-   * A value used to indicate that the token type is a bitwise-and operator.
-   */
-  static const TokenClass BITWISE_AND_OPERATOR =
-      const TokenClass('BITWISE_AND_OPERATOR', 11);
-
-  /**
-   * A value used to indicate that the token type is a bitwise-or operator.
-   */
-  static const TokenClass BITWISE_OR_OPERATOR =
-      const TokenClass('BITWISE_OR_OPERATOR', 9);
-
-  /**
-   * A value used to indicate that the token type is a bitwise-xor operator.
-   */
-  static const TokenClass BITWISE_XOR_OPERATOR =
-      const TokenClass('BITWISE_XOR_OPERATOR', 10);
-
-  /**
-   * A value used to indicate that the token type is a cascade operator.
-   */
-  static const TokenClass CASCADE_OPERATOR =
-      const TokenClass('CASCADE_OPERATOR', 2);
-
-  /**
-   * A value used to indicate that the token type is a conditional operator.
-   */
-  static const TokenClass CONDITIONAL_OPERATOR =
-      const TokenClass('CONDITIONAL_OPERATOR', 3);
-
-  /**
-   * A value used to indicate that the token type is an equality operator.
-   */
-  static const TokenClass EQUALITY_OPERATOR =
-      const TokenClass('EQUALITY_OPERATOR', 7);
-
-  /**
-   * A value used to indicate that the token type is an if-null operator.
-   */
-  static const TokenClass IF_NULL_OPERATOR =
-      const TokenClass('IF_NULL_OPERATOR', 4);
-
-  /**
-   * A value used to indicate that the token type is a logical-and operator.
-   */
-  static const TokenClass LOGICAL_AND_OPERATOR =
-      const TokenClass('LOGICAL_AND_OPERATOR', 6);
-
-  /**
-   * A value used to indicate that the token type is a logical-or operator.
-   */
-  static const TokenClass LOGICAL_OR_OPERATOR =
-      const TokenClass('LOGICAL_OR_OPERATOR', 5);
-
-  /**
-   * A value used to indicate that the token type is a multiplicative operator.
-   */
-  static const TokenClass MULTIPLICATIVE_OPERATOR =
-      const TokenClass('MULTIPLICATIVE_OPERATOR', 14);
-
-  /**
-   * A value used to indicate that the token type is a relational operator.
-   */
-  static const TokenClass RELATIONAL_OPERATOR =
-      const TokenClass('RELATIONAL_OPERATOR', 8);
-
-  /**
-   * A value used to indicate that the token type is a shift operator.
-   */
-  static const TokenClass SHIFT_OPERATOR =
-      const TokenClass('SHIFT_OPERATOR', 12);
-
-  /**
-   * A value used to indicate that the token type is a unary operator.
-   */
-  static const TokenClass UNARY_POSTFIX_OPERATOR =
-      const TokenClass('UNARY_POSTFIX_OPERATOR', 16);
-
-  /**
-   * A value used to indicate that the token type is a unary operator.
-   */
-  static const TokenClass UNARY_PREFIX_OPERATOR =
-      const TokenClass('UNARY_PREFIX_OPERATOR', 15);
-
-  /**
-   * The name of the token class.
-   */
-  final String name;
-
-  /**
-   * The precedence of tokens of this class, or `0` if the such tokens do not
-   * represent an operator.
-   */
-  final int precedence;
-
-  const TokenClass(this.name, [this.precedence = 0]);
-
-  @override
-  String toString() => name;
-}
-
-/**
- * The types of tokens that can be returned by the scanner.
- */
-class TokenType {
-  /**
-   * The type of the token that marks the end of the input.
-   */
-  static const TokenType EOF = const TokenType_EOF('EOF');
-
-  static const TokenType DOUBLE = const TokenType('DOUBLE');
-
-  static const TokenType HEXADECIMAL = const TokenType('HEXADECIMAL');
-
-  static const TokenType IDENTIFIER = const TokenType('IDENTIFIER');
-
-  static const TokenType INT = const TokenType('INT');
-
-  static const TokenType KEYWORD = const TokenType('KEYWORD');
-
-  static const TokenType MULTI_LINE_COMMENT =
-      const TokenType('MULTI_LINE_COMMENT');
-
-  static const TokenType SCRIPT_TAG = const TokenType('SCRIPT_TAG');
-
-  static const TokenType SINGLE_LINE_COMMENT =
-      const TokenType('SINGLE_LINE_COMMENT');
-
-  static const TokenType STRING = const TokenType('STRING');
-
-  static const TokenType AMPERSAND =
-      const TokenType('AMPERSAND', TokenClass.BITWISE_AND_OPERATOR, "&");
-
-  static const TokenType AMPERSAND_AMPERSAND = const TokenType(
-      'AMPERSAND_AMPERSAND', TokenClass.LOGICAL_AND_OPERATOR, "&&");
-
-  static const TokenType AMPERSAND_EQ =
-      const TokenType('AMPERSAND_EQ', TokenClass.ASSIGNMENT_OPERATOR, "&=");
-
-  static const TokenType AT = const TokenType('AT', TokenClass.NO_CLASS, "@");
-
-  static const TokenType BANG =
-      const TokenType('BANG', TokenClass.UNARY_PREFIX_OPERATOR, "!");
-
-  static const TokenType BANG_EQ =
-      const TokenType('BANG_EQ', TokenClass.EQUALITY_OPERATOR, "!=");
-
-  static const TokenType BAR =
-      const TokenType('BAR', TokenClass.BITWISE_OR_OPERATOR, "|");
-
-  static const TokenType BAR_BAR =
-      const TokenType('BAR_BAR', TokenClass.LOGICAL_OR_OPERATOR, "||");
-
-  static const TokenType BAR_EQ =
-      const TokenType('BAR_EQ', TokenClass.ASSIGNMENT_OPERATOR, "|=");
-
-  static const TokenType COLON =
-      const TokenType('COLON', TokenClass.NO_CLASS, ":");
-
-  static const TokenType COMMA =
-      const TokenType('COMMA', TokenClass.NO_CLASS, ",");
-
-  static const TokenType CARET =
-      const TokenType('CARET', TokenClass.BITWISE_XOR_OPERATOR, "^");
-
-  static const TokenType CARET_EQ =
-      const TokenType('CARET_EQ', TokenClass.ASSIGNMENT_OPERATOR, "^=");
-
-  static const TokenType CLOSE_CURLY_BRACKET =
-      const TokenType('CLOSE_CURLY_BRACKET', TokenClass.NO_CLASS, "}");
-
-  static const TokenType CLOSE_PAREN =
-      const TokenType('CLOSE_PAREN', TokenClass.NO_CLASS, ")");
-
-  static const TokenType CLOSE_SQUARE_BRACKET =
-      const TokenType('CLOSE_SQUARE_BRACKET', TokenClass.NO_CLASS, "]");
-
-  static const TokenType EQ =
-      const TokenType('EQ', TokenClass.ASSIGNMENT_OPERATOR, "=");
-
-  static const TokenType EQ_EQ =
-      const TokenType('EQ_EQ', TokenClass.EQUALITY_OPERATOR, "==");
-
-  static const TokenType FUNCTION =
-      const TokenType('FUNCTION', TokenClass.NO_CLASS, "=>");
-
-  static const TokenType GT =
-      const TokenType('GT', TokenClass.RELATIONAL_OPERATOR, ">");
-
-  static const TokenType GT_EQ =
-      const TokenType('GT_EQ', TokenClass.RELATIONAL_OPERATOR, ">=");
-
-  static const TokenType GT_GT =
-      const TokenType('GT_GT', TokenClass.SHIFT_OPERATOR, ">>");
-
-  static const TokenType GT_GT_EQ =
-      const TokenType('GT_GT_EQ', TokenClass.ASSIGNMENT_OPERATOR, ">>=");
-
-  static const TokenType HASH =
-      const TokenType('HASH', TokenClass.NO_CLASS, "#");
-
-  static const TokenType INDEX =
-      const TokenType('INDEX', TokenClass.UNARY_POSTFIX_OPERATOR, "[]");
-
-  static const TokenType INDEX_EQ =
-      const TokenType('INDEX_EQ', TokenClass.UNARY_POSTFIX_OPERATOR, "[]=");
-
-  static const TokenType IS =
-      const TokenType('IS', TokenClass.RELATIONAL_OPERATOR, "is");
-
-  static const TokenType LT =
-      const TokenType('LT', TokenClass.RELATIONAL_OPERATOR, "<");
-
-  static const TokenType LT_EQ =
-      const TokenType('LT_EQ', TokenClass.RELATIONAL_OPERATOR, "<=");
-
-  static const TokenType LT_LT =
-      const TokenType('LT_LT', TokenClass.SHIFT_OPERATOR, "<<");
-
-  static const TokenType LT_LT_EQ =
-      const TokenType('LT_LT_EQ', TokenClass.ASSIGNMENT_OPERATOR, "<<=");
-
-  static const TokenType MINUS =
-      const TokenType('MINUS', TokenClass.ADDITIVE_OPERATOR, "-");
-
-  static const TokenType MINUS_EQ =
-      const TokenType('MINUS_EQ', TokenClass.ASSIGNMENT_OPERATOR, "-=");
-
-  static const TokenType MINUS_MINUS =
-      const TokenType('MINUS_MINUS', TokenClass.UNARY_PREFIX_OPERATOR, "--");
-
-  static const TokenType OPEN_CURLY_BRACKET =
-      const TokenType('OPEN_CURLY_BRACKET', TokenClass.NO_CLASS, "{");
-
-  static const TokenType OPEN_PAREN =
-      const TokenType('OPEN_PAREN', TokenClass.UNARY_POSTFIX_OPERATOR, "(");
-
-  static const TokenType OPEN_SQUARE_BRACKET = const TokenType(
-      'OPEN_SQUARE_BRACKET', TokenClass.UNARY_POSTFIX_OPERATOR, "[");
-
-  static const TokenType PERCENT =
-      const TokenType('PERCENT', TokenClass.MULTIPLICATIVE_OPERATOR, "%");
-
-  static const TokenType PERCENT_EQ =
-      const TokenType('PERCENT_EQ', TokenClass.ASSIGNMENT_OPERATOR, "%=");
-
-  static const TokenType PERIOD =
-      const TokenType('PERIOD', TokenClass.UNARY_POSTFIX_OPERATOR, ".");
-
-  static const TokenType PERIOD_PERIOD =
-      const TokenType('PERIOD_PERIOD', TokenClass.CASCADE_OPERATOR, "..");
-
-  static const TokenType PLUS =
-      const TokenType('PLUS', TokenClass.ADDITIVE_OPERATOR, "+");
-
-  static const TokenType PLUS_EQ =
-      const TokenType('PLUS_EQ', TokenClass.ASSIGNMENT_OPERATOR, "+=");
-
-  static const TokenType PLUS_PLUS =
-      const TokenType('PLUS_PLUS', TokenClass.UNARY_PREFIX_OPERATOR, "++");
-
-  static const TokenType QUESTION =
-      const TokenType('QUESTION', TokenClass.CONDITIONAL_OPERATOR, "?");
-
-  static const TokenType QUESTION_PERIOD = const TokenType(
-      'QUESTION_PERIOD', TokenClass.UNARY_POSTFIX_OPERATOR, '?.');
-
-  static const TokenType QUESTION_QUESTION =
-      const TokenType('QUESTION_QUESTION', TokenClass.IF_NULL_OPERATOR, '??');
-
-  static const TokenType QUESTION_QUESTION_EQ = const TokenType(
-      'QUESTION_QUESTION_EQ', TokenClass.ASSIGNMENT_OPERATOR, '??=');
-
-  static const TokenType SEMICOLON =
-      const TokenType('SEMICOLON', TokenClass.NO_CLASS, ";");
-
-  static const TokenType SLASH =
-      const TokenType('SLASH', TokenClass.MULTIPLICATIVE_OPERATOR, "/");
-
-  static const TokenType SLASH_EQ =
-      const TokenType('SLASH_EQ', TokenClass.ASSIGNMENT_OPERATOR, "/=");
-
-  static const TokenType STAR =
-      const TokenType('STAR', TokenClass.MULTIPLICATIVE_OPERATOR, "*");
-
-  static const TokenType STAR_EQ =
-      const TokenType('STAR_EQ', TokenClass.ASSIGNMENT_OPERATOR, "*=");
-
-  static const TokenType STRING_INTERPOLATION_EXPRESSION = const TokenType(
-      'STRING_INTERPOLATION_EXPRESSION', TokenClass.NO_CLASS, "\${");
-
-  static const TokenType STRING_INTERPOLATION_IDENTIFIER = const TokenType(
-      'STRING_INTERPOLATION_IDENTIFIER', TokenClass.NO_CLASS, "\$");
-
-  static const TokenType TILDE =
-      const TokenType('TILDE', TokenClass.UNARY_PREFIX_OPERATOR, "~");
-
-  static const TokenType TILDE_SLASH =
-      const TokenType('TILDE_SLASH', TokenClass.MULTIPLICATIVE_OPERATOR, "~/");
-
-  static const TokenType TILDE_SLASH_EQ =
-      const TokenType('TILDE_SLASH_EQ', TokenClass.ASSIGNMENT_OPERATOR, "~/=");
-
-  static const TokenType BACKPING =
-      const TokenType('BACKPING', TokenClass.NO_CLASS, "`");
-
-  static const TokenType BACKSLASH =
-      const TokenType('BACKSLASH', TokenClass.NO_CLASS, "\\");
-
-  static const TokenType PERIOD_PERIOD_PERIOD =
-      const TokenType('PERIOD_PERIOD_PERIOD', TokenClass.NO_CLASS, "...");
-
-  static const TokenType GENERIC_METHOD_TYPE_LIST =
-      const TokenType('GENERIC_METHOD_TYPE_LIST');
-
-  static const TokenType GENERIC_METHOD_TYPE_ASSIGN =
-      const TokenType('GENERIC_METHOD_TYPE_ASSIGN');
-
-  /**
-   * The class of the token.
-   */
-  final TokenClass _tokenClass;
-
-  /**
-   * The name of the token type.
-   */
-  final String name;
-
-  /**
-   * The lexeme that defines this type of token, or `null` if there is more than
-   * one possible lexeme for this type of token.
-   */
-  final String lexeme;
-
-  const TokenType(this.name,
-      [this._tokenClass = TokenClass.NO_CLASS, this.lexeme = null]);
-
-  /**
-   * Return `true` if this type of token represents an additive operator.
-   */
-  bool get isAdditiveOperator => _tokenClass == TokenClass.ADDITIVE_OPERATOR;
-
-  /**
-   * Return `true` if this type of token represents an assignment operator.
-   */
-  bool get isAssignmentOperator =>
-      _tokenClass == TokenClass.ASSIGNMENT_OPERATOR;
-
-  /**
-   * Return `true` if this type of token represents an associative operator. An
-   * associative operator is an operator for which the following equality is
-   * true: `(a * b) * c == a * (b * c)`. In other words, if the result of
-   * applying the operator to multiple operands does not depend on the order in
-   * which those applications occur.
-   *
-   * Note: This method considers the logical-and and logical-or operators to be
-   * associative, even though the order in which the application of those
-   * operators can have an effect because evaluation of the right-hand operand
-   * is conditional.
-   */
-  bool get isAssociativeOperator =>
-      this == AMPERSAND ||
-      this == AMPERSAND_AMPERSAND ||
-      this == BAR ||
-      this == BAR_BAR ||
-      this == CARET ||
-      this == PLUS ||
-      this == STAR;
-
-  /**
-   * Return `true` if this type of token represents an equality operator.
-   */
-  bool get isEqualityOperator => _tokenClass == TokenClass.EQUALITY_OPERATOR;
-
-  /**
-   * Return `true` if this type of token represents an increment operator.
-   */
-  bool get isIncrementOperator =>
-      identical(lexeme, "++") || identical(lexeme, "--");
-
-  /**
-   * Return `true` if this type of token represents a multiplicative operator.
-   */
-  bool get isMultiplicativeOperator =>
-      _tokenClass == TokenClass.MULTIPLICATIVE_OPERATOR;
-
-  /**
-   * Return `true` if this token type represents an operator.
-   */
-  bool get isOperator =>
-      _tokenClass != TokenClass.NO_CLASS &&
-      this != OPEN_PAREN &&
-      this != OPEN_SQUARE_BRACKET &&
-      this != PERIOD;
-
-  /**
-   * Return `true` if this type of token represents a relational operator.
-   */
-  bool get isRelationalOperator =>
-      _tokenClass == TokenClass.RELATIONAL_OPERATOR;
-
-  /**
-   * Return `true` if this type of token represents a shift operator.
-   */
-  bool get isShiftOperator => _tokenClass == TokenClass.SHIFT_OPERATOR;
-
-  /**
-   * Return `true` if this type of token represents a unary postfix operator.
-   */
-  bool get isUnaryPostfixOperator =>
-      _tokenClass == TokenClass.UNARY_POSTFIX_OPERATOR;
-
-  /**
-   * Return `true` if this type of token represents a unary prefix operator.
-   */
-  bool get isUnaryPrefixOperator =>
-      _tokenClass == TokenClass.UNARY_PREFIX_OPERATOR;
-
-  /**
-   * Return `true` if this token type represents an operator that can be defined
-   * by users.
-   */
-  bool get isUserDefinableOperator =>
-      identical(lexeme, "==") ||
-      identical(lexeme, "~") ||
-      identical(lexeme, "[]") ||
-      identical(lexeme, "[]=") ||
-      identical(lexeme, "*") ||
-      identical(lexeme, "/") ||
-      identical(lexeme, "%") ||
-      identical(lexeme, "~/") ||
-      identical(lexeme, "+") ||
-      identical(lexeme, "-") ||
-      identical(lexeme, "<<") ||
-      identical(lexeme, ">>") ||
-      identical(lexeme, ">=") ||
-      identical(lexeme, ">") ||
-      identical(lexeme, "<=") ||
-      identical(lexeme, "<") ||
-      identical(lexeme, "&") ||
-      identical(lexeme, "^") ||
-      identical(lexeme, "|");
-
-  /**
-   * Return the precedence of the token, or `0` if the token does not represent
-   * an operator.
-   */
-  int get precedence => _tokenClass.precedence;
-
-  @override
-  String toString() => name;
-}
-
-class TokenType_EOF extends TokenType {
-  const TokenType_EOF(String name) : super(name, TokenClass.NO_CLASS, "");
-
-  @override
-  String toString() => "-eof-";
-}
-
-/**
- * A normal token that is preceded by comments.
- */
-class TokenWithComment extends Token {
-  /**
-   * The first comment in the list of comments that precede this token.
-   */
-  CommentToken _precedingComment;
-
-  /**
-   * Initialize a newly created token to have the given [type] at the given
-   * [offset] and to be preceded by the comments reachable from the given
-   * [comment].
-   */
-  TokenWithComment(TokenType type, int offset, this._precedingComment)
-      : super(type, offset) {
-    _setCommentParent(_precedingComment);
-  }
-
-  CommentToken get precedingComments => _precedingComment;
-
-  void set precedingComments(CommentToken comment) {
-    _precedingComment = comment;
-    _setCommentParent(_precedingComment);
-  }
-
-  @override
-  Token copy() => new TokenWithComment(type, offset, precedingComments);
-}
+export 'package:analyzer/dart/ast/token.dart';
+export 'package:analyzer/src/dart/ast/token.dart' hide SimpleToken;
+export 'package:analyzer/src/dart/scanner/scanner.dart';
+export 'package:analyzer/src/dart/scanner/reader.dart';
diff --git a/pkg/analyzer/lib/src/generated/sdk.dart b/pkg/analyzer/lib/src/generated/sdk.dart
index a2b6325..51c6ccc 100644
--- a/pkg/analyzer/lib/src/generated/sdk.dart
+++ b/pkg/analyzer/lib/src/generated/sdk.dart
@@ -8,34 +8,40 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
+import 'package:analyzer/src/generated/engine.dart'
+    show AnalysisContext, AnalysisOptions;
 import 'package:analyzer/src/generated/source.dart'
     show ContentCache, Source, UriKind;
 
 /**
+ * A function used to create a new DartSdk
+ */
+typedef DartSdk SdkCreator();
+
+/**
  * A Dart SDK installed in a specified location.
  */
 abstract class DartSdk {
   /**
    * The short name of the dart SDK 'async' library.
    */
-  static final String DART_ASYNC = "dart:async";
+  static const String DART_ASYNC = "dart:async";
 
   /**
    * The short name of the dart SDK 'core' library.
    */
-  static final String DART_CORE = "dart:core";
+  static const String DART_CORE = "dart:core";
 
   /**
    * The short name of the dart SDK 'html' library.
    */
-  static final String DART_HTML = "dart:html";
+  static const String DART_HTML = "dart:html";
 
   /**
    * The version number that is returned when the real version number could not
    * be determined.
    */
-  static final String DEFAULT_VERSION = "0";
+  static const String DEFAULT_VERSION = "0";
 
   /**
    * Return the analysis context used for all of the sources in this [DartSdk].
@@ -79,6 +85,56 @@
 }
 
 /**
+ * Manages the DartSdk's that have been created. Clients need to create multiple
+ * SDKs when the analysis options associated with those SDK's contexts will
+ * produce different analysis results.
+ */
+class DartSdkManager {
+  /**
+   * The function used to create new SDK's.
+   */
+  final SdkCreator sdkCreator;
+
+  /**
+   * A table mapping (an encoding of) analysis options to the SDK that has been
+   * configured with those options.
+   */
+  Map<int, DartSdk> sdkMap = new HashMap<int, DartSdk>();
+
+  /**
+   * Initialize a newly created manager.
+   */
+  DartSdkManager(this.sdkCreator);
+
+  /**
+   * Return any SDK that has been created, or `null` if no SDKs have been
+   * created.
+   */
+  DartSdk get anySdk {
+    if (sdkMap.isEmpty) {
+      return null;
+    }
+    return sdkMap.values.first;
+  }
+
+  /**
+   * Return the Dart SDK that is appropriate for the given analysis [options].
+   * If such an SDK has not yet been created, then the [sdkCreator] will be
+   * invoked to create it.
+   */
+  DartSdk getSdkForOptions(AnalysisOptions options) {
+    int encoding = options.encodeCrossContextOptions();
+    DartSdk sdk = sdkMap[encoding];
+    if (sdk == null) {
+      sdk = sdkCreator();
+      sdkMap[encoding] = sdk;
+      sdk.context.analysisOptions.setCrossContextOptionsFrom(options);
+    }
+    return sdk;
+  }
+}
+
+/**
  * A map from Dart library URI's to the [SdkLibraryImpl] representing that
  * library.
  */
@@ -224,7 +280,7 @@
             library.category =
                 convertCategories((expression as StringLiteral).stringValue);
           } else if (name == _IMPLEMENTATION) {
-            library.implementation = (expression as BooleanLiteral).value;
+            library._implementation = (expression as BooleanLiteral).value;
           } else if (name == _DOCUMENTED) {
             library.documented = (expression as BooleanLiteral).value;
           } else if (name == _PLATFORMS) {
@@ -364,13 +420,6 @@
     this._documented = documented;
   }
 
-  /**
-   * Set whether the library is an implementation library.
-   */
-  void set implementation(bool implementation) {
-    this._implementation = implementation;
-  }
-
   @override
   bool get isDart2JsLibrary => (_platforms & DART2JS_PLATFORM) != 0;
 
@@ -381,7 +430,7 @@
   bool get isImplementation => _implementation;
 
   @override
-  bool get isInternal => "Internal" == category;
+  bool get isInternal => category == "Internal";
 
   @override
   bool get isShared => category == "Shared";
diff --git a/pkg/analyzer/lib/src/generated/sdk_io.dart b/pkg/analyzer/lib/src/generated/sdk_io.dart
index 8cdb8f2..6a1e38d 100644
--- a/pkg/analyzer/lib/src/generated/sdk_io.dart
+++ b/pkg/analyzer/lib/src/generated/sdk_io.dart
@@ -9,6 +9,8 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_core.dart';
@@ -16,7 +18,6 @@
 import 'package:analyzer/src/generated/java_engine_io.dart';
 import 'package:analyzer/src/generated/java_io.dart';
 import 'package:analyzer/src/generated/parser.dart';
-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/idl.dart' show SdkBundle;
@@ -207,6 +208,11 @@
   JavaFile _libraryDirectory;
 
   /**
+   * The flag that specifies whether SDK summary should be used.
+   */
+  bool _useSummary = false;
+
+  /**
    * The revision number of this SDK, or `"0"` if the revision number cannot be
    * discovered.
    */
@@ -259,10 +265,12 @@
       SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
       _analysisContext.sourceFactory = factory;
       // Try to use summaries.
-      SdkBundle sdkBundle = _getSummarySdkBundle();
-      if (sdkBundle != null) {
-        _analysisContext.resultProvider =
-            new SdkSummaryResultProvider(_analysisContext, sdkBundle);
+      if (_useSummary) {
+        SdkBundle sdkBundle = _getSummarySdkBundle();
+        if (sdkBundle != null) {
+          _analysisContext.resultProvider =
+              new SdkSummaryResultProvider(_analysisContext, sdkBundle);
+        }
       }
     }
     return _analysisContext;
@@ -390,6 +398,17 @@
   List<String> get uris => _libraryMap.uris;
 
   /**
+   * Specify whether SDK summary should be used.  This property can only be set
+   * before [context] is invoked.
+   */
+  void set useSummary(bool use) {
+    if (_analysisContext != null) {
+      throw new StateError('SDK analysis context has been already created.');
+    }
+    _useSummary = use;
+  }
+
+  /**
    * Return the name of the file containing the VM executable.
    */
   String get vmBinaryName {
@@ -538,7 +557,7 @@
    */
   SdkBundle _getSummarySdkBundle() {
     String rootPath = directory.getAbsolutePath();
-    String path = pathos.join(rootPath, 'lib', '_internal', 'analysis_summary');
+    String path = pathos.join(rootPath, 'lib', '_internal', 'spec.sum');
     try {
       File file = new File(path);
       if (file.existsSync()) {
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index fa2bf1c..4a2362f 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -7,6 +7,7 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -14,8 +15,6 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
-import 'package:analyzer/src/generated/scanner.dart' as sc;
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
 /**
@@ -238,8 +237,8 @@
    */
   @override
   Object visitAssignmentExpression(AssignmentExpression node) {
-    sc.TokenType operator = node.operator.type;
-    if (operator == sc.TokenType.EQ) {
+    TokenType operator = node.operator.type;
+    if (operator == TokenType.EQ) {
       Expression rightHandSide = node.rightHandSide;
       DartType staticType = _getStaticType(rightHandSide);
       _recordStaticType(node, staticType);
@@ -250,7 +249,7 @@
         overrideType = propagatedType;
       }
       _resolver.overrideExpression(node.leftHandSide, overrideType, true, true);
-    } else if (operator == sc.TokenType.QUESTION_QUESTION_EQ) {
+    } else if (operator == TokenType.QUESTION_QUESTION_EQ) {
       // The static type of a compound assignment using ??= is the least upper
       // bound of the static types of the LHS and RHS.
       _analyzeLeastUpperBound(node, node.leftHandSide, node.rightHandSide);
@@ -477,11 +476,16 @@
 
       DartType functionType = InferenceContext.getType(node);
       if (functionType is FunctionType) {
-        DartType returnType = functionType.returnType;
-        if (computedType.isDynamic &&
-            !(returnType.isDynamic || returnType.isBottom)) {
-          computedType = returnType;
-          _resolver.inferenceContext.recordInference(node, functionType);
+        functionType = _resolver.matchFunctionTypeParameters(
+            node.typeParameters, functionType);
+
+        if (functionType is FunctionType) {
+          DartType returnType = functionType.returnType;
+          if (computedType.isDynamic &&
+              !(returnType.isDynamic || returnType.isBottom)) {
+            computedType = returnType;
+            _resolver.inferenceContext.recordInference(node, functionType);
+          }
         }
       }
     }
@@ -968,9 +972,8 @@
   Object visitPostfixExpression(PostfixExpression node) {
     Expression operand = node.operand;
     DartType staticType = _getStaticType(operand);
-    sc.TokenType operator = node.operator.type;
-    if (operator == sc.TokenType.MINUS_MINUS ||
-        operator == sc.TokenType.PLUS_PLUS) {
+    TokenType operator = node.operator.type;
+    if (operator == TokenType.MINUS_MINUS || operator == TokenType.PLUS_PLUS) {
       DartType intType = _typeProvider.intType;
       if (identical(_getStaticType(node.operand), intType)) {
         staticType = intType;
@@ -1070,15 +1073,15 @@
    */
   @override
   Object visitPrefixExpression(PrefixExpression node) {
-    sc.TokenType operator = node.operator.type;
-    if (operator == sc.TokenType.BANG) {
+    TokenType operator = node.operator.type;
+    if (operator == TokenType.BANG) {
       _recordStaticType(node, _typeProvider.boolType);
     } else {
       // The other cases are equivalent to invoking a method.
       ExecutableElement staticMethodElement = node.staticElement;
       DartType staticType = _computeStaticReturnType(staticMethodElement);
-      if (operator == sc.TokenType.MINUS_MINUS ||
-          operator == sc.TokenType.PLUS_PLUS) {
+      if (operator == TokenType.MINUS_MINUS ||
+          operator == TokenType.PLUS_PLUS) {
         DartType intType = _typeProvider.intType;
         if (identical(_getStaticType(node.operand), intType)) {
           staticType = intType;
@@ -1535,14 +1538,11 @@
   // TODO(vsm): Use leafp's matchType here?
   DartType _findIteratedType(DartType type, DartType targetType) {
     // Set by _find if match is found
-    DartType result = null;
+    DartType result;
     // Elements we've already visited on a given inheritance path.
-    HashSet<ClassElement> visitedClasses = null;
+    HashSet<ClassElement> visitedClasses;
 
-    while (type is TypeParameterType) {
-      TypeParameterElement element = type.element;
-      type = element.bound;
-    }
+    type = type.resolveToBound(_typeProvider.objectType);
 
     bool _find(InterfaceType type) {
       ClassElement element = type.element;
@@ -1817,6 +1817,21 @@
     return false;
   }
 
+  /**
+   * Given an uninstantiated generic type, try to infer the instantiated generic
+   * type from the surrounding context.
+   */
+  DartType _inferGenericInstantiationFromContext(
+      DartType context, DartType type) {
+    TypeSystem ts = _typeSystem;
+    if (context is FunctionType &&
+        type is FunctionType &&
+        ts is StrongTypeSystemImpl) {
+      return ts.inferFunctionTypeInstantiation(_typeProvider, context, type);
+    }
+    return type;
+  }
+
   FunctionType _inferGenericInvoke(FunctionType invokeType, FunctionType fnType,
       TypeArgumentList typeArguments, ArgumentList argumentList) {
     TypeSystem ts = _typeSystem;
@@ -1895,21 +1910,6 @@
   }
 
   /**
-   * Given an uninstantiated generic type, try to infer the instantiated generic
-   * type from the surrounding context.
-   */
-  DartType _inferGenericInstantiationFromContext(
-      DartType context, DartType type) {
-    TypeSystem ts = _typeSystem;
-    if (context is FunctionType &&
-        type is FunctionType &&
-        ts is StrongTypeSystemImpl) {
-      return ts.inferFunctionTypeInstantiation(_typeProvider, context, type);
-    }
-    return type;
-  }
-
-  /**
    * Given a method invocation [node], attempt to infer a better
    * type for the result if it is an inline JS invocation
    */
@@ -2119,32 +2119,32 @@
   DartType _refineBinaryExpressionType(
       BinaryExpression expression, DartType currentType,
       [DartType typeAccessor(Expression node)]) {
-    sc.TokenType operator = expression.operator.type;
+    TokenType operator = expression.operator.type;
     // bool
-    if (operator == sc.TokenType.AMPERSAND_AMPERSAND ||
-        operator == sc.TokenType.BAR_BAR ||
-        operator == sc.TokenType.EQ_EQ ||
-        operator == sc.TokenType.BANG_EQ) {
+    if (operator == TokenType.AMPERSAND_AMPERSAND ||
+        operator == TokenType.BAR_BAR ||
+        operator == TokenType.EQ_EQ ||
+        operator == TokenType.BANG_EQ) {
       return _typeProvider.boolType;
     }
     DartType intType = _typeProvider.intType;
     if (typeAccessor(expression.leftOperand) == intType) {
       // int op double
-      if (operator == sc.TokenType.MINUS ||
-          operator == sc.TokenType.PERCENT ||
-          operator == sc.TokenType.PLUS ||
-          operator == sc.TokenType.STAR) {
+      if (operator == TokenType.MINUS ||
+          operator == TokenType.PERCENT ||
+          operator == TokenType.PLUS ||
+          operator == TokenType.STAR) {
         DartType doubleType = _typeProvider.doubleType;
         if (typeAccessor(expression.rightOperand) == doubleType) {
           return doubleType;
         }
       }
       // int op int
-      if (operator == sc.TokenType.MINUS ||
-          operator == sc.TokenType.PERCENT ||
-          operator == sc.TokenType.PLUS ||
-          operator == sc.TokenType.STAR ||
-          operator == sc.TokenType.TILDE_SLASH) {
+      if (operator == TokenType.MINUS ||
+          operator == TokenType.PERCENT ||
+          operator == TokenType.PLUS ||
+          operator == TokenType.STAR ||
+          operator == TokenType.TILDE_SLASH) {
         if (typeAccessor(expression.rightOperand) == intType) {
           return intType;
         }
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
index 7e697eb..d8d44f4 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
@@ -5,9 +5,9 @@
 library analyzer.src.generated.testing.ast_factory;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index 72d8acf..b94cb64 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -7,6 +7,7 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
@@ -15,7 +16,6 @@
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/testing/ast_factory.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -202,7 +202,8 @@
   }
 
   static FieldElementImpl fieldElement(
-      String name, bool isStatic, bool isFinal, bool isConst, DartType type) {
+      String name, bool isStatic, bool isFinal, bool isConst, DartType type,
+      {Expression initializer}) {
     FieldElementImpl field = isConst
         ? new ConstFieldElementImpl(name, 0)
         : new FieldElementImpl(name, 0);
@@ -210,6 +211,9 @@
     field.final2 = isFinal;
     field.static = isStatic;
     field.type = type;
+    if (isConst) {
+      (field as ConstFieldElementImpl).constantInitializer = initializer;
+    }
     PropertyAccessorElementImpl getter =
         new PropertyAccessorElementImpl.forVariable(field);
     getter.getter = true;
@@ -496,6 +500,16 @@
     return parameter;
   }
 
+  static ParameterElementImpl namedParameter3(String name,
+      {DartType type, Expression initializer}) {
+    DefaultParameterElementImpl parameter =
+        new DefaultParameterElementImpl(name, 0);
+    parameter.parameterKind = ParameterKind.NAMED;
+    parameter.type = type;
+    parameter.constantInitializer = initializer;
+    return parameter;
+  }
+
   static ParameterElementImpl positionalParameter(String name) {
     ParameterElementImpl parameter = new ParameterElementImpl(name, 0);
     parameter.parameterKind = ParameterKind.POSITIONAL;
diff --git a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
index b3aaea8..48c4f98 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -5,6 +5,7 @@
 library analyzer.src.generated.testing.test_type_provider;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
@@ -12,7 +13,6 @@
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
 import 'package:analyzer/src/generated/source.dart' show Source;
 import 'package:analyzer/src/generated/testing/ast_factory.dart';
@@ -170,7 +170,8 @@
           .constructorElement(boolElement, "fromEnvironment", true);
       fromEnvironment.parameters = <ParameterElement>[
         ElementFactory.requiredParameter2("name", stringType),
-        ElementFactory.namedParameter2("defaultValue", _boolType)
+        ElementFactory.namedParameter3("defaultValue",
+            type: _boolType, initializer: AstFactory.booleanLiteral(false))
       ];
       fromEnvironment.factory = true;
       fromEnvironment.isCycleFree = true;
@@ -195,7 +196,9 @@
       FieldElementImpl expiresField = ElementFactory.fieldElement(
           'expires', false, true, false, stringType);
       deprecatedElement.fields = <FieldElement>[expiresField];
-      deprecatedElement.accessors = <PropertyAccessorElement>[expiresField.getter];
+      deprecatedElement.accessors = <PropertyAccessorElement>[
+        expiresField.getter
+      ];
       ConstructorElementImpl constructor = ElementFactory
           .constructorElement(deprecatedElement, '', true, [stringType]);
       (constructor.parameters[0] as ParameterElementImpl).name = 'expires';
@@ -492,7 +495,7 @@
           .constructorElement(stringElement, "fromEnvironment", true);
       fromEnvironment.parameters = <ParameterElement>[
         ElementFactory.requiredParameter2("name", stringType),
-        ElementFactory.namedParameter2("defaultValue", _stringType)
+        ElementFactory.namedParameter3("defaultValue", type: _stringType)
       ];
       fromEnvironment.factory = true;
       fromEnvironment.isCycleFree = true;
@@ -610,7 +613,7 @@
         ElementFactory.constructorElement(intElement, "fromEnvironment", true);
     fromEnvironment.parameters = <ParameterElement>[
       ElementFactory.requiredParameter2("name", stringType),
-      ElementFactory.namedParameter2("defaultValue", _intType)
+      ElementFactory.namedParameter3("defaultValue", type: _intType)
     ];
     fromEnvironment.factory = true;
     fromEnvironment.isCycleFree = true;
@@ -623,18 +626,23 @@
       ElementFactory.constructorElement(doubleElement, null, false)
         ..synthetic = true
     ];
-    ConstFieldElementImpl varINFINITY =
-        ElementFactory.fieldElement("INFINITY", true, false, true, _doubleType);
+    ConstFieldElementImpl varINFINITY = ElementFactory.fieldElement(
+        "INFINITY", true, false, true, _doubleType,
+        initializer: AstFactory.doubleLiteral(double.INFINITY));
     varINFINITY.constantInitializer = AstFactory.binaryExpression(
         AstFactory.integer(1), TokenType.SLASH, AstFactory.integer(0));
     List<FieldElement> fields = <FieldElement>[
-      ElementFactory.fieldElement("NAN", true, false, true, _doubleType),
+      ElementFactory.fieldElement("NAN", true, false, true, _doubleType,
+          initializer: AstFactory.doubleLiteral(double.NAN)),
       varINFINITY,
       ElementFactory.fieldElement(
-          "NEGATIVE_INFINITY", true, false, true, _doubleType),
+          "NEGATIVE_INFINITY", true, false, true, _doubleType,
+          initializer: AstFactory.doubleLiteral(double.NEGATIVE_INFINITY)),
       ElementFactory.fieldElement(
-          "MIN_POSITIVE", true, false, true, _doubleType),
-      ElementFactory.fieldElement("MAX_FINITE", true, false, true, _doubleType)
+          "MIN_POSITIVE", true, false, true, _doubleType,
+          initializer: AstFactory.doubleLiteral(double.MIN_POSITIVE)),
+      ElementFactory.fieldElement("MAX_FINITE", true, false, true, _doubleType,
+          initializer: AstFactory.doubleLiteral(double.MAX_FINITE))
     ];
     doubleElement.fields = fields;
     int fieldCount = fields.length;
diff --git a/pkg/analyzer/lib/src/generated/testing/token_factory.dart b/pkg/analyzer/lib/src/generated/testing/token_factory.dart
index a293842..918b9a1 100644
--- a/pkg/analyzer/lib/src/generated/testing/token_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/token_factory.dart
@@ -4,7 +4,8 @@
 
 library analyzer.src.generated.testing.token_factory;
 
-import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 
 /**
  * A set of utility methods that can be used to create tokens.
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 16e0817..851a990 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -53,20 +53,20 @@
   }
 
   /// Given a function type with generic type parameters, infer the type
-  /// parameters from the actual argument types, and return it. If we can't.
-  /// returns the original function type.
+  /// parameters from the actual argument types, and return the instantiated
+  /// function type. If we can't, returns the original function type.
   ///
   /// Concretely, given a function type with parameter types P0, P1, ... Pn,
   /// result type R, and generic type parameters T0, T1, ... Tm, use the
   /// argument types A0, A1, ... An to solve for the type parameters.
   ///
   /// For each parameter Pi, we want to ensure that Ai <: Pi. We can do this by
-  /// running the subtype algorithm, and when we reach a type parameter Pj,
+  /// running the subtype algorithm, and when we reach a type parameter Tj,
   /// recording the lower or upper bound it must satisfy. At the end, all
   /// constraints can be combined to determine the type.
   ///
   /// As a simplification, we do not actually store all constraints on each type
-  /// parameter Pj. Instead we track Uj and Lj where U is the upper bound and
+  /// parameter Tj. Instead we track Uj and Lj where U is the upper bound and
   /// L is the lower bound of that type parameter.
   FunctionType inferCallFromArguments(
       TypeProvider typeProvider,
@@ -91,7 +91,14 @@
           argumentTypes[i], correspondingParameterTypes[i]);
     }
 
-    return inferringTypeSystem._infer(fnType);
+    // We are okay inferring some type variables and not others.
+    //
+    // This lets our return type be as precise as possible, which will help
+    // make any type information resulting from it more precise.
+    //
+    // This is simply a heuristic: the code is incorrect, and we'll issue an
+    // error on this call, to indicate that types don't match.
+    return inferringTypeSystem._infer(fnType, allowPartialSolution: true);
   }
 
   /**
@@ -118,61 +125,25 @@
     var inferringTypeSystem =
         new _StrongInferenceTypeSystem(typeProvider, fnType.typeFormals);
 
-    // Add constraints for each corresponding pair of parameters.
-    var fRequired = fnType.normalParameterTypes;
-    var cRequired = contextType.normalParameterTypes;
-    if (cRequired.length != fRequired.length) {
-      // If the number of required parameters differs, we can't infer from this
-      // type (this will be a static type error).
+    // Since we're trying to infer the instantiation, we want to ignore type
+    // formals as we check the parameters and return type.
+    var inferFnType =
+        fnType.instantiate(TypeParameterTypeImpl.getTypes(fnType.typeFormals));
+    if (!inferringTypeSystem.isSubtypeOf(inferFnType, contextType)) {
       return fnType;
     }
-    for (int i = 0; i < fRequired.length; i++) {
-      inferringTypeSystem.isSubtypeOf(cRequired[i], fRequired[i]);
-    }
 
-    var fOptional = fnType.optionalParameterTypes;
-    var cOptional = contextType.optionalParameterTypes;
-    if (cOptional.length > fOptional.length) {
-      // If we have more optional parameters that can be passed, we can't infer
-      // from this type (this will be a static type error).
-      return fnType;
-    }
-    // Ignore any extra optional arguments in F. We only need to pass arguments
-    // that could be passed to C.
-    for (int i = 0; i < cOptional.length; i++) {
-      inferringTypeSystem.isSubtypeOf(cOptional[i], fOptional[i]);
-    }
+    // Try to infer and instantiate the resulting type.
+    var resultType =
+        inferringTypeSystem._infer(fnType, allowPartialSolution: false);
 
-    var fNamed = fnType.namedParameterTypes;
-    var cNamed = contextType.namedParameterTypes;
-    for (var name in cNamed.keys) {
-      DartType fNamedType = fNamed[name];
-      if (fNamedType == null) {
-        // If F does not have a named parameter needed for C, then we can't
-        // infer from this type (this will be a static type error).
-        return fnType;
-      }
-      DartType cNamedType = cNamed[name];
-      inferringTypeSystem.isSubtypeOf(cNamedType, fNamedType);
-    }
-
-    // Infer from the return type. F must return a subtype of what C returns.
-    inferringTypeSystem.isSubtypeOf(fnType.returnType, contextType.returnType);
-
-    // Instantiate the resulting type.
-    var resultType = inferringTypeSystem._infer(fnType);
-
-    // If the instantiation is not a subtype of our context (because some
-    // constraints could not be solved), return the original type, so the error
-    // is in terms of it.
+    // If the instantiation failed (because some type variable constraints
+    // could not be solved, in other words, we could not find a valid subtype),
+    // then return the original type, so the error is in terms of it.
     //
-    // TODO(jmesserly): for performance, we could refactor this so the _infer
-    // call above bails out sooner, and then we can avoid this extra check.
-    if (isSubtypeOf(resultType, contextType)) {
-      return resultType;
-    } else {
-      return fnType;
-    }
+    // It would be safe to return a partial solution here, but the user
+    // experience may be better if we simply do not infer in this case.
+    return resultType ?? fnType;
   }
 
   /**
@@ -319,69 +290,14 @@
    */
   bool _isFunctionSubtypeOf(FunctionType f1, FunctionType f2,
       {bool fuzzyArrows: true}) {
-    if (!f1.typeFormals.isEmpty) {
-      if (f2.typeFormals.isEmpty) {
-        f1 = instantiateToBounds(f1);
-        return _isFunctionSubtypeOf(f1, f2);
-      } else {
-        return _isGenericFunctionSubtypeOf(f1, f2, fuzzyArrows: fuzzyArrows);
-      }
-    }
 
-    return FunctionTypeImpl.structuralCompare(
+    return FunctionTypeImpl.relate(
         f1,
         f2,
         (DartType t1, DartType t2) =>
             _isSubtypeOf(t2, t1, null, dynamicIsBottom: fuzzyArrows),
-        isSubtypeOf);
-  }
-
-  /**
-   * Check that [f1] is a subtype of [f2] where f1 and f2 are known
-   * to be generic function types (both have type parameters)
-   * [fuzzyArrows] indicates whether or not the f1 and f2 should be
-   * treated as fuzzy arrow types (and hence dynamic parameters to f2 treated
-   * as bottom).
-   */
-  bool _isGenericFunctionSubtypeOf(FunctionType f1, FunctionType f2,
-      {bool fuzzyArrows: true}) {
-    List<TypeParameterElement> params1 = f1.typeFormals;
-    List<TypeParameterElement> params2 = f2.typeFormals;
-    int count = params1.length;
-    if (params2.length != count) {
-      return false;
-    }
-    // We build up a substitution matching up the type parameters
-    // from the two types, {variablesFresh/variables1} and
-    // {variablesFresh/variables2}
-    List<DartType> variables1 = new List<DartType>();
-    List<DartType> variables2 = new List<DartType>();
-    List<DartType> variablesFresh = new List<DartType>();
-    for (int i = 0; i < count; i++) {
-      TypeParameterElement p1 = params1[i];
-      TypeParameterElement p2 = params2[i];
-      TypeParameterElementImpl pFresh =
-          new TypeParameterElementImpl(p2.name, -1);
-
-      DartType variable1 = p1.type;
-      DartType variable2 = p2.type;
-      DartType variableFresh = new TypeParameterTypeImpl(pFresh);
-
-      variables1.add(variable1);
-      variables2.add(variable2);
-      variablesFresh.add(variableFresh);
-      DartType bound1 = p1.bound ?? DynamicTypeImpl.instance;
-      DartType bound2 = p2.bound ?? DynamicTypeImpl.instance;
-      bound1 = bound1.substitute2(variablesFresh, variables1);
-      bound2 = bound2.substitute2(variablesFresh, variables2);
-      pFresh.bound = bound2;
-      if (!isSubtypeOf(bound2, bound1)) {
-        return false;
-      }
-    }
-    return _isFunctionSubtypeOf(
-        f1.instantiate(variablesFresh), f2.instantiate(variablesFresh),
-        fuzzyArrows: fuzzyArrows);
+        instantiateToBounds,
+        returnRelation: isSubtypeOf);
   }
 
   bool _isInterfaceSubtypeOf(
@@ -622,26 +538,12 @@
     if (type2.isBottom) {
       return type1;
     }
+
     // Let U be a type variable with upper bound B.  The least upper bound of U
     // and a type T is the least upper bound of B and T.
-    while (type1 is TypeParameterType) {
-      // TODO(paulberry): is this correct in the complex of F-bounded
-      // polymorphism?
-      DartType bound = (type1 as TypeParameterType).element.bound;
-      if (bound == null) {
-        bound = typeProvider.objectType;
-      }
-      type1 = bound;
-    }
-    while (type2 is TypeParameterType) {
-      // TODO(paulberry): is this correct in the context of F-bounded
-      // polymorphism?
-      DartType bound = (type2 as TypeParameterType).element.bound;
-      if (bound == null) {
-        bound = typeProvider.objectType;
-      }
-      type2 = bound;
-    }
+    type1 = type1.resolveToBound(typeProvider.objectType);
+    type2 = type2.resolveToBound(typeProvider.objectType);
+
     // The least upper bound of a function type and an interface type T is the
     // least upper bound of Function and T.
     if (type1 is FunctionType && type2 is InterfaceType) {
@@ -790,7 +692,7 @@
 
   /// Given the constraints that were given by calling [isSubtypeOf], find the
   /// instantiation of the generic function that satisfies these constraints.
-  FunctionType _infer(FunctionType fnType) {
+  FunctionType _infer(FunctionType fnType, {bool allowPartialSolution: false}) {
     List<TypeParameterType> fnTypeParams =
         TypeParameterTypeImpl.getTypes(fnType.typeFormals);
 
@@ -832,13 +734,22 @@
       inferredTypes[i] =
           inferredTypes[i].substitute2(inferredTypes, fnTypeParams);
 
-      // See if this actually worked.
-      // If not, fall back to the known upper bound (if any) or `dynamic`.
+      // See if the constraints on the type variable are satisfied.
+      //
+      // If not, bail out of the analysis, unless a partial solution was
+      // requested. If we are willing to accept a partial solution, fall back to
+      // the known upper bound (if any) or `dynamic` for this unsolvable type
+      // variable.
       if (inferredTypes[i].isBottom ||
           !isSubtypeOf(inferredTypes[i],
               bound.upper.substitute2(inferredTypes, fnTypeParams)) ||
           !isSubtypeOf(bound.lower.substitute2(inferredTypes, fnTypeParams),
               inferredTypes[i])) {
+        // Unless a partial solution was requested, bail.
+        if (!allowPartialSolution) {
+          return null;
+        }
+
         inferredTypes[i] = DynamicTypeImpl.instance;
         if (typeParam.element.bound != null) {
           inferredTypes[i] =
diff --git a/pkg/analyzer/lib/src/generated/utilities_collection.dart b/pkg/analyzer/lib/src/generated/utilities_collection.dart
index 453ee37..a1f6cd6 100644
--- a/pkg/analyzer/lib/src/generated/utilities_collection.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_collection.dart
@@ -7,8 +7,31 @@
 import 'dart:collection';
 import "dart:math" as math;
 
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/scanner.dart' show Token;
+
+/**
+ * Returns `true` if a and b contain equal elements in the same order.
+ */
+bool listsEqual(List a, List b) {
+  // TODO(rnystrom): package:collection also implements this, and analyzer
+  // already transitively depends on that package. Consider using it instead.
+  if (identical(a, b)) {
+    return true;
+  }
+
+  if (a.length != b.length) {
+    return false;
+  }
+
+  for (int i = 0; i < a.length; i++) {
+    if (a[i] != b[i]) {
+      return false;
+    }
+  }
+
+  return true;
+}
 
 /**
  * The class `BooleanArray` defines methods for operating on integers as if they were arrays
diff --git a/pkg/analyzer/lib/src/generated/utilities_dart.dart b/pkg/analyzer/lib/src/generated/utilities_dart.dart
index 5fe5e72..695f75e 100644
--- a/pkg/analyzer/lib/src/generated/utilities_dart.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_dart.dart
@@ -4,9 +4,25 @@
 
 library analyzer.src.generated.utilities_dart;
 
+import 'package:analyzer/dart/ast/ast.dart' show AnnotatedNode, Comment;
+import 'package:analyzer/dart/ast/token.dart' show Token;
+import 'package:analyzer/src/generated/element.dart' show ElementImpl;
 import 'package:analyzer/src/generated/java_core.dart';
 
 /**
+ * If the given [node] has a documentation comment, remember its content
+ * and range into the given [element].
+ */
+void setElementDocumentationComment(ElementImpl element, AnnotatedNode node) {
+  Comment comment = node.documentationComment;
+  if (comment != null && comment.isDocumentation) {
+    element.documentationComment =
+        comment.tokens.map((Token t) => t.lexeme).join('\n');
+    element.setDocRange(comment.offset, comment.length);
+  }
+}
+
+/**
  * Check whether [uri1] starts with (or 'is prefixed by') [uri2] by checking
  * path segments.
  */
diff --git a/pkg/analyzer/lib/src/generated/utilities_general.dart b/pkg/analyzer/lib/src/generated/utilities_general.dart
index 1adc883..e0600dc 100644
--- a/pkg/analyzer/lib/src/generated/utilities_general.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_general.dart
@@ -20,6 +20,24 @@
     value is bool ? value : toLowerCase(value) == 'true';
 
 /**
+ * Safely convert the given [value] to a bool value, or return `null` if the
+ * value coult not be converted.
+ */
+bool toBool(Object value) {
+  if (value is bool) {
+    return value;
+  }
+  String string = toLowerCase(value);
+  if (string == 'true') {
+    return true;
+  }
+  if (string == 'false') {
+    return false;
+  }
+  return null;
+}
+
+/**
  * Safely convert this [value] to lower case, returning `null` if [value] is
  * null.
  */
diff --git a/pkg/analyzer/lib/src/summary/base.dart b/pkg/analyzer/lib/src/summary/base.dart
index a04476b..c4a4cdb 100644
--- a/pkg/analyzer/lib/src/summary/base.dart
+++ b/pkg/analyzer/lib/src/summary/base.dart
@@ -8,6 +8,21 @@
 library analyzer.src.summary.base;
 
 /**
+ * Annotation used in the summary IDL to indicate the id of a field.  The set
+ * of ids used by a class must cover the contiguous range from 0 to N-1, where
+ * N is the number of fields.
+ *
+ * In order to preserve forwards and backwards compatibility, id numbers must
+ * be stable between releases.  So when new fields are added they should take
+ * the next available id without renumbering other fields.
+ */
+class Id {
+  final int value;
+
+  const Id(this.value);
+}
+
+/**
  * Instances of this class represent data that has been read from a summary.
  */
 abstract class SummaryClass {
diff --git a/pkg/analyzer/lib/src/summary/flat_buffers.dart b/pkg/analyzer/lib/src/summary/flat_buffers.dart
index c56b298..c7a4f44 100644
--- a/pkg/analyzer/lib/src/summary/flat_buffers.dart
+++ b/pkg/analyzer/lib/src/summary/flat_buffers.dart
@@ -63,6 +63,8 @@
   int _getUint32([int delta = 0]) =>
       _buffer.getUint32(_offset + delta, Endianness.LITTLE_ENDIAN);
 
+  int _getUint8([int delta = 0]) => _buffer.getUint8(_offset + delta);
+
   /**
    * If the [byteList] is already a [Uint8List] return it.
    * Otherwise return a [Uint8List] copy of the [byteList].
@@ -110,6 +112,12 @@
 
   _VTable _currentVTable;
 
+  /**
+   * Map containing all strings that have been written so far.  This allows us
+   * to avoid duplicating strings.
+   */
+  Map<String, Offset<String>> _strings = <String, Offset<String>>{};
+
   Builder({this.initialSize: 1024}) {
     reset();
   }
@@ -120,9 +128,7 @@
    * `0` for `false` and `1` for `true`.
    */
   void addBool(int field, bool value, [bool def]) {
-    if (_currentVTable == null) {
-      throw new StateError('Start a table before adding values.');
-    }
+    _ensureCurrentVTable();
     if (value != null && value != def) {
       int size = 1;
       _prepare(size, 1);
@@ -136,9 +142,7 @@
    * not added if the [value] is equal to [def].
    */
   void addInt32(int field, int value, [int def]) {
-    if (_currentVTable == null) {
-      throw new StateError('Start a table before adding values.');
-    }
+    _ensureCurrentVTable();
     if (value != null && value != def) {
       int size = 4;
       _prepare(size, 1);
@@ -152,9 +156,7 @@
    * not added if the [value] is equal to [def].
    */
   void addInt8(int field, int value, [int def]) {
-    if (_currentVTable == null) {
-      throw new StateError('Start a table before adding values.');
-    }
+    _ensureCurrentVTable();
     if (value != null && value != def) {
       int size = 1;
       _prepare(size, 1);
@@ -167,9 +169,7 @@
    * Add the [field] referencing an object with the given [offset].
    */
   void addOffset(int field, Offset offset) {
-    if (_currentVTable == null) {
-      throw new StateError('Start a table before adding values.');
-    }
+    _ensureCurrentVTable();
     if (offset != null) {
       _prepare(4, 1);
       _trackField(field);
@@ -182,9 +182,7 @@
    * is not added if the [value] is equal to [def].
    */
   void addUint32(int field, int value, [int def]) {
-    if (_currentVTable == null) {
-      throw new StateError('Start a table before adding values.');
-    }
+    _ensureCurrentVTable();
     if (value != null && value != def) {
       int size = 4;
       _prepare(size, 1);
@@ -194,17 +192,31 @@
   }
 
   /**
+   * Add the [field] with the given 8-bit unsigned integer [value].  The field
+   * is not added if the [value] is equal to [def].
+   */
+  void addUint8(int field, int value, [int def]) {
+    _ensureCurrentVTable();
+    if (value != null && value != def) {
+      int size = 1;
+      _prepare(size, 1);
+      _trackField(field);
+      _setUint8AtTail(_buf, _tail, value);
+    }
+  }
+
+  /**
    * End the current table and return its offset.
    */
   Offset endTable() {
     if (_currentVTable == null) {
       throw new StateError('Start a table before ending it.');
     }
-    // Prepare the size of the current table.
-    _currentVTable.tableSize = _tail - _currentTableEndTail;
     // Prepare for writing the VTable.
     _prepare(4, 1);
     int tableTail = _tail;
+    // Prepare the size of the current table.
+    _currentVTable.tableSize = tableTail - _currentTableEndTail;
     // Prepare the VTable to use for the current table.
     int vTableTail;
     {
@@ -301,10 +313,7 @@
    * Write the given list of [values].
    */
   Offset writeList(List<Offset> values) {
-    if (_currentVTable != null) {
-      throw new StateError(
-          'Cannot write a non-scalar value while writing a table.');
-    }
+    _ensureNoVTable();
     _prepare(4, 1 + values.length);
     Offset result = new Offset(_tail);
     int tail = _tail;
@@ -321,10 +330,7 @@
    * Write the given list of 64-bit float [values].
    */
   Offset writeListFloat64(List<double> values) {
-    if (_currentVTable != null) {
-      throw new StateError(
-          'Cannot write a non-scalar value while writing a table.');
-    }
+    _ensureNoVTable();
     _prepare(8, 1 + values.length);
     Offset result = new Offset(_tail);
     int tail = _tail;
@@ -341,10 +347,7 @@
    * Write the given list of signed 32-bit integer [values].
    */
   Offset writeListInt32(List<int> values) {
-    if (_currentVTable != null) {
-      throw new StateError(
-          'Cannot write a non-scalar value while writing a table.');
-    }
+    _ensureNoVTable();
     _prepare(4, 1 + values.length);
     Offset result = new Offset(_tail);
     int tail = _tail;
@@ -361,10 +364,7 @@
    * Write the given list of unsigned 32-bit integer [values].
    */
   Offset writeListUint32(List<int> values) {
-    if (_currentVTable != null) {
-      throw new StateError(
-          'Cannot write a non-scalar value while writing a table.');
-    }
+    _ensureNoVTable();
     _prepare(4, 1 + values.length);
     Offset result = new Offset(_tail);
     int tail = _tail;
@@ -378,28 +378,63 @@
   }
 
   /**
+   * Write the given list of unsigned 8-bit integer [values].
+   */
+  Offset writeListUint8(List<int> values) {
+    _ensureNoVTable();
+    _prepare(4, 1, additionalBytes: values.length);
+    Offset result = new Offset(_tail);
+    int tail = _tail;
+    _setUint32AtTail(_buf, tail, values.length);
+    tail -= 4;
+    for (int value in values) {
+      _setUint8AtTail(_buf, tail, value);
+      tail -= 1;
+    }
+    return result;
+  }
+
+  /**
    * Write the given string [value] and return its [Offset], or `null` if
    * the [value] is equal to [def].
    */
   Offset<String> writeString(String value, [String def]) {
+    _ensureNoVTable();
+    if (value != def) {
+      return _strings.putIfAbsent(value, () {
+        // TODO(scheglov) optimize for ASCII strings
+        List<int> bytes = UTF8.encode(value);
+        int length = bytes.length;
+        _prepare(4, 1, additionalBytes: length);
+        Offset<String> result = new Offset(_tail);
+        _setUint32AtTail(_buf, _tail, length);
+        int offset = _buf.lengthInBytes - _tail + 4;
+        for (int i = 0; i < length; i++) {
+          _buf.setUint8(offset++, bytes[i]);
+        }
+        return result;
+      });
+    }
+    return null;
+  }
+
+  /**
+   * Throw an exception if there is not currently a vtable.
+   */
+  void _ensureCurrentVTable() {
+    if (_currentVTable == null) {
+      throw new StateError('Start a table before adding values.');
+    }
+  }
+
+  /**
+   * Throw an exception if there is currently a vtable.
+   */
+  void _ensureNoVTable() {
     if (_currentVTable != null) {
       throw new StateError(
           'Cannot write a non-scalar value while writing a table.');
     }
-    if (value != def) {
-      // TODO(scheglov) optimize for ASCII strings
-      List<int> bytes = UTF8.encode(value);
-      int length = bytes.length;
-      _prepare(4, 1, additionalBytes: length);
-      Offset<String> result = new Offset(_tail);
-      _setUint32AtTail(_buf, _tail, length);
-      int offset = _buf.lengthInBytes - _tail + 4;
-      for (int i = 0; i < length; i++) {
-        _buf.setUint8(offset++, bytes[i]);
-      }
-      return result;
-    }
-    return null;
   }
 
   /**
@@ -453,6 +488,10 @@
   static void _setUint32AtTail(ByteData _buf, int tail, int x) {
     _buf.setUint32(_buf.lengthInBytes - tail, x, Endianness.LITTLE_ENDIAN);
   }
+
+  static void _setUint8AtTail(ByteData _buf, int tail, int x) {
+    _buf.setUint8(_buf.lengthInBytes - tail, x);
+  }
 }
 
 /**
@@ -511,7 +550,7 @@
 
   @override
   List<E> read(BufferPointer bp) =>
-      new _FbInt32List<E>(_elementReader, bp.derefObject());
+      new _FbGenericList<E>(_elementReader, bp.derefObject());
 }
 
 /**
@@ -598,6 +637,21 @@
 }
 
 /**
+ * Reader of lists of 32-bit float values.
+ *
+ * The returned unmodifiable lists lazily read values on access.
+ */
+class Uint32ListReader extends Reader<List<int>> {
+  const Uint32ListReader();
+
+  @override
+  int get size => 4;
+
+  @override
+  List<int> read(BufferPointer bp) => new _FbUint32List(bp.derefObject());
+}
+
+/**
  * The reader of unsigned 32-bit integers.
  */
 class Uint32Reader extends Reader<int> {
@@ -611,21 +665,25 @@
 }
 
 /**
+ * The reader of unsigned 8-bit integers.
+ */
+class Uint8Reader extends Reader<int> {
+  const Uint8Reader() : super();
+
+  @override
+  int get size => 1;
+
+  @override
+  int read(BufferPointer bp) => bp._getUint8();
+}
+
+/**
  * The list backed by 64-bit values - Uint64 length and Float64.
  */
 class _FbFloat64List extends _FbList<double> {
-  final BufferPointer bp;
-
-  int _length;
   List<double> _items;
 
-  _FbFloat64List(this.bp);
-
-  @override
-  int get length {
-    _length ??= bp._getUint32();
-    return _length;
-  }
+  _FbFloat64List(BufferPointer bp) : super(bp);
 
   @override
   double operator [](int i) {
@@ -641,29 +699,21 @@
 }
 
 /**
- * The list backed by 32-bit values - offsets or integers.
+ * List backed by a generic object which may have any size.
  */
-class _FbInt32List<E> extends _FbList<E> {
+class _FbGenericList<E> extends _FbList<E> {
   final Reader<E> elementReader;
-  final BufferPointer bp;
 
-  int _length;
   List<E> _items;
 
-  _FbInt32List(this.elementReader, this.bp);
-
-  @override
-  int get length {
-    _length ??= bp._getUint32();
-    return _length;
-  }
+  _FbGenericList(this.elementReader, BufferPointer bp) : super(bp);
 
   @override
   E operator [](int i) {
     _items ??= new List<E>(length);
     E item = _items[i];
     if (item == null) {
-      BufferPointer ref = bp._advance(4 + 4 * i);
+      BufferPointer ref = bp._advance(4 + elementReader.size * i);
       item = elementReader.read(ref);
       _items[i] = item;
     }
@@ -675,6 +725,17 @@
  * The base class for immutable lists read from flat buffers.
  */
 abstract class _FbList<E> extends Object with ListMixin<E> implements List<E> {
+  final BufferPointer bp;
+  int _length;
+
+  _FbList(this.bp);
+
+  @override
+  int get length {
+    _length ??= bp._getUint32();
+    return _length;
+  }
+
   @override
   void set length(int i) =>
       throw new StateError('Attempt to modify immutable list');
@@ -685,6 +746,26 @@
 }
 
 /**
+ * List backed by 32-bit unsigned integers.
+ */
+class _FbUint32List extends _FbList<int> {
+  List<int> _items;
+
+  _FbUint32List(BufferPointer bp) : super(bp);
+
+  @override
+  int operator [](int i) {
+    _items ??= new List<int>(length);
+    int item = _items[i];
+    if (item == null) {
+      item = bp._getUint32(4 + 4 * i);
+      _items[i] = item;
+    }
+    return item;
+  }
+}
+
+/**
  * Class that describes the structure of a table.
  */
 class _VTable {
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index 8f2fe1e..5507871 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -14,11 +14,11 @@
   const _ReferenceKindReader() : super();
 
   @override
-  int get size => 4;
+  int get size => 1;
 
   @override
   idl.ReferenceKind read(fb.BufferPointer bp) {
-    int index = const fb.Uint32Reader().read(bp);
+    int index = const fb.Uint8Reader().read(bp);
     return idl.ReferenceKind.values[index];
   }
 }
@@ -27,11 +27,11 @@
   const _UnlinkedConstOperationReader() : super();
 
   @override
-  int get size => 4;
+  int get size => 1;
 
   @override
   idl.UnlinkedConstOperation read(fb.BufferPointer bp) {
-    int index = const fb.Uint32Reader().read(bp);
+    int index = const fb.Uint8Reader().read(bp);
     return idl.UnlinkedConstOperation.values[index];
   }
 }
@@ -40,11 +40,11 @@
   const _UnlinkedConstructorInitializerKindReader() : super();
 
   @override
-  int get size => 4;
+  int get size => 1;
 
   @override
   idl.UnlinkedConstructorInitializerKind read(fb.BufferPointer bp) {
-    int index = const fb.Uint32Reader().read(bp);
+    int index = const fb.Uint8Reader().read(bp);
     return idl.UnlinkedConstructorInitializerKind.values[index];
   }
 }
@@ -53,11 +53,11 @@
   const _UnlinkedExecutableKindReader() : super();
 
   @override
-  int get size => 4;
+  int get size => 1;
 
   @override
   idl.UnlinkedExecutableKind read(fb.BufferPointer bp) {
-    int index = const fb.Uint32Reader().read(bp);
+    int index = const fb.Uint8Reader().read(bp);
     return idl.UnlinkedExecutableKind.values[index];
   }
 }
@@ -66,11 +66,11 @@
   const _UnlinkedParamKindReader() : super();
 
   @override
-  int get size => 4;
+  int get size => 1;
 
   @override
   idl.UnlinkedParamKind read(fb.BufferPointer bp) {
-    int index = const fb.Uint32Reader().read(bp);
+    int index = const fb.Uint8Reader().read(bp);
     return idl.UnlinkedParamKind.values[index];
   }
 }
@@ -205,19 +205,19 @@
     }
     fbBuilder.startTable();
     if (offset_implicitFunctionTypeIndices != null) {
-      fbBuilder.addOffset(0, offset_implicitFunctionTypeIndices);
+      fbBuilder.addOffset(4, offset_implicitFunctionTypeIndices);
     }
     if (_paramReference != null && _paramReference != 0) {
-      fbBuilder.addUint32(1, _paramReference);
+      fbBuilder.addUint32(3, _paramReference);
     }
     if (_reference != null && _reference != 0) {
-      fbBuilder.addUint32(2, _reference);
+      fbBuilder.addUint32(0, _reference);
     }
     if (_slot != null && _slot != 0) {
-      fbBuilder.addUint32(3, _slot);
+      fbBuilder.addUint32(2, _slot);
     }
     if (offset_typeArguments != null) {
-      fbBuilder.addOffset(4, offset_typeArguments);
+      fbBuilder.addOffset(1, offset_typeArguments);
     }
     return fbBuilder.endTable();
   }
@@ -243,31 +243,31 @@
 
   @override
   List<int> get implicitFunctionTypeIndices {
-    _implicitFunctionTypeIndices ??= const fb.ListReader<int>(const fb.Uint32Reader()).vTableGet(_bp, 0, const <int>[]);
+    _implicitFunctionTypeIndices ??= const fb.Uint32ListReader().vTableGet(_bp, 4, const <int>[]);
     return _implicitFunctionTypeIndices;
   }
 
   @override
   int get paramReference {
-    _paramReference ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
+    _paramReference ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
     return _paramReference;
   }
 
   @override
   int get reference {
-    _reference ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
+    _reference ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
     return _reference;
   }
 
   @override
   int get slot {
-    _slot ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+    _slot ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
     return _slot;
   }
 
   @override
   List<idl.EntityRef> get typeArguments {
-    _typeArguments ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bp, 4, const <idl.EntityRef>[]);
+    _typeArguments ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bp, 1, const <idl.EntityRef>[]);
     return _typeArguments;
   }
 }
@@ -333,10 +333,10 @@
     }
     fbBuilder.startTable();
     if (offset_parts != null) {
-      fbBuilder.addOffset(0, offset_parts);
+      fbBuilder.addOffset(1, offset_parts);
     }
     if (offset_uri != null) {
-      fbBuilder.addOffset(1, offset_uri);
+      fbBuilder.addOffset(0, offset_uri);
     }
     return fbBuilder.endTable();
   }
@@ -359,13 +359,13 @@
 
   @override
   List<String> get parts {
-    _parts ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 0, const <String>[]);
+    _parts ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 1, const <String>[]);
     return _parts;
   }
 
   @override
   String get uri {
-    _uri ??= const fb.StringReader().vTableGet(_bp, 1, '');
+    _uri ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _uri;
   }
 }
@@ -455,13 +455,13 @@
       fbBuilder.addUint32(0, _dependency);
     }
     if (_kind != null && _kind != idl.ReferenceKind.classOrEnum) {
-      fbBuilder.addUint32(1, _kind.index);
+      fbBuilder.addUint8(3, _kind.index);
     }
     if (offset_name != null) {
-      fbBuilder.addOffset(2, offset_name);
+      fbBuilder.addOffset(1, offset_name);
     }
     if (_unit != null && _unit != 0) {
-      fbBuilder.addUint32(3, _unit);
+      fbBuilder.addUint32(2, _unit);
     }
     return fbBuilder.endTable();
   }
@@ -492,19 +492,19 @@
 
   @override
   idl.ReferenceKind get kind {
-    _kind ??= const _ReferenceKindReader().vTableGet(_bp, 1, idl.ReferenceKind.classOrEnum);
+    _kind ??= const _ReferenceKindReader().vTableGet(_bp, 3, idl.ReferenceKind.classOrEnum);
     return _kind;
   }
 
   @override
   String get name {
-    _name ??= const fb.StringReader().vTableGet(_bp, 2, '');
+    _name ??= const fb.StringReader().vTableGet(_bp, 1, '');
     return _name;
   }
 
   @override
   int get unit {
-    _unit ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+    _unit ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
     return _unit;
   }
 }
@@ -644,16 +644,16 @@
       fbBuilder.addOffset(0, offset_dependencies);
     }
     if (offset_exportNames != null) {
-      fbBuilder.addOffset(1, offset_exportNames);
+      fbBuilder.addOffset(4, offset_exportNames);
     }
     if (offset_importDependencies != null) {
-      fbBuilder.addOffset(2, offset_importDependencies);
+      fbBuilder.addOffset(1, offset_importDependencies);
     }
     if (_numPrelinkedDependencies != null && _numPrelinkedDependencies != 0) {
-      fbBuilder.addUint32(3, _numPrelinkedDependencies);
+      fbBuilder.addUint32(2, _numPrelinkedDependencies);
     }
     if (offset_units != null) {
-      fbBuilder.addOffset(4, offset_units);
+      fbBuilder.addOffset(3, offset_units);
     }
     return fbBuilder.endTable();
   }
@@ -690,25 +690,25 @@
 
   @override
   List<idl.LinkedExportName> get exportNames {
-    _exportNames ??= const fb.ListReader<idl.LinkedExportName>(const _LinkedExportNameReader()).vTableGet(_bp, 1, const <idl.LinkedExportName>[]);
+    _exportNames ??= const fb.ListReader<idl.LinkedExportName>(const _LinkedExportNameReader()).vTableGet(_bp, 4, const <idl.LinkedExportName>[]);
     return _exportNames;
   }
 
   @override
   List<int> get importDependencies {
-    _importDependencies ??= const fb.ListReader<int>(const fb.Uint32Reader()).vTableGet(_bp, 2, const <int>[]);
+    _importDependencies ??= const fb.Uint32ListReader().vTableGet(_bp, 1, const <int>[]);
     return _importDependencies;
   }
 
   @override
   int get numPrelinkedDependencies {
-    _numPrelinkedDependencies ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+    _numPrelinkedDependencies ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
     return _numPrelinkedDependencies;
   }
 
   @override
   List<idl.LinkedUnit> get units {
-    _units ??= const fb.ListReader<idl.LinkedUnit>(const _LinkedUnitReader()).vTableGet(_bp, 4, const <idl.LinkedUnit>[]);
+    _units ??= const fb.ListReader<idl.LinkedUnit>(const _LinkedUnitReader()).vTableGet(_bp, 3, const <idl.LinkedUnit>[]);
     return _units;
   }
 }
@@ -843,13 +843,13 @@
     }
     fbBuilder.startTable();
     if (_containingReference != null && _containingReference != 0) {
-      fbBuilder.addUint32(0, _containingReference);
+      fbBuilder.addUint32(5, _containingReference);
     }
     if (_dependency != null && _dependency != 0) {
       fbBuilder.addUint32(1, _dependency);
     }
     if (_kind != null && _kind != idl.ReferenceKind.classOrEnum) {
-      fbBuilder.addUint32(2, _kind.index);
+      fbBuilder.addUint8(2, _kind.index);
     }
     if (offset_name != null) {
       fbBuilder.addOffset(3, offset_name);
@@ -858,7 +858,7 @@
       fbBuilder.addUint32(4, _numTypeParameters);
     }
     if (_unit != null && _unit != 0) {
-      fbBuilder.addUint32(5, _unit);
+      fbBuilder.addUint32(0, _unit);
     }
     return fbBuilder.endTable();
   }
@@ -885,7 +885,7 @@
 
   @override
   int get containingReference {
-    _containingReference ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
+    _containingReference ??= const fb.Uint32Reader().vTableGet(_bp, 5, 0);
     return _containingReference;
   }
 
@@ -915,7 +915,7 @@
 
   @override
   int get unit {
-    _unit ??= const fb.Uint32Reader().vTableGet(_bp, 5, 0);
+    _unit ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
     return _unit;
   }
 }
@@ -1405,43 +1405,43 @@
     }
     fbBuilder.startTable();
     if (offset_annotations != null) {
-      fbBuilder.addOffset(0, offset_annotations);
+      fbBuilder.addOffset(5, offset_annotations);
     }
     if (offset_documentationComment != null) {
-      fbBuilder.addOffset(1, offset_documentationComment);
+      fbBuilder.addOffset(6, offset_documentationComment);
     }
     if (offset_executables != null) {
       fbBuilder.addOffset(2, offset_executables);
     }
     if (offset_fields != null) {
-      fbBuilder.addOffset(3, offset_fields);
+      fbBuilder.addOffset(4, offset_fields);
     }
     if (_hasNoSupertype == true) {
-      fbBuilder.addBool(4, true);
+      fbBuilder.addBool(12, true);
     }
     if (offset_interfaces != null) {
-      fbBuilder.addOffset(5, offset_interfaces);
+      fbBuilder.addOffset(7, offset_interfaces);
     }
     if (_isAbstract == true) {
-      fbBuilder.addBool(6, true);
+      fbBuilder.addBool(8, true);
     }
     if (_isMixinApplication == true) {
-      fbBuilder.addBool(7, true);
+      fbBuilder.addBool(11, true);
     }
     if (offset_mixins != null) {
-      fbBuilder.addOffset(8, offset_mixins);
+      fbBuilder.addOffset(10, offset_mixins);
     }
     if (offset_name != null) {
-      fbBuilder.addOffset(9, offset_name);
+      fbBuilder.addOffset(0, offset_name);
     }
     if (_nameOffset != null && _nameOffset != 0) {
-      fbBuilder.addUint32(10, _nameOffset);
+      fbBuilder.addUint32(1, _nameOffset);
     }
     if (offset_supertype != null) {
-      fbBuilder.addOffset(11, offset_supertype);
+      fbBuilder.addOffset(3, offset_supertype);
     }
     if (offset_typeParameters != null) {
-      fbBuilder.addOffset(12, offset_typeParameters);
+      fbBuilder.addOffset(9, offset_typeParameters);
     }
     return fbBuilder.endTable();
   }
@@ -1475,13 +1475,13 @@
 
   @override
   List<idl.UnlinkedConst> get annotations {
-    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 5, const <idl.UnlinkedConst>[]);
     return _annotations;
   }
 
   @override
   idl.UnlinkedDocumentationComment get documentationComment {
-    _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 1, null);
+    _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 6, null);
     return _documentationComment;
   }
 
@@ -1493,61 +1493,61 @@
 
   @override
   List<idl.UnlinkedVariable> get fields {
-    _fields ??= const fb.ListReader<idl.UnlinkedVariable>(const _UnlinkedVariableReader()).vTableGet(_bp, 3, const <idl.UnlinkedVariable>[]);
+    _fields ??= const fb.ListReader<idl.UnlinkedVariable>(const _UnlinkedVariableReader()).vTableGet(_bp, 4, const <idl.UnlinkedVariable>[]);
     return _fields;
   }
 
   @override
   bool get hasNoSupertype {
-    _hasNoSupertype ??= const fb.BoolReader().vTableGet(_bp, 4, false);
+    _hasNoSupertype ??= const fb.BoolReader().vTableGet(_bp, 12, false);
     return _hasNoSupertype;
   }
 
   @override
   List<idl.EntityRef> get interfaces {
-    _interfaces ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bp, 5, const <idl.EntityRef>[]);
+    _interfaces ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bp, 7, const <idl.EntityRef>[]);
     return _interfaces;
   }
 
   @override
   bool get isAbstract {
-    _isAbstract ??= const fb.BoolReader().vTableGet(_bp, 6, false);
+    _isAbstract ??= const fb.BoolReader().vTableGet(_bp, 8, false);
     return _isAbstract;
   }
 
   @override
   bool get isMixinApplication {
-    _isMixinApplication ??= const fb.BoolReader().vTableGet(_bp, 7, false);
+    _isMixinApplication ??= const fb.BoolReader().vTableGet(_bp, 11, false);
     return _isMixinApplication;
   }
 
   @override
   List<idl.EntityRef> get mixins {
-    _mixins ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bp, 8, const <idl.EntityRef>[]);
+    _mixins ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bp, 10, const <idl.EntityRef>[]);
     return _mixins;
   }
 
   @override
   String get name {
-    _name ??= const fb.StringReader().vTableGet(_bp, 9, '');
+    _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _name;
   }
 
   @override
   int get nameOffset {
-    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 10, 0);
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _nameOffset;
   }
 
   @override
   idl.EntityRef get supertype {
-    _supertype ??= const _EntityRefReader().vTableGet(_bp, 11, null);
+    _supertype ??= const _EntityRefReader().vTableGet(_bp, 3, null);
     return _supertype;
   }
 
   @override
   List<idl.UnlinkedTypeParam> get typeParameters {
-    _typeParameters ??= const fb.ListReader<idl.UnlinkedTypeParam>(const _UnlinkedTypeParamReader()).vTableGet(_bp, 12, const <idl.UnlinkedTypeParam>[]);
+    _typeParameters ??= const fb.ListReader<idl.UnlinkedTypeParam>(const _UnlinkedTypeParamReader()).vTableGet(_bp, 9, const <idl.UnlinkedTypeParam>[]);
     return _typeParameters;
   }
 }
@@ -1616,10 +1616,10 @@
     }
     fbBuilder.startTable();
     if (offset_hides != null) {
-      fbBuilder.addOffset(0, offset_hides);
+      fbBuilder.addOffset(1, offset_hides);
     }
     if (offset_shows != null) {
-      fbBuilder.addOffset(1, offset_shows);
+      fbBuilder.addOffset(0, offset_shows);
     }
     return fbBuilder.endTable();
   }
@@ -1642,13 +1642,13 @@
 
   @override
   List<String> get hides {
-    _hides ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 0, const <String>[]);
+    _hides ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 1, const <String>[]);
     return _hides;
   }
 
   @override
   List<String> get shows {
-    _shows ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 1, const <String>[]);
+    _shows ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 0, const <String>[]);
     return _shows;
   }
 }
@@ -1769,7 +1769,7 @@
       offset_ints = fbBuilder.writeListUint32(_ints);
     }
     if (!(_operations == null || _operations.isEmpty)) {
-      offset_operations = fbBuilder.writeListUint32(_operations.map((b) => b.index).toList());
+      offset_operations = fbBuilder.writeListUint8(_operations.map((b) => b.index).toList());
     }
     if (!(_references == null || _references.isEmpty)) {
       offset_references = fbBuilder.writeList(_references.map((b) => b.finish(fbBuilder)).toList());
@@ -1779,22 +1779,22 @@
     }
     fbBuilder.startTable();
     if (offset_doubles != null) {
-      fbBuilder.addOffset(0, offset_doubles);
+      fbBuilder.addOffset(4, offset_doubles);
     }
     if (offset_ints != null) {
       fbBuilder.addOffset(1, offset_ints);
     }
     if (_isInvalid == true) {
-      fbBuilder.addBool(2, true);
+      fbBuilder.addBool(5, true);
     }
     if (offset_operations != null) {
-      fbBuilder.addOffset(3, offset_operations);
+      fbBuilder.addOffset(0, offset_operations);
     }
     if (offset_references != null) {
-      fbBuilder.addOffset(4, offset_references);
+      fbBuilder.addOffset(2, offset_references);
     }
     if (offset_strings != null) {
-      fbBuilder.addOffset(5, offset_strings);
+      fbBuilder.addOffset(3, offset_strings);
     }
     return fbBuilder.endTable();
   }
@@ -1821,37 +1821,37 @@
 
   @override
   List<double> get doubles {
-    _doubles ??= const fb.Float64ListReader().vTableGet(_bp, 0, const <double>[]);
+    _doubles ??= const fb.Float64ListReader().vTableGet(_bp, 4, const <double>[]);
     return _doubles;
   }
 
   @override
   List<int> get ints {
-    _ints ??= const fb.ListReader<int>(const fb.Uint32Reader()).vTableGet(_bp, 1, const <int>[]);
+    _ints ??= const fb.Uint32ListReader().vTableGet(_bp, 1, const <int>[]);
     return _ints;
   }
 
   @override
   bool get isInvalid {
-    _isInvalid ??= const fb.BoolReader().vTableGet(_bp, 2, false);
+    _isInvalid ??= const fb.BoolReader().vTableGet(_bp, 5, false);
     return _isInvalid;
   }
 
   @override
   List<idl.UnlinkedConstOperation> get operations {
-    _operations ??= const fb.ListReader<idl.UnlinkedConstOperation>(const _UnlinkedConstOperationReader()).vTableGet(_bp, 3, const <idl.UnlinkedConstOperation>[]);
+    _operations ??= const fb.ListReader<idl.UnlinkedConstOperation>(const _UnlinkedConstOperationReader()).vTableGet(_bp, 0, const <idl.UnlinkedConstOperation>[]);
     return _operations;
   }
 
   @override
   List<idl.EntityRef> get references {
-    _references ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bp, 4, const <idl.EntityRef>[]);
+    _references ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bp, 2, const <idl.EntityRef>[]);
     return _references;
   }
 
   @override
   List<String> get strings {
-    _strings ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 5, const <String>[]);
+    _strings ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 3, const <String>[]);
     return _strings;
   }
 }
@@ -1948,16 +1948,16 @@
     }
     fbBuilder.startTable();
     if (offset_arguments != null) {
-      fbBuilder.addOffset(0, offset_arguments);
+      fbBuilder.addOffset(3, offset_arguments);
     }
     if (offset_expression != null) {
       fbBuilder.addOffset(1, offset_expression);
     }
     if (_kind != null && _kind != idl.UnlinkedConstructorInitializerKind.field) {
-      fbBuilder.addUint32(2, _kind.index);
+      fbBuilder.addUint8(2, _kind.index);
     }
     if (offset_name != null) {
-      fbBuilder.addOffset(3, offset_name);
+      fbBuilder.addOffset(0, offset_name);
     }
     return fbBuilder.endTable();
   }
@@ -1982,7 +1982,7 @@
 
   @override
   List<idl.UnlinkedConst> get arguments {
-    _arguments ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+    _arguments ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 3, const <idl.UnlinkedConst>[]);
     return _arguments;
   }
 
@@ -2000,7 +2000,7 @@
 
   @override
   String get name {
-    _name ??= const fb.StringReader().vTableGet(_bp, 3, '');
+    _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _name;
   }
 }
@@ -2078,10 +2078,10 @@
       fbBuilder.addUint32(0, _length);
     }
     if (_offset != null && _offset != 0) {
-      fbBuilder.addUint32(1, _offset);
+      fbBuilder.addUint32(2, _offset);
     }
     if (offset_text != null) {
-      fbBuilder.addOffset(2, offset_text);
+      fbBuilder.addOffset(1, offset_text);
     }
     return fbBuilder.endTable();
   }
@@ -2111,13 +2111,13 @@
 
   @override
   int get offset {
-    _offset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
+    _offset ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
     return _offset;
   }
 
   @override
   String get text {
-    _text ??= const fb.StringReader().vTableGet(_bp, 2, '');
+    _text ??= const fb.StringReader().vTableGet(_bp, 1, '');
     return _text;
   }
 }
@@ -2225,19 +2225,19 @@
     }
     fbBuilder.startTable();
     if (offset_annotations != null) {
-      fbBuilder.addOffset(0, offset_annotations);
+      fbBuilder.addOffset(4, offset_annotations);
     }
     if (offset_documentationComment != null) {
-      fbBuilder.addOffset(1, offset_documentationComment);
+      fbBuilder.addOffset(3, offset_documentationComment);
     }
     if (offset_name != null) {
-      fbBuilder.addOffset(2, offset_name);
+      fbBuilder.addOffset(0, offset_name);
     }
     if (_nameOffset != null && _nameOffset != 0) {
-      fbBuilder.addUint32(3, _nameOffset);
+      fbBuilder.addUint32(1, _nameOffset);
     }
     if (offset_values != null) {
-      fbBuilder.addOffset(4, offset_values);
+      fbBuilder.addOffset(2, offset_values);
     }
     return fbBuilder.endTable();
   }
@@ -2263,31 +2263,31 @@
 
   @override
   List<idl.UnlinkedConst> get annotations {
-    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 4, const <idl.UnlinkedConst>[]);
     return _annotations;
   }
 
   @override
   idl.UnlinkedDocumentationComment get documentationComment {
-    _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 1, null);
+    _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 3, null);
     return _documentationComment;
   }
 
   @override
   String get name {
-    _name ??= const fb.StringReader().vTableGet(_bp, 2, '');
+    _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _name;
   }
 
   @override
   int get nameOffset {
-    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _nameOffset;
   }
 
   @override
   List<idl.UnlinkedEnumValue> get values {
-    _values ??= const fb.ListReader<idl.UnlinkedEnumValue>(const _UnlinkedEnumValueReader()).vTableGet(_bp, 4, const <idl.UnlinkedEnumValue>[]);
+    _values ??= const fb.ListReader<idl.UnlinkedEnumValue>(const _UnlinkedEnumValueReader()).vTableGet(_bp, 2, const <idl.UnlinkedEnumValue>[]);
     return _values;
   }
 }
@@ -2363,13 +2363,13 @@
     }
     fbBuilder.startTable();
     if (offset_documentationComment != null) {
-      fbBuilder.addOffset(0, offset_documentationComment);
+      fbBuilder.addOffset(2, offset_documentationComment);
     }
     if (offset_name != null) {
-      fbBuilder.addOffset(1, offset_name);
+      fbBuilder.addOffset(0, offset_name);
     }
     if (_nameOffset != null && _nameOffset != 0) {
-      fbBuilder.addUint32(2, _nameOffset);
+      fbBuilder.addUint32(1, _nameOffset);
     }
     return fbBuilder.endTable();
   }
@@ -2393,19 +2393,19 @@
 
   @override
   idl.UnlinkedDocumentationComment get documentationComment {
-    _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 0, null);
+    _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 2, null);
     return _documentationComment;
   }
 
   @override
   String get name {
-    _name ??= const fb.StringReader().vTableGet(_bp, 1, '');
+    _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _name;
   }
 
   @override
   int get nameOffset {
-    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _nameOffset;
   }
 }
@@ -2430,13 +2430,20 @@
   bool _isConst;
   bool _isExternal;
   bool _isFactory;
+  bool _isRedirectedConstructor;
   bool _isStatic;
   idl.UnlinkedExecutableKind _kind;
+  List<UnlinkedExecutableBuilder> _localFunctions;
+  List<UnlinkedVariableBuilder> _localVariables;
   String _name;
   int _nameOffset;
   List<UnlinkedParamBuilder> _parameters;
+  EntityRefBuilder _redirectedConstructor;
+  String _redirectedConstructorName;
   EntityRefBuilder _returnType;
   List<UnlinkedTypeParamBuilder> _typeParameters;
+  int _visibleLength;
+  int _visibleOffset;
 
   @override
   List<UnlinkedConstBuilder> get annotations => _annotations ??= <UnlinkedConstBuilder>[];
@@ -2534,6 +2541,17 @@
   }
 
   @override
+  bool get isRedirectedConstructor => _isRedirectedConstructor ??= false;
+
+  /**
+   * Indicates whether the executable is a redirected constructor.
+   */
+  void set isRedirectedConstructor(bool _value) {
+    assert(!_finished);
+    _isRedirectedConstructor = _value;
+  }
+
+  @override
   bool get isStatic => _isStatic ??= false;
 
   /**
@@ -2561,6 +2579,28 @@
   }
 
   @override
+  List<UnlinkedExecutableBuilder> get localFunctions => _localFunctions ??= <UnlinkedExecutableBuilder>[];
+
+  /**
+   * The list of local functions.
+   */
+  void set localFunctions(List<UnlinkedExecutableBuilder> _value) {
+    assert(!_finished);
+    _localFunctions = _value;
+  }
+
+  @override
+  List<UnlinkedVariableBuilder> get localVariables => _localVariables ??= <UnlinkedVariableBuilder>[];
+
+  /**
+   * The list of local variables.
+   */
+  void set localVariables(List<UnlinkedVariableBuilder> _value) {
+    assert(!_finished);
+    _localVariables = _value;
+  }
+
+  @override
   String get name => _name ??= '';
 
   /**
@@ -2602,6 +2642,31 @@
   }
 
   @override
+  EntityRefBuilder get redirectedConstructor => _redirectedConstructor;
+
+  /**
+   * If [isRedirectedConstructor] and [isFactory] are both `true`, the
+   * constructor to which this constructor redirects; otherwise empty.
+   */
+  void set redirectedConstructor(EntityRefBuilder _value) {
+    assert(!_finished);
+    _redirectedConstructor = _value;
+  }
+
+  @override
+  String get redirectedConstructorName => _redirectedConstructorName ??= '';
+
+  /**
+   * If [isRedirectedConstructor] is `true` and [isFactory] is `false`, the
+   * name of the constructor that this constructor redirects to; otherwise
+   * empty.
+   */
+  void set redirectedConstructorName(String _value) {
+    assert(!_finished);
+    _redirectedConstructorName = _value;
+  }
+
+  @override
   EntityRefBuilder get returnType => _returnType;
 
   /**
@@ -2625,7 +2690,31 @@
     _typeParameters = _value;
   }
 
-  UnlinkedExecutableBuilder({List<UnlinkedConstBuilder> annotations, List<UnlinkedConstructorInitializerBuilder> constantInitializers, UnlinkedDocumentationCommentBuilder documentationComment, int inferredReturnTypeSlot, bool isAbstract, bool isConst, bool isExternal, bool isFactory, bool isStatic, idl.UnlinkedExecutableKind kind, String name, int nameOffset, List<UnlinkedParamBuilder> parameters, EntityRefBuilder returnType, List<UnlinkedTypeParamBuilder> typeParameters})
+  @override
+  int get visibleLength => _visibleLength ??= 0;
+
+  /**
+   * If a local function, the length of the visible range; zero otherwise.
+   */
+  void set visibleLength(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _visibleLength = _value;
+  }
+
+  @override
+  int get visibleOffset => _visibleOffset ??= 0;
+
+  /**
+   * If a local function, the beginning of the visible range; zero otherwise.
+   */
+  void set visibleOffset(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _visibleOffset = _value;
+  }
+
+  UnlinkedExecutableBuilder({List<UnlinkedConstBuilder> annotations, List<UnlinkedConstructorInitializerBuilder> constantInitializers, UnlinkedDocumentationCommentBuilder documentationComment, int inferredReturnTypeSlot, bool isAbstract, bool isConst, bool isExternal, bool isFactory, bool isRedirectedConstructor, bool isStatic, idl.UnlinkedExecutableKind kind, List<UnlinkedExecutableBuilder> localFunctions, List<UnlinkedVariableBuilder> localVariables, String name, int nameOffset, List<UnlinkedParamBuilder> parameters, EntityRefBuilder redirectedConstructor, String redirectedConstructorName, EntityRefBuilder returnType, List<UnlinkedTypeParamBuilder> typeParameters, int visibleLength, int visibleOffset})
     : _annotations = annotations,
       _constantInitializers = constantInitializers,
       _documentationComment = documentationComment,
@@ -2634,13 +2723,20 @@
       _isConst = isConst,
       _isExternal = isExternal,
       _isFactory = isFactory,
+      _isRedirectedConstructor = isRedirectedConstructor,
       _isStatic = isStatic,
       _kind = kind,
+      _localFunctions = localFunctions,
+      _localVariables = localVariables,
       _name = name,
       _nameOffset = nameOffset,
       _parameters = parameters,
+      _redirectedConstructor = redirectedConstructor,
+      _redirectedConstructorName = redirectedConstructorName,
       _returnType = returnType,
-      _typeParameters = typeParameters;
+      _typeParameters = typeParameters,
+      _visibleLength = visibleLength,
+      _visibleOffset = visibleOffset;
 
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
@@ -2648,8 +2744,12 @@
     fb.Offset offset_annotations;
     fb.Offset offset_constantInitializers;
     fb.Offset offset_documentationComment;
+    fb.Offset offset_localFunctions;
+    fb.Offset offset_localVariables;
     fb.Offset offset_name;
     fb.Offset offset_parameters;
+    fb.Offset offset_redirectedConstructor;
+    fb.Offset offset_redirectedConstructorName;
     fb.Offset offset_returnType;
     fb.Offset offset_typeParameters;
     if (!(_annotations == null || _annotations.isEmpty)) {
@@ -2661,12 +2761,24 @@
     if (_documentationComment != null) {
       offset_documentationComment = _documentationComment.finish(fbBuilder);
     }
+    if (!(_localFunctions == null || _localFunctions.isEmpty)) {
+      offset_localFunctions = fbBuilder.writeList(_localFunctions.map((b) => b.finish(fbBuilder)).toList());
+    }
+    if (!(_localVariables == null || _localVariables.isEmpty)) {
+      offset_localVariables = fbBuilder.writeList(_localVariables.map((b) => b.finish(fbBuilder)).toList());
+    }
     if (_name != null) {
       offset_name = fbBuilder.writeString(_name);
     }
     if (!(_parameters == null || _parameters.isEmpty)) {
       offset_parameters = fbBuilder.writeList(_parameters.map((b) => b.finish(fbBuilder)).toList());
     }
+    if (_redirectedConstructor != null) {
+      offset_redirectedConstructor = _redirectedConstructor.finish(fbBuilder);
+    }
+    if (_redirectedConstructorName != null) {
+      offset_redirectedConstructorName = fbBuilder.writeString(_redirectedConstructorName);
+    }
     if (_returnType != null) {
       offset_returnType = _returnType.finish(fbBuilder);
     }
@@ -2675,49 +2787,70 @@
     }
     fbBuilder.startTable();
     if (offset_annotations != null) {
-      fbBuilder.addOffset(0, offset_annotations);
+      fbBuilder.addOffset(6, offset_annotations);
     }
     if (offset_constantInitializers != null) {
-      fbBuilder.addOffset(1, offset_constantInitializers);
+      fbBuilder.addOffset(14, offset_constantInitializers);
     }
     if (offset_documentationComment != null) {
-      fbBuilder.addOffset(2, offset_documentationComment);
+      fbBuilder.addOffset(7, offset_documentationComment);
     }
     if (_inferredReturnTypeSlot != null && _inferredReturnTypeSlot != 0) {
-      fbBuilder.addUint32(3, _inferredReturnTypeSlot);
+      fbBuilder.addUint32(5, _inferredReturnTypeSlot);
     }
     if (_isAbstract == true) {
-      fbBuilder.addBool(4, true);
+      fbBuilder.addBool(10, true);
     }
     if (_isConst == true) {
-      fbBuilder.addBool(5, true);
+      fbBuilder.addBool(12, true);
     }
     if (_isExternal == true) {
-      fbBuilder.addBool(6, true);
+      fbBuilder.addBool(11, true);
     }
     if (_isFactory == true) {
-      fbBuilder.addBool(7, true);
-    }
-    if (_isStatic == true) {
       fbBuilder.addBool(8, true);
     }
+    if (_isRedirectedConstructor == true) {
+      fbBuilder.addBool(13, true);
+    }
+    if (_isStatic == true) {
+      fbBuilder.addBool(9, true);
+    }
     if (_kind != null && _kind != idl.UnlinkedExecutableKind.functionOrMethod) {
-      fbBuilder.addUint32(9, _kind.index);
+      fbBuilder.addUint8(4, _kind.index);
+    }
+    if (offset_localFunctions != null) {
+      fbBuilder.addOffset(18, offset_localFunctions);
+    }
+    if (offset_localVariables != null) {
+      fbBuilder.addOffset(19, offset_localVariables);
     }
     if (offset_name != null) {
-      fbBuilder.addOffset(10, offset_name);
+      fbBuilder.addOffset(1, offset_name);
     }
     if (_nameOffset != null && _nameOffset != 0) {
-      fbBuilder.addUint32(11, _nameOffset);
+      fbBuilder.addUint32(0, _nameOffset);
     }
     if (offset_parameters != null) {
-      fbBuilder.addOffset(12, offset_parameters);
+      fbBuilder.addOffset(2, offset_parameters);
+    }
+    if (offset_redirectedConstructor != null) {
+      fbBuilder.addOffset(15, offset_redirectedConstructor);
+    }
+    if (offset_redirectedConstructorName != null) {
+      fbBuilder.addOffset(17, offset_redirectedConstructorName);
     }
     if (offset_returnType != null) {
-      fbBuilder.addOffset(13, offset_returnType);
+      fbBuilder.addOffset(3, offset_returnType);
     }
     if (offset_typeParameters != null) {
-      fbBuilder.addOffset(14, offset_typeParameters);
+      fbBuilder.addOffset(16, offset_typeParameters);
+    }
+    if (_visibleLength != null && _visibleLength != 0) {
+      fbBuilder.addUint32(20, _visibleLength);
+    }
+    if (_visibleOffset != null && _visibleOffset != 0) {
+      fbBuilder.addUint32(21, _visibleOffset);
     }
     return fbBuilder.endTable();
   }
@@ -2743,103 +2876,152 @@
   bool _isConst;
   bool _isExternal;
   bool _isFactory;
+  bool _isRedirectedConstructor;
   bool _isStatic;
   idl.UnlinkedExecutableKind _kind;
+  List<idl.UnlinkedExecutable> _localFunctions;
+  List<idl.UnlinkedVariable> _localVariables;
   String _name;
   int _nameOffset;
   List<idl.UnlinkedParam> _parameters;
+  idl.EntityRef _redirectedConstructor;
+  String _redirectedConstructorName;
   idl.EntityRef _returnType;
   List<idl.UnlinkedTypeParam> _typeParameters;
+  int _visibleLength;
+  int _visibleOffset;
 
   @override
   List<idl.UnlinkedConst> get annotations {
-    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 6, const <idl.UnlinkedConst>[]);
     return _annotations;
   }
 
   @override
   List<idl.UnlinkedConstructorInitializer> get constantInitializers {
-    _constantInitializers ??= const fb.ListReader<idl.UnlinkedConstructorInitializer>(const _UnlinkedConstructorInitializerReader()).vTableGet(_bp, 1, const <idl.UnlinkedConstructorInitializer>[]);
+    _constantInitializers ??= const fb.ListReader<idl.UnlinkedConstructorInitializer>(const _UnlinkedConstructorInitializerReader()).vTableGet(_bp, 14, const <idl.UnlinkedConstructorInitializer>[]);
     return _constantInitializers;
   }
 
   @override
   idl.UnlinkedDocumentationComment get documentationComment {
-    _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 2, null);
+    _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 7, null);
     return _documentationComment;
   }
 
   @override
   int get inferredReturnTypeSlot {
-    _inferredReturnTypeSlot ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+    _inferredReturnTypeSlot ??= const fb.Uint32Reader().vTableGet(_bp, 5, 0);
     return _inferredReturnTypeSlot;
   }
 
   @override
   bool get isAbstract {
-    _isAbstract ??= const fb.BoolReader().vTableGet(_bp, 4, false);
+    _isAbstract ??= const fb.BoolReader().vTableGet(_bp, 10, false);
     return _isAbstract;
   }
 
   @override
   bool get isConst {
-    _isConst ??= const fb.BoolReader().vTableGet(_bp, 5, false);
+    _isConst ??= const fb.BoolReader().vTableGet(_bp, 12, false);
     return _isConst;
   }
 
   @override
   bool get isExternal {
-    _isExternal ??= const fb.BoolReader().vTableGet(_bp, 6, false);
+    _isExternal ??= const fb.BoolReader().vTableGet(_bp, 11, false);
     return _isExternal;
   }
 
   @override
   bool get isFactory {
-    _isFactory ??= const fb.BoolReader().vTableGet(_bp, 7, false);
+    _isFactory ??= const fb.BoolReader().vTableGet(_bp, 8, false);
     return _isFactory;
   }
 
   @override
+  bool get isRedirectedConstructor {
+    _isRedirectedConstructor ??= const fb.BoolReader().vTableGet(_bp, 13, false);
+    return _isRedirectedConstructor;
+  }
+
+  @override
   bool get isStatic {
-    _isStatic ??= const fb.BoolReader().vTableGet(_bp, 8, false);
+    _isStatic ??= const fb.BoolReader().vTableGet(_bp, 9, false);
     return _isStatic;
   }
 
   @override
   idl.UnlinkedExecutableKind get kind {
-    _kind ??= const _UnlinkedExecutableKindReader().vTableGet(_bp, 9, idl.UnlinkedExecutableKind.functionOrMethod);
+    _kind ??= const _UnlinkedExecutableKindReader().vTableGet(_bp, 4, idl.UnlinkedExecutableKind.functionOrMethod);
     return _kind;
   }
 
   @override
+  List<idl.UnlinkedExecutable> get localFunctions {
+    _localFunctions ??= const fb.ListReader<idl.UnlinkedExecutable>(const _UnlinkedExecutableReader()).vTableGet(_bp, 18, const <idl.UnlinkedExecutable>[]);
+    return _localFunctions;
+  }
+
+  @override
+  List<idl.UnlinkedVariable> get localVariables {
+    _localVariables ??= const fb.ListReader<idl.UnlinkedVariable>(const _UnlinkedVariableReader()).vTableGet(_bp, 19, const <idl.UnlinkedVariable>[]);
+    return _localVariables;
+  }
+
+  @override
   String get name {
-    _name ??= const fb.StringReader().vTableGet(_bp, 10, '');
+    _name ??= const fb.StringReader().vTableGet(_bp, 1, '');
     return _name;
   }
 
   @override
   int get nameOffset {
-    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 11, 0);
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
     return _nameOffset;
   }
 
   @override
   List<idl.UnlinkedParam> get parameters {
-    _parameters ??= const fb.ListReader<idl.UnlinkedParam>(const _UnlinkedParamReader()).vTableGet(_bp, 12, const <idl.UnlinkedParam>[]);
+    _parameters ??= const fb.ListReader<idl.UnlinkedParam>(const _UnlinkedParamReader()).vTableGet(_bp, 2, const <idl.UnlinkedParam>[]);
     return _parameters;
   }
 
   @override
+  idl.EntityRef get redirectedConstructor {
+    _redirectedConstructor ??= const _EntityRefReader().vTableGet(_bp, 15, null);
+    return _redirectedConstructor;
+  }
+
+  @override
+  String get redirectedConstructorName {
+    _redirectedConstructorName ??= const fb.StringReader().vTableGet(_bp, 17, '');
+    return _redirectedConstructorName;
+  }
+
+  @override
   idl.EntityRef get returnType {
-    _returnType ??= const _EntityRefReader().vTableGet(_bp, 13, null);
+    _returnType ??= const _EntityRefReader().vTableGet(_bp, 3, null);
     return _returnType;
   }
 
   @override
   List<idl.UnlinkedTypeParam> get typeParameters {
-    _typeParameters ??= const fb.ListReader<idl.UnlinkedTypeParam>(const _UnlinkedTypeParamReader()).vTableGet(_bp, 14, const <idl.UnlinkedTypeParam>[]);
+    _typeParameters ??= const fb.ListReader<idl.UnlinkedTypeParam>(const _UnlinkedTypeParamReader()).vTableGet(_bp, 16, const <idl.UnlinkedTypeParam>[]);
     return _typeParameters;
   }
+
+  @override
+  int get visibleLength {
+    _visibleLength ??= const fb.Uint32Reader().vTableGet(_bp, 20, 0);
+    return _visibleLength;
+  }
+
+  @override
+  int get visibleOffset {
+    _visibleOffset ??= const fb.Uint32Reader().vTableGet(_bp, 21, 0);
+    return _visibleOffset;
+  }
 }
 
 abstract class _UnlinkedExecutableMixin implements idl.UnlinkedExecutable {
@@ -2853,13 +3035,20 @@
     "isConst": isConst,
     "isExternal": isExternal,
     "isFactory": isFactory,
+    "isRedirectedConstructor": isRedirectedConstructor,
     "isStatic": isStatic,
     "kind": kind,
+    "localFunctions": localFunctions,
+    "localVariables": localVariables,
     "name": name,
     "nameOffset": nameOffset,
     "parameters": parameters,
+    "redirectedConstructor": redirectedConstructor,
+    "redirectedConstructorName": redirectedConstructorName,
     "returnType": returnType,
     "typeParameters": typeParameters,
+    "visibleLength": visibleLength,
+    "visibleOffset": visibleOffset,
   };
 }
 
@@ -2935,16 +3124,16 @@
     }
     fbBuilder.startTable();
     if (offset_annotations != null) {
-      fbBuilder.addOffset(0, offset_annotations);
+      fbBuilder.addOffset(3, offset_annotations);
     }
     if (_offset != null && _offset != 0) {
-      fbBuilder.addUint32(1, _offset);
+      fbBuilder.addUint32(0, _offset);
     }
     if (_uriEnd != null && _uriEnd != 0) {
-      fbBuilder.addUint32(2, _uriEnd);
+      fbBuilder.addUint32(1, _uriEnd);
     }
     if (_uriOffset != null && _uriOffset != 0) {
-      fbBuilder.addUint32(3, _uriOffset);
+      fbBuilder.addUint32(2, _uriOffset);
     }
     return fbBuilder.endTable();
   }
@@ -2969,25 +3158,25 @@
 
   @override
   List<idl.UnlinkedConst> get annotations {
-    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 3, const <idl.UnlinkedConst>[]);
     return _annotations;
   }
 
   @override
   int get offset {
-    _offset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
+    _offset ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
     return _offset;
   }
 
   @override
   int get uriEnd {
-    _uriEnd ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
+    _uriEnd ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _uriEnd;
   }
 
   @override
   int get uriOffset {
-    _uriOffset ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+    _uriOffset ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
     return _uriOffset;
   }
 }
@@ -3047,10 +3236,10 @@
     }
     fbBuilder.startTable();
     if (offset_combinators != null) {
-      fbBuilder.addOffset(0, offset_combinators);
+      fbBuilder.addOffset(1, offset_combinators);
     }
     if (offset_uri != null) {
-      fbBuilder.addOffset(1, offset_uri);
+      fbBuilder.addOffset(0, offset_uri);
     }
     return fbBuilder.endTable();
   }
@@ -3073,13 +3262,13 @@
 
   @override
   List<idl.UnlinkedCombinator> get combinators {
-    _combinators ??= const fb.ListReader<idl.UnlinkedCombinator>(const _UnlinkedCombinatorReader()).vTableGet(_bp, 0, const <idl.UnlinkedCombinator>[]);
+    _combinators ??= const fb.ListReader<idl.UnlinkedCombinator>(const _UnlinkedCombinatorReader()).vTableGet(_bp, 1, const <idl.UnlinkedCombinator>[]);
     return _combinators;
   }
 
   @override
   String get uri {
-    _uri ??= const fb.StringReader().vTableGet(_bp, 1, '');
+    _uri ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _uri;
   }
 }
@@ -3257,34 +3446,34 @@
     }
     fbBuilder.startTable();
     if (offset_annotations != null) {
-      fbBuilder.addOffset(0, offset_annotations);
+      fbBuilder.addOffset(8, offset_annotations);
     }
     if (offset_combinators != null) {
-      fbBuilder.addOffset(1, offset_combinators);
+      fbBuilder.addOffset(4, offset_combinators);
     }
     if (_isDeferred == true) {
-      fbBuilder.addBool(2, true);
+      fbBuilder.addBool(9, true);
     }
     if (_isImplicit == true) {
-      fbBuilder.addBool(3, true);
+      fbBuilder.addBool(5, true);
     }
     if (_offset != null && _offset != 0) {
-      fbBuilder.addUint32(4, _offset);
+      fbBuilder.addUint32(0, _offset);
     }
     if (_prefixOffset != null && _prefixOffset != 0) {
-      fbBuilder.addUint32(5, _prefixOffset);
+      fbBuilder.addUint32(6, _prefixOffset);
     }
     if (_prefixReference != null && _prefixReference != 0) {
-      fbBuilder.addUint32(6, _prefixReference);
+      fbBuilder.addUint32(7, _prefixReference);
     }
     if (offset_uri != null) {
-      fbBuilder.addOffset(7, offset_uri);
+      fbBuilder.addOffset(1, offset_uri);
     }
     if (_uriEnd != null && _uriEnd != 0) {
-      fbBuilder.addUint32(8, _uriEnd);
+      fbBuilder.addUint32(2, _uriEnd);
     }
     if (_uriOffset != null && _uriOffset != 0) {
-      fbBuilder.addUint32(9, _uriOffset);
+      fbBuilder.addUint32(3, _uriOffset);
     }
     return fbBuilder.endTable();
   }
@@ -3315,61 +3504,61 @@
 
   @override
   List<idl.UnlinkedConst> get annotations {
-    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 8, const <idl.UnlinkedConst>[]);
     return _annotations;
   }
 
   @override
   List<idl.UnlinkedCombinator> get combinators {
-    _combinators ??= const fb.ListReader<idl.UnlinkedCombinator>(const _UnlinkedCombinatorReader()).vTableGet(_bp, 1, const <idl.UnlinkedCombinator>[]);
+    _combinators ??= const fb.ListReader<idl.UnlinkedCombinator>(const _UnlinkedCombinatorReader()).vTableGet(_bp, 4, const <idl.UnlinkedCombinator>[]);
     return _combinators;
   }
 
   @override
   bool get isDeferred {
-    _isDeferred ??= const fb.BoolReader().vTableGet(_bp, 2, false);
+    _isDeferred ??= const fb.BoolReader().vTableGet(_bp, 9, false);
     return _isDeferred;
   }
 
   @override
   bool get isImplicit {
-    _isImplicit ??= const fb.BoolReader().vTableGet(_bp, 3, false);
+    _isImplicit ??= const fb.BoolReader().vTableGet(_bp, 5, false);
     return _isImplicit;
   }
 
   @override
   int get offset {
-    _offset ??= const fb.Uint32Reader().vTableGet(_bp, 4, 0);
+    _offset ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
     return _offset;
   }
 
   @override
   int get prefixOffset {
-    _prefixOffset ??= const fb.Uint32Reader().vTableGet(_bp, 5, 0);
+    _prefixOffset ??= const fb.Uint32Reader().vTableGet(_bp, 6, 0);
     return _prefixOffset;
   }
 
   @override
   int get prefixReference {
-    _prefixReference ??= const fb.Uint32Reader().vTableGet(_bp, 6, 0);
+    _prefixReference ??= const fb.Uint32Reader().vTableGet(_bp, 7, 0);
     return _prefixReference;
   }
 
   @override
   String get uri {
-    _uri ??= const fb.StringReader().vTableGet(_bp, 7, '');
+    _uri ??= const fb.StringReader().vTableGet(_bp, 1, '');
     return _uri;
   }
 
   @override
   int get uriEnd {
-    _uriEnd ??= const fb.Uint32Reader().vTableGet(_bp, 8, 0);
+    _uriEnd ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
     return _uriEnd;
   }
 
   @override
   int get uriOffset {
-    _uriOffset ??= const fb.Uint32Reader().vTableGet(_bp, 9, 0);
+    _uriOffset ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
     return _uriOffset;
   }
 }
@@ -3403,6 +3592,8 @@
   int _nameOffset;
   List<UnlinkedParamBuilder> _parameters;
   EntityRefBuilder _type;
+  int _visibleLength;
+  int _visibleOffset;
 
   @override
   List<UnlinkedConstBuilder> get annotations => _annotations ??= <UnlinkedConstBuilder>[];
@@ -3529,7 +3720,31 @@
     _type = _value;
   }
 
-  UnlinkedParamBuilder({List<UnlinkedConstBuilder> annotations, UnlinkedConstBuilder defaultValue, int inferredTypeSlot, bool isFunctionTyped, bool isInitializingFormal, idl.UnlinkedParamKind kind, String name, int nameOffset, List<UnlinkedParamBuilder> parameters, EntityRefBuilder type})
+  @override
+  int get visibleLength => _visibleLength ??= 0;
+
+  /**
+   * The length of the visible range.
+   */
+  void set visibleLength(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _visibleLength = _value;
+  }
+
+  @override
+  int get visibleOffset => _visibleOffset ??= 0;
+
+  /**
+   * The beginning of the visible range.
+   */
+  void set visibleOffset(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _visibleOffset = _value;
+  }
+
+  UnlinkedParamBuilder({List<UnlinkedConstBuilder> annotations, UnlinkedConstBuilder defaultValue, int inferredTypeSlot, bool isFunctionTyped, bool isInitializingFormal, idl.UnlinkedParamKind kind, String name, int nameOffset, List<UnlinkedParamBuilder> parameters, EntityRefBuilder type, int visibleLength, int visibleOffset})
     : _annotations = annotations,
       _defaultValue = defaultValue,
       _inferredTypeSlot = inferredTypeSlot,
@@ -3539,7 +3754,9 @@
       _name = name,
       _nameOffset = nameOffset,
       _parameters = parameters,
-      _type = type;
+      _type = type,
+      _visibleLength = visibleLength,
+      _visibleOffset = visibleOffset;
 
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
@@ -3566,34 +3783,40 @@
     }
     fbBuilder.startTable();
     if (offset_annotations != null) {
-      fbBuilder.addOffset(0, offset_annotations);
+      fbBuilder.addOffset(9, offset_annotations);
     }
     if (offset_defaultValue != null) {
-      fbBuilder.addOffset(1, offset_defaultValue);
+      fbBuilder.addOffset(7, offset_defaultValue);
     }
     if (_inferredTypeSlot != null && _inferredTypeSlot != 0) {
       fbBuilder.addUint32(2, _inferredTypeSlot);
     }
     if (_isFunctionTyped == true) {
-      fbBuilder.addBool(3, true);
+      fbBuilder.addBool(5, true);
     }
     if (_isInitializingFormal == true) {
-      fbBuilder.addBool(4, true);
+      fbBuilder.addBool(6, true);
     }
     if (_kind != null && _kind != idl.UnlinkedParamKind.required) {
-      fbBuilder.addUint32(5, _kind.index);
+      fbBuilder.addUint8(4, _kind.index);
     }
     if (offset_name != null) {
-      fbBuilder.addOffset(6, offset_name);
+      fbBuilder.addOffset(0, offset_name);
     }
     if (_nameOffset != null && _nameOffset != 0) {
-      fbBuilder.addUint32(7, _nameOffset);
+      fbBuilder.addUint32(1, _nameOffset);
     }
     if (offset_parameters != null) {
       fbBuilder.addOffset(8, offset_parameters);
     }
     if (offset_type != null) {
-      fbBuilder.addOffset(9, offset_type);
+      fbBuilder.addOffset(3, offset_type);
+    }
+    if (_visibleLength != null && _visibleLength != 0) {
+      fbBuilder.addUint32(10, _visibleLength);
+    }
+    if (_visibleOffset != null && _visibleOffset != 0) {
+      fbBuilder.addUint32(11, _visibleOffset);
     }
     return fbBuilder.endTable();
   }
@@ -3621,16 +3844,18 @@
   int _nameOffset;
   List<idl.UnlinkedParam> _parameters;
   idl.EntityRef _type;
+  int _visibleLength;
+  int _visibleOffset;
 
   @override
   List<idl.UnlinkedConst> get annotations {
-    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 9, const <idl.UnlinkedConst>[]);
     return _annotations;
   }
 
   @override
   idl.UnlinkedConst get defaultValue {
-    _defaultValue ??= const _UnlinkedConstReader().vTableGet(_bp, 1, null);
+    _defaultValue ??= const _UnlinkedConstReader().vTableGet(_bp, 7, null);
     return _defaultValue;
   }
 
@@ -3642,31 +3867,31 @@
 
   @override
   bool get isFunctionTyped {
-    _isFunctionTyped ??= const fb.BoolReader().vTableGet(_bp, 3, false);
+    _isFunctionTyped ??= const fb.BoolReader().vTableGet(_bp, 5, false);
     return _isFunctionTyped;
   }
 
   @override
   bool get isInitializingFormal {
-    _isInitializingFormal ??= const fb.BoolReader().vTableGet(_bp, 4, false);
+    _isInitializingFormal ??= const fb.BoolReader().vTableGet(_bp, 6, false);
     return _isInitializingFormal;
   }
 
   @override
   idl.UnlinkedParamKind get kind {
-    _kind ??= const _UnlinkedParamKindReader().vTableGet(_bp, 5, idl.UnlinkedParamKind.required);
+    _kind ??= const _UnlinkedParamKindReader().vTableGet(_bp, 4, idl.UnlinkedParamKind.required);
     return _kind;
   }
 
   @override
   String get name {
-    _name ??= const fb.StringReader().vTableGet(_bp, 6, '');
+    _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _name;
   }
 
   @override
   int get nameOffset {
-    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 7, 0);
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _nameOffset;
   }
 
@@ -3678,9 +3903,21 @@
 
   @override
   idl.EntityRef get type {
-    _type ??= const _EntityRefReader().vTableGet(_bp, 9, null);
+    _type ??= const _EntityRefReader().vTableGet(_bp, 3, null);
     return _type;
   }
+
+  @override
+  int get visibleLength {
+    _visibleLength ??= const fb.Uint32Reader().vTableGet(_bp, 10, 0);
+    return _visibleLength;
+  }
+
+  @override
+  int get visibleOffset {
+    _visibleOffset ??= const fb.Uint32Reader().vTableGet(_bp, 11, 0);
+    return _visibleOffset;
+  }
 }
 
 abstract class _UnlinkedParamMixin implements idl.UnlinkedParam {
@@ -3696,6 +3933,8 @@
     "nameOffset": nameOffset,
     "parameters": parameters,
     "type": type,
+    "visibleLength": visibleLength,
+    "visibleOffset": visibleOffset,
   };
 }
 
@@ -3757,13 +3996,13 @@
     }
     fbBuilder.startTable();
     if (offset_annotations != null) {
-      fbBuilder.addOffset(0, offset_annotations);
+      fbBuilder.addOffset(2, offset_annotations);
     }
     if (_uriEnd != null && _uriEnd != 0) {
-      fbBuilder.addUint32(1, _uriEnd);
+      fbBuilder.addUint32(0, _uriEnd);
     }
     if (_uriOffset != null && _uriOffset != 0) {
-      fbBuilder.addUint32(2, _uriOffset);
+      fbBuilder.addUint32(1, _uriOffset);
     }
     return fbBuilder.endTable();
   }
@@ -3787,19 +4026,19 @@
 
   @override
   List<idl.UnlinkedConst> get annotations {
-    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 2, const <idl.UnlinkedConst>[]);
     return _annotations;
   }
 
   @override
   int get uriEnd {
-    _uriEnd ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
+    _uriEnd ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
     return _uriEnd;
   }
 
   @override
   int get uriOffset {
-    _uriOffset ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
+    _uriOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _uriOffset;
   }
 }
@@ -3816,25 +4055,12 @@
 class UnlinkedPublicNameBuilder extends Object with _UnlinkedPublicNameMixin implements idl.UnlinkedPublicName {
   bool _finished = false;
 
-  List<UnlinkedPublicNameBuilder> _constMembers;
   idl.ReferenceKind _kind;
+  List<UnlinkedPublicNameBuilder> _members;
   String _name;
   int _numTypeParameters;
 
   @override
-  List<UnlinkedPublicNameBuilder> get constMembers => _constMembers ??= <UnlinkedPublicNameBuilder>[];
-
-  /**
-   * If this [UnlinkedPublicName] is a class, the list of members which can be
-   * referenced from constants - static constant fields, static methods, and
-   * constructors.  Otherwise empty.
-   */
-  void set constMembers(List<UnlinkedPublicNameBuilder> _value) {
-    assert(!_finished);
-    _constMembers = _value;
-  }
-
-  @override
   idl.ReferenceKind get kind => _kind ??= idl.ReferenceKind.classOrEnum;
 
   /**
@@ -3846,6 +4072,22 @@
   }
 
   @override
+  List<UnlinkedPublicNameBuilder> get members => _members ??= <UnlinkedPublicNameBuilder>[];
+
+  /**
+   * If this [UnlinkedPublicName] is a class, the list of members which can be
+   * referenced from constants or factory redirects - static constant fields,
+   * static methods, and constructors.  Otherwise empty.
+   *
+   * Unnamed constructors are not included since they do not constitute a
+   * separate name added to any namespace.
+   */
+  void set members(List<UnlinkedPublicNameBuilder> _value) {
+    assert(!_finished);
+    _members = _value;
+  }
+
+  @override
   String get name => _name ??= '';
 
   /**
@@ -3869,32 +4111,32 @@
     _numTypeParameters = _value;
   }
 
-  UnlinkedPublicNameBuilder({List<UnlinkedPublicNameBuilder> constMembers, idl.ReferenceKind kind, String name, int numTypeParameters})
-    : _constMembers = constMembers,
-      _kind = kind,
+  UnlinkedPublicNameBuilder({idl.ReferenceKind kind, List<UnlinkedPublicNameBuilder> members, String name, int numTypeParameters})
+    : _kind = kind,
+      _members = members,
       _name = name,
       _numTypeParameters = numTypeParameters;
 
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
-    fb.Offset offset_constMembers;
+    fb.Offset offset_members;
     fb.Offset offset_name;
-    if (!(_constMembers == null || _constMembers.isEmpty)) {
-      offset_constMembers = fbBuilder.writeList(_constMembers.map((b) => b.finish(fbBuilder)).toList());
+    if (!(_members == null || _members.isEmpty)) {
+      offset_members = fbBuilder.writeList(_members.map((b) => b.finish(fbBuilder)).toList());
     }
     if (_name != null) {
       offset_name = fbBuilder.writeString(_name);
     }
     fbBuilder.startTable();
-    if (offset_constMembers != null) {
-      fbBuilder.addOffset(0, offset_constMembers);
-    }
     if (_kind != null && _kind != idl.ReferenceKind.classOrEnum) {
-      fbBuilder.addUint32(1, _kind.index);
+      fbBuilder.addUint8(1, _kind.index);
+    }
+    if (offset_members != null) {
+      fbBuilder.addOffset(2, offset_members);
     }
     if (offset_name != null) {
-      fbBuilder.addOffset(2, offset_name);
+      fbBuilder.addOffset(0, offset_name);
     }
     if (_numTypeParameters != null && _numTypeParameters != 0) {
       fbBuilder.addUint32(3, _numTypeParameters);
@@ -3915,26 +4157,26 @@
 
   _UnlinkedPublicNameImpl(this._bp);
 
-  List<idl.UnlinkedPublicName> _constMembers;
   idl.ReferenceKind _kind;
+  List<idl.UnlinkedPublicName> _members;
   String _name;
   int _numTypeParameters;
 
   @override
-  List<idl.UnlinkedPublicName> get constMembers {
-    _constMembers ??= const fb.ListReader<idl.UnlinkedPublicName>(const _UnlinkedPublicNameReader()).vTableGet(_bp, 0, const <idl.UnlinkedPublicName>[]);
-    return _constMembers;
-  }
-
-  @override
   idl.ReferenceKind get kind {
     _kind ??= const _ReferenceKindReader().vTableGet(_bp, 1, idl.ReferenceKind.classOrEnum);
     return _kind;
   }
 
   @override
+  List<idl.UnlinkedPublicName> get members {
+    _members ??= const fb.ListReader<idl.UnlinkedPublicName>(const _UnlinkedPublicNameReader()).vTableGet(_bp, 2, const <idl.UnlinkedPublicName>[]);
+    return _members;
+  }
+
+  @override
   String get name {
-    _name ??= const fb.StringReader().vTableGet(_bp, 2, '');
+    _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _name;
   }
 
@@ -3948,8 +4190,8 @@
 abstract class _UnlinkedPublicNameMixin implements idl.UnlinkedPublicName {
   @override
   Map<String, Object> toMap() => {
-    "constMembers": constMembers,
     "kind": kind,
+    "members": members,
     "name": name,
     "numTypeParameters": numTypeParameters,
   };
@@ -4025,13 +4267,13 @@
     }
     fbBuilder.startTable();
     if (offset_exports != null) {
-      fbBuilder.addOffset(0, offset_exports);
+      fbBuilder.addOffset(2, offset_exports);
     }
     if (offset_names != null) {
-      fbBuilder.addOffset(1, offset_names);
+      fbBuilder.addOffset(0, offset_names);
     }
     if (offset_parts != null) {
-      fbBuilder.addOffset(2, offset_parts);
+      fbBuilder.addOffset(1, offset_parts);
     }
     return fbBuilder.endTable();
   }
@@ -4060,19 +4302,19 @@
 
   @override
   List<idl.UnlinkedExportPublic> get exports {
-    _exports ??= const fb.ListReader<idl.UnlinkedExportPublic>(const _UnlinkedExportPublicReader()).vTableGet(_bp, 0, const <idl.UnlinkedExportPublic>[]);
+    _exports ??= const fb.ListReader<idl.UnlinkedExportPublic>(const _UnlinkedExportPublicReader()).vTableGet(_bp, 2, const <idl.UnlinkedExportPublic>[]);
     return _exports;
   }
 
   @override
   List<idl.UnlinkedPublicName> get names {
-    _names ??= const fb.ListReader<idl.UnlinkedPublicName>(const _UnlinkedPublicNameReader()).vTableGet(_bp, 1, const <idl.UnlinkedPublicName>[]);
+    _names ??= const fb.ListReader<idl.UnlinkedPublicName>(const _UnlinkedPublicNameReader()).vTableGet(_bp, 0, const <idl.UnlinkedPublicName>[]);
     return _names;
   }
 
   @override
   List<String> get parts {
-    _parts ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 2, const <String>[]);
+    _parts ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 1, const <String>[]);
     return _parts;
   }
 }
@@ -4307,25 +4549,25 @@
     }
     fbBuilder.startTable();
     if (offset_annotations != null) {
-      fbBuilder.addOffset(0, offset_annotations);
+      fbBuilder.addOffset(4, offset_annotations);
     }
     if (offset_documentationComment != null) {
-      fbBuilder.addOffset(1, offset_documentationComment);
+      fbBuilder.addOffset(6, offset_documentationComment);
     }
     if (offset_name != null) {
-      fbBuilder.addOffset(2, offset_name);
+      fbBuilder.addOffset(0, offset_name);
     }
     if (_nameOffset != null && _nameOffset != 0) {
-      fbBuilder.addUint32(3, _nameOffset);
+      fbBuilder.addUint32(1, _nameOffset);
     }
     if (offset_parameters != null) {
-      fbBuilder.addOffset(4, offset_parameters);
+      fbBuilder.addOffset(3, offset_parameters);
     }
     if (offset_returnType != null) {
-      fbBuilder.addOffset(5, offset_returnType);
+      fbBuilder.addOffset(2, offset_returnType);
     }
     if (offset_typeParameters != null) {
-      fbBuilder.addOffset(6, offset_typeParameters);
+      fbBuilder.addOffset(5, offset_typeParameters);
     }
     return fbBuilder.endTable();
   }
@@ -4353,43 +4595,43 @@
 
   @override
   List<idl.UnlinkedConst> get annotations {
-    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 4, const <idl.UnlinkedConst>[]);
     return _annotations;
   }
 
   @override
   idl.UnlinkedDocumentationComment get documentationComment {
-    _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 1, null);
+    _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 6, null);
     return _documentationComment;
   }
 
   @override
   String get name {
-    _name ??= const fb.StringReader().vTableGet(_bp, 2, '');
+    _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _name;
   }
 
   @override
   int get nameOffset {
-    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _nameOffset;
   }
 
   @override
   List<idl.UnlinkedParam> get parameters {
-    _parameters ??= const fb.ListReader<idl.UnlinkedParam>(const _UnlinkedParamReader()).vTableGet(_bp, 4, const <idl.UnlinkedParam>[]);
+    _parameters ??= const fb.ListReader<idl.UnlinkedParam>(const _UnlinkedParamReader()).vTableGet(_bp, 3, const <idl.UnlinkedParam>[]);
     return _parameters;
   }
 
   @override
   idl.EntityRef get returnType {
-    _returnType ??= const _EntityRefReader().vTableGet(_bp, 5, null);
+    _returnType ??= const _EntityRefReader().vTableGet(_bp, 2, null);
     return _returnType;
   }
 
   @override
   List<idl.UnlinkedTypeParam> get typeParameters {
-    _typeParameters ??= const fb.ListReader<idl.UnlinkedTypeParam>(const _UnlinkedTypeParamReader()).vTableGet(_bp, 6, const <idl.UnlinkedTypeParam>[]);
+    _typeParameters ??= const fb.ListReader<idl.UnlinkedTypeParam>(const _UnlinkedTypeParamReader()).vTableGet(_bp, 5, const <idl.UnlinkedTypeParam>[]);
     return _typeParameters;
   }
 }
@@ -4484,16 +4726,16 @@
     }
     fbBuilder.startTable();
     if (offset_annotations != null) {
-      fbBuilder.addOffset(0, offset_annotations);
+      fbBuilder.addOffset(3, offset_annotations);
     }
     if (offset_bound != null) {
-      fbBuilder.addOffset(1, offset_bound);
+      fbBuilder.addOffset(2, offset_bound);
     }
     if (offset_name != null) {
-      fbBuilder.addOffset(2, offset_name);
+      fbBuilder.addOffset(0, offset_name);
     }
     if (_nameOffset != null && _nameOffset != 0) {
-      fbBuilder.addUint32(3, _nameOffset);
+      fbBuilder.addUint32(1, _nameOffset);
     }
     return fbBuilder.endTable();
   }
@@ -4518,25 +4760,25 @@
 
   @override
   List<idl.UnlinkedConst> get annotations {
-    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 3, const <idl.UnlinkedConst>[]);
     return _annotations;
   }
 
   @override
   idl.EntityRef get bound {
-    _bound ??= const _EntityRefReader().vTableGet(_bp, 1, null);
+    _bound ??= const _EntityRefReader().vTableGet(_bp, 2, null);
     return _bound;
   }
 
   @override
   String get name {
-    _name ??= const fb.StringReader().vTableGet(_bp, 2, '');
+    _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _name;
   }
 
   @override
   int get nameOffset {
-    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _nameOffset;
   }
 }
@@ -4825,49 +5067,49 @@
     }
     fbBuilder.startTable();
     if (offset_classes != null) {
-      fbBuilder.addOffset(0, offset_classes);
+      fbBuilder.addOffset(2, offset_classes);
     }
     if (offset_enums != null) {
-      fbBuilder.addOffset(1, offset_enums);
+      fbBuilder.addOffset(12, offset_enums);
     }
     if (offset_executables != null) {
-      fbBuilder.addOffset(2, offset_executables);
+      fbBuilder.addOffset(4, offset_executables);
     }
     if (offset_exports != null) {
-      fbBuilder.addOffset(3, offset_exports);
+      fbBuilder.addOffset(13, offset_exports);
     }
     if (offset_imports != null) {
-      fbBuilder.addOffset(4, offset_imports);
+      fbBuilder.addOffset(5, offset_imports);
     }
     if (offset_libraryAnnotations != null) {
-      fbBuilder.addOffset(5, offset_libraryAnnotations);
+      fbBuilder.addOffset(14, offset_libraryAnnotations);
     }
     if (offset_libraryDocumentationComment != null) {
-      fbBuilder.addOffset(6, offset_libraryDocumentationComment);
+      fbBuilder.addOffset(9, offset_libraryDocumentationComment);
     }
     if (offset_libraryName != null) {
-      fbBuilder.addOffset(7, offset_libraryName);
+      fbBuilder.addOffset(6, offset_libraryName);
     }
     if (_libraryNameLength != null && _libraryNameLength != 0) {
-      fbBuilder.addUint32(8, _libraryNameLength);
+      fbBuilder.addUint32(7, _libraryNameLength);
     }
     if (_libraryNameOffset != null && _libraryNameOffset != 0) {
-      fbBuilder.addUint32(9, _libraryNameOffset);
+      fbBuilder.addUint32(8, _libraryNameOffset);
     }
     if (offset_parts != null) {
-      fbBuilder.addOffset(10, offset_parts);
+      fbBuilder.addOffset(11, offset_parts);
     }
     if (offset_publicNamespace != null) {
-      fbBuilder.addOffset(11, offset_publicNamespace);
+      fbBuilder.addOffset(0, offset_publicNamespace);
     }
     if (offset_references != null) {
-      fbBuilder.addOffset(12, offset_references);
+      fbBuilder.addOffset(1, offset_references);
     }
     if (offset_typedefs != null) {
-      fbBuilder.addOffset(13, offset_typedefs);
+      fbBuilder.addOffset(10, offset_typedefs);
     }
     if (offset_variables != null) {
-      fbBuilder.addOffset(14, offset_variables);
+      fbBuilder.addOffset(3, offset_variables);
     }
     return fbBuilder.endTable();
   }
@@ -4908,91 +5150,91 @@
 
   @override
   List<idl.UnlinkedClass> get classes {
-    _classes ??= const fb.ListReader<idl.UnlinkedClass>(const _UnlinkedClassReader()).vTableGet(_bp, 0, const <idl.UnlinkedClass>[]);
+    _classes ??= const fb.ListReader<idl.UnlinkedClass>(const _UnlinkedClassReader()).vTableGet(_bp, 2, const <idl.UnlinkedClass>[]);
     return _classes;
   }
 
   @override
   List<idl.UnlinkedEnum> get enums {
-    _enums ??= const fb.ListReader<idl.UnlinkedEnum>(const _UnlinkedEnumReader()).vTableGet(_bp, 1, const <idl.UnlinkedEnum>[]);
+    _enums ??= const fb.ListReader<idl.UnlinkedEnum>(const _UnlinkedEnumReader()).vTableGet(_bp, 12, const <idl.UnlinkedEnum>[]);
     return _enums;
   }
 
   @override
   List<idl.UnlinkedExecutable> get executables {
-    _executables ??= const fb.ListReader<idl.UnlinkedExecutable>(const _UnlinkedExecutableReader()).vTableGet(_bp, 2, const <idl.UnlinkedExecutable>[]);
+    _executables ??= const fb.ListReader<idl.UnlinkedExecutable>(const _UnlinkedExecutableReader()).vTableGet(_bp, 4, const <idl.UnlinkedExecutable>[]);
     return _executables;
   }
 
   @override
   List<idl.UnlinkedExportNonPublic> get exports {
-    _exports ??= const fb.ListReader<idl.UnlinkedExportNonPublic>(const _UnlinkedExportNonPublicReader()).vTableGet(_bp, 3, const <idl.UnlinkedExportNonPublic>[]);
+    _exports ??= const fb.ListReader<idl.UnlinkedExportNonPublic>(const _UnlinkedExportNonPublicReader()).vTableGet(_bp, 13, const <idl.UnlinkedExportNonPublic>[]);
     return _exports;
   }
 
   @override
   List<idl.UnlinkedImport> get imports {
-    _imports ??= const fb.ListReader<idl.UnlinkedImport>(const _UnlinkedImportReader()).vTableGet(_bp, 4, const <idl.UnlinkedImport>[]);
+    _imports ??= const fb.ListReader<idl.UnlinkedImport>(const _UnlinkedImportReader()).vTableGet(_bp, 5, const <idl.UnlinkedImport>[]);
     return _imports;
   }
 
   @override
   List<idl.UnlinkedConst> get libraryAnnotations {
-    _libraryAnnotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 5, const <idl.UnlinkedConst>[]);
+    _libraryAnnotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 14, const <idl.UnlinkedConst>[]);
     return _libraryAnnotations;
   }
 
   @override
   idl.UnlinkedDocumentationComment get libraryDocumentationComment {
-    _libraryDocumentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 6, null);
+    _libraryDocumentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 9, null);
     return _libraryDocumentationComment;
   }
 
   @override
   String get libraryName {
-    _libraryName ??= const fb.StringReader().vTableGet(_bp, 7, '');
+    _libraryName ??= const fb.StringReader().vTableGet(_bp, 6, '');
     return _libraryName;
   }
 
   @override
   int get libraryNameLength {
-    _libraryNameLength ??= const fb.Uint32Reader().vTableGet(_bp, 8, 0);
+    _libraryNameLength ??= const fb.Uint32Reader().vTableGet(_bp, 7, 0);
     return _libraryNameLength;
   }
 
   @override
   int get libraryNameOffset {
-    _libraryNameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 9, 0);
+    _libraryNameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 8, 0);
     return _libraryNameOffset;
   }
 
   @override
   List<idl.UnlinkedPart> get parts {
-    _parts ??= const fb.ListReader<idl.UnlinkedPart>(const _UnlinkedPartReader()).vTableGet(_bp, 10, const <idl.UnlinkedPart>[]);
+    _parts ??= const fb.ListReader<idl.UnlinkedPart>(const _UnlinkedPartReader()).vTableGet(_bp, 11, const <idl.UnlinkedPart>[]);
     return _parts;
   }
 
   @override
   idl.UnlinkedPublicNamespace get publicNamespace {
-    _publicNamespace ??= const _UnlinkedPublicNamespaceReader().vTableGet(_bp, 11, null);
+    _publicNamespace ??= const _UnlinkedPublicNamespaceReader().vTableGet(_bp, 0, null);
     return _publicNamespace;
   }
 
   @override
   List<idl.UnlinkedReference> get references {
-    _references ??= const fb.ListReader<idl.UnlinkedReference>(const _UnlinkedReferenceReader()).vTableGet(_bp, 12, const <idl.UnlinkedReference>[]);
+    _references ??= const fb.ListReader<idl.UnlinkedReference>(const _UnlinkedReferenceReader()).vTableGet(_bp, 1, const <idl.UnlinkedReference>[]);
     return _references;
   }
 
   @override
   List<idl.UnlinkedTypedef> get typedefs {
-    _typedefs ??= const fb.ListReader<idl.UnlinkedTypedef>(const _UnlinkedTypedefReader()).vTableGet(_bp, 13, const <idl.UnlinkedTypedef>[]);
+    _typedefs ??= const fb.ListReader<idl.UnlinkedTypedef>(const _UnlinkedTypedefReader()).vTableGet(_bp, 10, const <idl.UnlinkedTypedef>[]);
     return _typedefs;
   }
 
   @override
   List<idl.UnlinkedVariable> get variables {
-    _variables ??= const fb.ListReader<idl.UnlinkedVariable>(const _UnlinkedVariableReader()).vTableGet(_bp, 14, const <idl.UnlinkedVariable>[]);
+    _variables ??= const fb.ListReader<idl.UnlinkedVariable>(const _UnlinkedVariableReader()).vTableGet(_bp, 3, const <idl.UnlinkedVariable>[]);
     return _variables;
   }
 }
@@ -5032,6 +5274,8 @@
   int _nameOffset;
   int _propagatedTypeSlot;
   EntityRefBuilder _type;
+  int _visibleLength;
+  int _visibleOffset;
 
   @override
   List<UnlinkedConstBuilder> get annotations => _annotations ??= <UnlinkedConstBuilder>[];
@@ -5172,7 +5416,31 @@
     _type = _value;
   }
 
-  UnlinkedVariableBuilder({List<UnlinkedConstBuilder> annotations, UnlinkedConstBuilder constExpr, UnlinkedDocumentationCommentBuilder documentationComment, int inferredTypeSlot, bool isConst, bool isFinal, bool isStatic, String name, int nameOffset, int propagatedTypeSlot, EntityRefBuilder type})
+  @override
+  int get visibleLength => _visibleLength ??= 0;
+
+  /**
+   * If a local variable, the length of the visible range; zero otherwise.
+   */
+  void set visibleLength(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _visibleLength = _value;
+  }
+
+  @override
+  int get visibleOffset => _visibleOffset ??= 0;
+
+  /**
+   * If a local variable, the beginning of the visible range; zero otherwise.
+   */
+  void set visibleOffset(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _visibleOffset = _value;
+  }
+
+  UnlinkedVariableBuilder({List<UnlinkedConstBuilder> annotations, UnlinkedConstBuilder constExpr, UnlinkedDocumentationCommentBuilder documentationComment, int inferredTypeSlot, bool isConst, bool isFinal, bool isStatic, String name, int nameOffset, int propagatedTypeSlot, EntityRefBuilder type, int visibleLength, int visibleOffset})
     : _annotations = annotations,
       _constExpr = constExpr,
       _documentationComment = documentationComment,
@@ -5183,7 +5451,9 @@
       _name = name,
       _nameOffset = nameOffset,
       _propagatedTypeSlot = propagatedTypeSlot,
-      _type = type;
+      _type = type,
+      _visibleLength = visibleLength,
+      _visibleOffset = visibleOffset;
 
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
@@ -5210,37 +5480,43 @@
     }
     fbBuilder.startTable();
     if (offset_annotations != null) {
-      fbBuilder.addOffset(0, offset_annotations);
+      fbBuilder.addOffset(8, offset_annotations);
     }
     if (offset_constExpr != null) {
-      fbBuilder.addOffset(1, offset_constExpr);
+      fbBuilder.addOffset(5, offset_constExpr);
     }
     if (offset_documentationComment != null) {
-      fbBuilder.addOffset(2, offset_documentationComment);
+      fbBuilder.addOffset(10, offset_documentationComment);
     }
     if (_inferredTypeSlot != null && _inferredTypeSlot != 0) {
-      fbBuilder.addUint32(3, _inferredTypeSlot);
+      fbBuilder.addUint32(9, _inferredTypeSlot);
     }
     if (_isConst == true) {
-      fbBuilder.addBool(4, true);
-    }
-    if (_isFinal == true) {
-      fbBuilder.addBool(5, true);
-    }
-    if (_isStatic == true) {
       fbBuilder.addBool(6, true);
     }
+    if (_isFinal == true) {
+      fbBuilder.addBool(7, true);
+    }
+    if (_isStatic == true) {
+      fbBuilder.addBool(4, true);
+    }
     if (offset_name != null) {
-      fbBuilder.addOffset(7, offset_name);
+      fbBuilder.addOffset(0, offset_name);
     }
     if (_nameOffset != null && _nameOffset != 0) {
-      fbBuilder.addUint32(8, _nameOffset);
+      fbBuilder.addUint32(1, _nameOffset);
     }
     if (_propagatedTypeSlot != null && _propagatedTypeSlot != 0) {
-      fbBuilder.addUint32(9, _propagatedTypeSlot);
+      fbBuilder.addUint32(2, _propagatedTypeSlot);
     }
     if (offset_type != null) {
-      fbBuilder.addOffset(10, offset_type);
+      fbBuilder.addOffset(3, offset_type);
+    }
+    if (_visibleLength != null && _visibleLength != 0) {
+      fbBuilder.addUint32(11, _visibleLength);
+    }
+    if (_visibleOffset != null && _visibleOffset != 0) {
+      fbBuilder.addUint32(12, _visibleOffset);
     }
     return fbBuilder.endTable();
   }
@@ -5269,72 +5545,86 @@
   int _nameOffset;
   int _propagatedTypeSlot;
   idl.EntityRef _type;
+  int _visibleLength;
+  int _visibleOffset;
 
   @override
   List<idl.UnlinkedConst> get annotations {
-    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+    _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 8, const <idl.UnlinkedConst>[]);
     return _annotations;
   }
 
   @override
   idl.UnlinkedConst get constExpr {
-    _constExpr ??= const _UnlinkedConstReader().vTableGet(_bp, 1, null);
+    _constExpr ??= const _UnlinkedConstReader().vTableGet(_bp, 5, null);
     return _constExpr;
   }
 
   @override
   idl.UnlinkedDocumentationComment get documentationComment {
-    _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 2, null);
+    _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 10, null);
     return _documentationComment;
   }
 
   @override
   int get inferredTypeSlot {
-    _inferredTypeSlot ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+    _inferredTypeSlot ??= const fb.Uint32Reader().vTableGet(_bp, 9, 0);
     return _inferredTypeSlot;
   }
 
   @override
   bool get isConst {
-    _isConst ??= const fb.BoolReader().vTableGet(_bp, 4, false);
+    _isConst ??= const fb.BoolReader().vTableGet(_bp, 6, false);
     return _isConst;
   }
 
   @override
   bool get isFinal {
-    _isFinal ??= const fb.BoolReader().vTableGet(_bp, 5, false);
+    _isFinal ??= const fb.BoolReader().vTableGet(_bp, 7, false);
     return _isFinal;
   }
 
   @override
   bool get isStatic {
-    _isStatic ??= const fb.BoolReader().vTableGet(_bp, 6, false);
+    _isStatic ??= const fb.BoolReader().vTableGet(_bp, 4, false);
     return _isStatic;
   }
 
   @override
   String get name {
-    _name ??= const fb.StringReader().vTableGet(_bp, 7, '');
+    _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _name;
   }
 
   @override
   int get nameOffset {
-    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 8, 0);
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _nameOffset;
   }
 
   @override
   int get propagatedTypeSlot {
-    _propagatedTypeSlot ??= const fb.Uint32Reader().vTableGet(_bp, 9, 0);
+    _propagatedTypeSlot ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
     return _propagatedTypeSlot;
   }
 
   @override
   idl.EntityRef get type {
-    _type ??= const _EntityRefReader().vTableGet(_bp, 10, null);
+    _type ??= const _EntityRefReader().vTableGet(_bp, 3, null);
     return _type;
   }
+
+  @override
+  int get visibleLength {
+    _visibleLength ??= const fb.Uint32Reader().vTableGet(_bp, 11, 0);
+    return _visibleLength;
+  }
+
+  @override
+  int get visibleOffset {
+    _visibleOffset ??= const fb.Uint32Reader().vTableGet(_bp, 12, 0);
+    return _visibleOffset;
+  }
 }
 
 abstract class _UnlinkedVariableMixin implements idl.UnlinkedVariable {
@@ -5351,6 +5641,8 @@
     "nameOffset": nameOffset,
     "propagatedTypeSlot": propagatedTypeSlot,
     "type": type,
+    "visibleLength": visibleLength,
+    "visibleOffset": visibleOffset,
   };
 }
 
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 6ec0ded..fca673c 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -42,29 +42,17 @@
 library analyzer.tool.summary.idl;
 
 import 'base.dart' as base;
+import 'base.dart' show Id;
 import 'format.dart' as generated;
 
 /**
  * Annotation describing information which is not part of Dart semantics; in
  * other words, if this information (or any information it refers to) changes,
  * static analysis and runtime behavior of the library are unaffected.
- *
- * TODO(paulberry): some informative information is currently missing from the
- * summary format.
  */
 const informative = null;
 
 /**
- * Annotation describing information which is not part of the public API to a
- * library; in other words, if this information (or any information it refers
- * to) changes, libraries outside this one are unaffected.
- *
- * TODO(paulberry): currently the summary format does not contain private
- * information.
- */
-const private = null;
-
-/**
  * Annotation describing a class which can be the top level object in an
  * encoded summary.
  */
@@ -97,6 +85,7 @@
    * generic class, then the type arguments in [typeArguments] are applied
    * first to the class and then to the method.
    */
+  @Id(4)
   List<int> get implicitFunctionTypeIndices;
 
   /**
@@ -118,12 +107,14 @@
    * If the type being referred to is not a type parameter, [paramReference] is
    * zero.
    */
+  @Id(3)
   int get paramReference;
 
   /**
    * Index into [UnlinkedUnit.references] for the entity being referred to, or
    * zero if this is a reference to a type parameter.
    */
+  @Id(0)
   int get reference;
 
   /**
@@ -133,6 +124,7 @@
    *
    * Otherwise zero.
    */
+  @Id(2)
   int get slot;
 
   /**
@@ -140,6 +132,7 @@
    * type arguments used to instantiate it.  Trailing type arguments of type
    * `dynamic` are omitted.
    */
+  @Id(1)
   List<EntityRef> get typeArguments;
 }
 
@@ -152,6 +145,7 @@
    * URI for the compilation units listed in the library's `part` declarations.
    * These URIs are relative to the importing library.
    */
+  @Id(1)
   List<String> get parts;
 
   /**
@@ -161,6 +155,7 @@
    * `d/e.dart`, the URI listed for `a.dart`'s dependency on `e.dart` will be
    * `b/d/e.dart`.
    */
+  @Id(0)
   String get uri;
 }
 
@@ -173,17 +168,20 @@
    * Index into [LinkedLibrary.dependencies] for the library in which the
    * entity is defined.
    */
+  @Id(0)
   int get dependency;
 
   /**
    * The kind of the entity being referred to.
    */
+  @Id(3)
   ReferenceKind get kind;
 
   /**
    * Name of the exported entity.  For an exported setter, this name includes
    * the trailing '='.
    */
+  @Id(1)
   String get name;
 
   /**
@@ -192,6 +190,7 @@
    * zero represents the defining compilation unit, and nonzero values
    * represent parts in the order of the corresponding `part` declarations.
    */
+  @Id(2)
   int get unit;
 }
 
@@ -219,6 +218,7 @@
    * anti-dependency (e.g. the result of type propagation or type inference
    * depends on the lack of a certain declaration in the library).
    */
+  @Id(0)
   List<LinkedDependency> get dependencies;
 
   /**
@@ -228,12 +228,14 @@
    *
    * Sorted by name.
    */
+  @Id(4)
   List<LinkedExportName> get exportNames;
 
   /**
    * For each import in [UnlinkedUnit.imports], an index into [dependencies]
    * of the library being imported.
    */
+  @Id(1)
   List<int> get importDependencies;
 
   /**
@@ -241,6 +243,7 @@
    * dependencies (that is, the number of libraries in the direct imports plus
    * the transitive closure of exports, plus the library itself).
    */
+  @Id(2)
   int get numPrelinkedDependencies;
 
   /**
@@ -249,6 +252,7 @@
    * followed by the summary of each part, in the order of the `part`
    * declarations in the defining compilation unit.
    */
+  @Id(3)
   List<LinkedUnit> get units;
 }
 
@@ -267,6 +271,7 @@
    * LinkedUnit.references[i].containingReference != 0, then
    * LinkedUnit.references[i].containingReference < i.
    */
+  @Id(5)
   int get containingReference;
 
   /**
@@ -276,12 +281,14 @@
    * Zero if this entity is contained within another entity (e.g. a class
    * member), or if [kind] is [ReferenceKind.prefix].
    */
+  @Id(1)
   int get dependency;
 
   /**
    * The kind of the entity being referred to.  For the pseudo-types `dynamic`
    * and `void`, the kind is [ReferenceKind.classOrEnum].
    */
+  @Id(2)
   ReferenceKind get kind;
 
   /**
@@ -289,12 +296,14 @@
    * name of the entity being referred to.  For the pseudo-type `dynamic`, the
    * string is "dynamic".  For the pseudo-type `void`, the string is "void".
    */
+  @Id(3)
   String get name;
 
   /**
    * If the entity being referred to is generic, the number of type parameters
    * it accepts.  Otherwise zero.
    */
+  @Id(4)
   int get numTypeParameters;
 
   /**
@@ -306,6 +315,7 @@
    * Zero if this entity is contained within another entity (e.g. a class
    * member).
    */
+  @Id(0)
   int get unit;
 }
 
@@ -321,12 +331,14 @@
    * additional elements are references that are only referred to implicitly
    * (e.g. elements involved in inferred or propagated types).
    */
+  @Id(0)
   List<LinkedReference> get references;
 
   /**
    * List associating slot ids found inside the unlinked summary for the
    * compilation unit with propagated and inferred types.
    */
+  @Id(1)
   List<EntityRef> get types;
 }
 
@@ -399,21 +411,25 @@
   /**
    * Linked libraries.
    */
+  @Id(0)
   List<LinkedLibrary> get linkedLibraries;
 
   /**
    * The list of URIs of items in [linkedLibraries], e.g. `dart:core`.
    */
+  @Id(1)
   List<String> get linkedLibraryUris;
 
   /**
    * Unlinked information for the compilation units constituting the SDK.
    */
+  @Id(2)
   List<UnlinkedUnit> get unlinkedUnits;
 
   /**
    * The list of URIs of items in [unlinkedUnits], e.g. `dart:core/bool.dart`.
    */
+  @Id(3)
   List<String> get unlinkedUnitUris;
 }
 
@@ -424,6 +440,7 @@
   /**
    * Annotations for this class.
    */
+  @Id(5)
   List<UnlinkedConst> get annotations;
 
   /**
@@ -431,53 +448,63 @@
    * documentation comment.
    */
   @informative
+  @Id(6)
   UnlinkedDocumentationComment get documentationComment;
 
   /**
    * Executable objects (methods, getters, and setters) contained in the class.
    */
+  @Id(2)
   List<UnlinkedExecutable> get executables;
 
   /**
    * Field declarations contained in the class.
    */
+  @Id(4)
   List<UnlinkedVariable> get fields;
 
   /**
    * Indicates whether this class is the core "Object" class (and hence has no
    * supertype)
    */
+  @Id(12)
   bool get hasNoSupertype;
 
   /**
    * Interfaces appearing in an `implements` clause, if any.
    */
+  @Id(7)
   List<EntityRef> get interfaces;
 
   /**
    * Indicates whether the class is declared with the `abstract` keyword.
    */
+  @Id(8)
   bool get isAbstract;
 
   /**
    * Indicates whether the class is declared using mixin application syntax.
    */
+  @Id(11)
   bool get isMixinApplication;
 
   /**
    * Mixins appearing in a `with` clause, if any.
    */
+  @Id(10)
   List<EntityRef> get mixins;
 
   /**
    * Name of the class.
    */
+  @Id(0)
   String get name;
 
   /**
    * Offset of the class name relative to the beginning of the file.
    */
   @informative
+  @Id(1)
   int get nameOffset;
 
   /**
@@ -485,11 +512,13 @@
    * explicitly declare a supertype (and hence has supertype `Object`), or (b)
    * the class *is* `Object` (and hence has no supertype).
    */
+  @Id(3)
   EntityRef get supertype;
 
   /**
    * Type parameters of the class, if any.
    */
+  @Id(9)
   List<UnlinkedTypeParam> get typeParameters;
 }
 
@@ -501,11 +530,13 @@
   /**
    * List of names which are hidden.  Empty if this is a `show` combinator.
    */
+  @Id(1)
   List<String> get hides;
 
   /**
    * List of names which are shown.  Empty if this is a `hide` combinator.
    */
+  @Id(0)
   List<String> get shows;
 }
 
@@ -523,6 +554,7 @@
   /**
    * Sequence of 64-bit doubles consumed by the operation `pushDouble`.
    */
+  @Id(4)
   List<double> get doubles;
 
   /**
@@ -530,18 +562,21 @@
    * `pushArgument`, `pushInt`, `shiftOr`, `concatenate`, `invokeConstructor`,
    * `makeList`, and `makeMap`.
    */
+  @Id(1)
   List<int> get ints;
 
   /**
    * Indicates whether the expression is not a valid potentially constant
    * expression.
    */
+  @Id(5)
   bool get isInvalid;
 
   /**
    * Sequence of operations to execute (starting with an empty stack) to form
    * the constant value.
    */
+  @Id(0)
   List<UnlinkedConstOperation> get operations;
 
   /**
@@ -550,12 +585,14 @@
    * that in the case of `pushReference` (and sometimes `invokeConstructor` the
    * actual entity being referred to may be something other than a type.
    */
+  @Id(2)
   List<EntityRef> get references;
 
   /**
    * Sequence of strings consumed by the operations `pushString` and
    * `invokeConstructor`.
    */
+  @Id(3)
   List<String> get strings;
 }
 
@@ -857,17 +894,20 @@
    * If [kind] is `thisInvocation` or `superInvocation`, the arguments of the
    * invocation.  Otherwise empty.
    */
+  @Id(3)
   List<UnlinkedConst> get arguments;
 
   /**
    * If [kind] is `field`, the expression of the field initializer.
    * Otherwise `null`.
    */
+  @Id(1)
   UnlinkedConst get expression;
 
   /**
    * The kind of the constructor initializer (field, redirect, super).
    */
+  @Id(2)
   UnlinkedConstructorInitializerKind get kind;
 
   /**
@@ -876,6 +916,7 @@
    * class, to redirect to.  If [kind] is `superInvocation`, the name of the
    * constructor, declared in the superclass, to invoke.
    */
+  @Id(0)
   String get name;
 }
 
@@ -906,12 +947,14 @@
   /**
    * Length of the documentation comment (prior to replacing '\r\n' with '\n').
    */
+  @Id(0)
   int get length;
 
   /**
    * Offset of the beginning of the documentation comment relative to the
    * beginning of the file.
    */
+  @Id(2)
   int get offset;
 
   /**
@@ -920,6 +963,7 @@
    * References appearing within the doc comment in square brackets are not
    * specially encoded.
    */
+  @Id(1)
   String get text;
 }
 
@@ -930,6 +974,7 @@
   /**
    * Annotations for this enum.
    */
+  @Id(4)
   List<UnlinkedConst> get annotations;
 
   /**
@@ -937,22 +982,26 @@
    * comment.
    */
   @informative
+  @Id(3)
   UnlinkedDocumentationComment get documentationComment;
 
   /**
    * Name of the enum type.
    */
+  @Id(0)
   String get name;
 
   /**
    * Offset of the enum name relative to the beginning of the file.
    */
   @informative
+  @Id(1)
   int get nameOffset;
 
   /**
    * Values listed in the enum declaration, in declaration order.
    */
+  @Id(2)
   List<UnlinkedEnumValue> get values;
 }
 
@@ -966,17 +1015,20 @@
    * documentation comment.
    */
   @informative
+  @Id(2)
   UnlinkedDocumentationComment get documentationComment;
 
   /**
    * Name of the enumerated value.
    */
+  @Id(0)
   String get name;
 
   /**
    * Offset of the enum value name relative to the beginning of the file.
    */
   @informative
+  @Id(1)
   int get nameOffset;
 }
 
@@ -988,12 +1040,14 @@
   /**
    * Annotations for this executable.
    */
+  @Id(6)
   List<UnlinkedConst> get annotations;
 
   /**
    * If a constant [UnlinkedExecutableKind.constructor], the constructor
    * initializers.  Otherwise empty.
    */
+  @Id(14)
   List<UnlinkedConstructorInitializer> get constantInitializers;
 
   /**
@@ -1001,6 +1055,7 @@
    * documentation comment.
    */
   @informative
+  @Id(7)
   UnlinkedDocumentationComment get documentationComment;
 
   /**
@@ -1010,48 +1065,74 @@
    * no return type was inferred for this variable, so its static type is
    * `dynamic`.
    */
+  @Id(5)
   int get inferredReturnTypeSlot;
 
   /**
    * Indicates whether the executable is declared using the `abstract` keyword.
    */
+  @Id(10)
   bool get isAbstract;
 
   /**
    * Indicates whether the executable is declared using the `const` keyword.
    */
+  @Id(12)
   bool get isConst;
 
   /**
    * Indicates whether the executable is declared using the `external` keyword.
    */
+  @Id(11)
   bool get isExternal;
 
   /**
    * Indicates whether the executable is declared using the `factory` keyword.
    */
+  @Id(8)
   bool get isFactory;
 
   /**
+   * Indicates whether the executable is a redirected constructor.
+   */
+  @Id(13)
+  bool get isRedirectedConstructor;
+
+  /**
    * 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).
    */
+  @Id(9)
   bool get isStatic;
 
   /**
    * The kind of the executable (function/method, getter, setter, or
    * constructor).
    */
+  @Id(4)
   UnlinkedExecutableKind get kind;
 
   /**
+   * The list of local functions.
+   */
+  @Id(18)
+  List<UnlinkedExecutable> get localFunctions;
+
+  /**
+   * The list of local variables.
+   */
+  @Id(19)
+  List<UnlinkedVariable> get localVariables;
+
+  /**
    * 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.
    */
+  @Id(1)
   String get name;
 
   /**
@@ -1061,6 +1142,7 @@
    * offset of the second "C" in "class C { C(); }").
    */
   @informative
+  @Id(0)
   int get nameOffset;
 
   /**
@@ -1068,19 +1150,49 @@
    * parameters (hence this will be the empty list), and setters have a single
    * parameter.
    */
+  @Id(2)
   List<UnlinkedParam> get parameters;
 
   /**
+   * If [isRedirectedConstructor] and [isFactory] are both `true`, the
+   * constructor to which this constructor redirects; otherwise empty.
+   */
+  @Id(15)
+  EntityRef get redirectedConstructor;
+
+  /**
+   * If [isRedirectedConstructor] is `true` and [isFactory] is `false`, the
+   * name of the constructor that this constructor redirects to; otherwise
+   * empty.
+   */
+  @Id(17)
+  String get redirectedConstructorName;
+
+  /**
    * Declared return type of the executable.  Absent if the executable is a
    * constructor or the return type is implicit.
    */
+  @Id(3)
   EntityRef get returnType;
 
   /**
    * Type parameters of the executable, if any.  Empty if support for generic
    * method syntax is disabled.
    */
+  @Id(16)
   List<UnlinkedTypeParam> get typeParameters;
+
+  /**
+   * If a local function, the length of the visible range; zero otherwise.
+   */
+  @Id(20)
+  int get visibleLength;
+
+  /**
+   * If a local function, the beginning of the visible range; zero otherwise.
+   */
+  @Id(21)
+  int get visibleOffset;
 }
 
 /**
@@ -1116,12 +1228,14 @@
   /**
    * Annotations for this export directive.
    */
+  @Id(3)
   List<UnlinkedConst> get annotations;
 
   /**
    * Offset of the "export" keyword.
    */
   @informative
+  @Id(0)
   int get offset;
 
   /**
@@ -1129,6 +1243,7 @@
    * file.
    */
   @informative
+  @Id(1)
   int get uriEnd;
 
   /**
@@ -1136,6 +1251,7 @@
    * the file.
    */
   @informative
+  @Id(2)
   int get uriOffset;
 }
 
@@ -1147,11 +1263,13 @@
   /**
    * Combinators contained in this import declaration.
    */
+  @Id(1)
   List<UnlinkedCombinator> get combinators;
 
   /**
    * URI used in the source code to reference the exported library.
    */
+  @Id(0)
   String get uri;
 }
 
@@ -1162,21 +1280,25 @@
   /**
    * Annotations for this import declaration.
    */
+  @Id(8)
   List<UnlinkedConst> get annotations;
 
   /**
    * Combinators contained in this import declaration.
    */
+  @Id(4)
   List<UnlinkedCombinator> get combinators;
 
   /**
    * Indicates whether the import declaration uses the `deferred` keyword.
    */
+  @Id(9)
   bool get isDeferred;
 
   /**
    * Indicates whether the import declaration is implicit.
    */
+  @Id(5)
   bool get isImplicit;
 
   /**
@@ -1184,6 +1306,7 @@
    * is true, zero.
    */
   @informative
+  @Id(0)
   int get offset;
 
   /**
@@ -1191,6 +1314,7 @@
    * if there is no prefix.
    */
   @informative
+  @Id(6)
   int get prefixOffset;
 
   /**
@@ -1199,11 +1323,13 @@
    *
    * Note that multiple imports can declare the same prefix.
    */
+  @Id(7)
   int get prefixReference;
 
   /**
    * URI used in the source code to reference the imported library.
    */
+  @Id(1)
   String get uri;
 
   /**
@@ -1211,6 +1337,7 @@
    * file.  If [isImplicit] is true, zero.
    */
   @informative
+  @Id(2)
   int get uriEnd;
 
   /**
@@ -1218,6 +1345,7 @@
    * the file.  If [isImplicit] is true, zero.
    */
   @informative
+  @Id(3)
   int get uriOffset;
 }
 
@@ -1228,6 +1356,7 @@
   /**
    * Annotations for this parameter.
    */
+  @Id(9)
   List<UnlinkedConst> get annotations;
 
   /**
@@ -1235,6 +1364,7 @@
    * default value.  Note that the presence of this expression does not mean
    * that it is a valid, check [UnlinkedConst.isInvalid].
    */
+  @Id(7)
   UnlinkedConst get defaultValue;
 
   /**
@@ -1248,38 +1378,45 @@
    * not specified, they always inherit the static type of the corresponding
    * field.
    */
+  @Id(2)
   int get inferredTypeSlot;
 
   /**
    * Indicates whether this is a function-typed parameter.
    */
+  @Id(5)
   bool get isFunctionTyped;
 
   /**
    * Indicates whether this is an initializing formal parameter (i.e. it is
    * declared using `this.` syntax).
    */
+  @Id(6)
   bool get isInitializingFormal;
 
   /**
    * Kind of the parameter.
    */
+  @Id(4)
   UnlinkedParamKind get kind;
 
   /**
    * Name of the parameter.
    */
+  @Id(0)
   String get name;
 
   /**
    * Offset of the parameter name relative to the beginning of the file.
    */
   @informative
+  @Id(1)
   int get nameOffset;
 
   /**
    * If [isFunctionTyped] is `true`, the parameters of the function type.
    */
+  @Id(8)
   List<UnlinkedParam> get parameters;
 
   /**
@@ -1287,7 +1424,20 @@
    * [isFunctionTyped] is `false`, the declared type.  Absent if the type is
    * implicit.
    */
+  @Id(3)
   EntityRef get type;
+
+  /**
+   * The length of the visible range.
+   */
+  @Id(10)
+  int get visibleLength;
+
+  /**
+   * The beginning of the visible range.
+   */
+  @Id(11)
+  int get visibleOffset;
 }
 
 /**
@@ -1317,6 +1467,7 @@
   /**
    * Annotations for this part declaration.
    */
+  @Id(2)
   List<UnlinkedConst> get annotations;
 
   /**
@@ -1324,6 +1475,7 @@
    * file.
    */
   @informative
+  @Id(0)
   int get uriEnd;
 
   /**
@@ -1331,6 +1483,7 @@
    * the file.
    */
   @informative
+  @Id(1)
   int get uriOffset;
 }
 
@@ -1344,26 +1497,33 @@
  */
 abstract class UnlinkedPublicName extends base.SummaryClass {
   /**
-   * If this [UnlinkedPublicName] is a class, the list of members which can be
-   * referenced from constants - static constant fields, static methods, and
-   * constructors.  Otherwise empty.
-   */
-  List<UnlinkedPublicName> get constMembers;
-
-  /**
    * The kind of object referred to by the name.
    */
+  @Id(1)
   ReferenceKind get kind;
 
   /**
+   * If this [UnlinkedPublicName] is a class, the list of members which can be
+   * referenced from constants or factory redirects - static constant fields,
+   * static methods, and constructors.  Otherwise empty.
+   *
+   * Unnamed constructors are not included since they do not constitute a
+   * separate name added to any namespace.
+   */
+  @Id(2)
+  List<UnlinkedPublicName> get members;
+
+  /**
    * The name itself.
    */
+  @Id(0)
   String get name;
 
   /**
    * If the entity being referred to is generic, the number of type parameters
    * it accepts.  Otherwise zero.
    */
+  @Id(3)
   int get numTypeParameters;
 }
 
@@ -1380,6 +1540,7 @@
   /**
    * Export declarations in the compilation unit.
    */
+  @Id(2)
   List<UnlinkedExportPublic> get exports;
 
   /**
@@ -1388,11 +1549,13 @@
    * TODO(paulberry): consider sorting these names to reduce unnecessary
    * relinking.
    */
+  @Id(0)
   List<UnlinkedPublicName> get names;
 
   /**
    * URIs referenced by part declarations in the compilation unit.
    */
+  @Id(1)
   List<String> get parts;
 }
 
@@ -1405,6 +1568,7 @@
    * Name of the entity being referred to.  For the pseudo-type `dynamic`, the
    * string is "dynamic".  For the pseudo-type `void`, the string is "void".
    */
+  @Id(0)
   String get name;
 
   /**
@@ -1415,6 +1579,7 @@
    * UnlinkedUnit.references[i].prefixReference != 0, then
    * UnlinkedUnit.references[i].prefixReference < i.
    */
+  @Id(1)
   int get prefixReference;
 }
 
@@ -1425,6 +1590,7 @@
   /**
    * Annotations for this typedef.
    */
+  @Id(4)
   List<UnlinkedConst> get annotations;
 
   /**
@@ -1432,32 +1598,38 @@
    * documentation comment.
    */
   @informative
+  @Id(6)
   UnlinkedDocumentationComment get documentationComment;
 
   /**
    * Name of the typedef.
    */
+  @Id(0)
   String get name;
 
   /**
    * Offset of the typedef name relative to the beginning of the file.
    */
   @informative
+  @Id(1)
   int get nameOffset;
 
   /**
    * Parameters of the executable, if any.
    */
+  @Id(3)
   List<UnlinkedParam> get parameters;
 
   /**
    * Return type of the typedef.
    */
+  @Id(2)
   EntityRef get returnType;
 
   /**
    * Type parameters of the typedef, if any.
    */
+  @Id(5)
   List<UnlinkedTypeParam> get typeParameters;
 }
 
@@ -1468,23 +1640,27 @@
   /**
    * Annotations for this type parameter.
    */
+  @Id(3)
   List<UnlinkedConst> get annotations;
 
   /**
    * Bound of the type parameter, if a bound is explicitly declared.  Otherwise
    * null.
    */
+  @Id(2)
   EntityRef get bound;
 
   /**
    * Name of the type parameter.
    */
+  @Id(0)
   String get name;
 
   /**
    * Offset of the type parameter name relative to the beginning of the file.
    */
   @informative
+  @Id(1)
   int get nameOffset;
 }
 
@@ -1499,33 +1675,39 @@
   /**
    * Classes declared in the compilation unit.
    */
+  @Id(2)
   List<UnlinkedClass> get classes;
 
   /**
    * Enums declared in the compilation unit.
    */
+  @Id(12)
   List<UnlinkedEnum> get enums;
 
   /**
    * Top level executable objects (functions, getters, and setters) declared in
    * the compilation unit.
    */
+  @Id(4)
   List<UnlinkedExecutable> get executables;
 
   /**
    * Export declarations in the compilation unit.
    */
+  @Id(13)
   List<UnlinkedExportNonPublic> get exports;
 
   /**
    * Import declarations in the compilation unit.
    */
+  @Id(5)
   List<UnlinkedImport> get imports;
 
   /**
    * Annotations for the library declaration, or the empty list if there is no
    * library declaration.
    */
+  @Id(14)
   List<UnlinkedConst> get libraryAnnotations;
 
   /**
@@ -1533,11 +1715,13 @@
    * documentation comment.
    */
   @informative
+  @Id(9)
   UnlinkedDocumentationComment get libraryDocumentationComment;
 
   /**
    * Name of the library (from a "library" declaration, if present).
    */
+  @Id(6)
   String get libraryName;
 
   /**
@@ -1545,6 +1729,7 @@
    * library has no name).
    */
   @informative
+  @Id(7)
   int get libraryNameLength;
 
   /**
@@ -1552,16 +1737,19 @@
    * the library has no name).
    */
   @informative
+  @Id(8)
   int get libraryNameOffset;
 
   /**
    * Part declarations in the compilation unit.
    */
+  @Id(11)
   List<UnlinkedPart> get parts;
 
   /**
    * Unlinked public namespace of this compilation unit.
    */
+  @Id(0)
   UnlinkedPublicNamespace get publicNamespace;
 
   /**
@@ -1571,16 +1759,19 @@
    * example [UnlinkedReference.prefixReference or
    * UnlinkedImport.prefixReference]).
    */
+  @Id(1)
   List<UnlinkedReference> get references;
 
   /**
    * Typedefs declared in the compilation unit.
    */
+  @Id(10)
   List<UnlinkedTypedef> get typedefs;
 
   /**
    * Top level variables declared in the compilation unit.
    */
+  @Id(3)
   List<UnlinkedVariable> get variables;
 }
 
@@ -1592,6 +1783,7 @@
   /**
    * Annotations for this variable.
    */
+  @Id(8)
   List<UnlinkedConst> get annotations;
 
   /**
@@ -1599,6 +1791,7 @@
    * expression in the initializer.  Note that the presence of this expression
    * does not mean that it is a valid, check [UnlinkedConst.isInvalid].
    */
+  @Id(5)
   UnlinkedConst get constExpr;
 
   /**
@@ -1606,6 +1799,7 @@
    * documentation comment.
    */
   @informative
+  @Id(10)
   UnlinkedDocumentationComment get documentationComment;
 
   /**
@@ -1614,16 +1808,19 @@
    * there is no matching entry in [LinkedLibrary.types], then no type was
    * inferred for this variable, so its static type is `dynamic`.
    */
+  @Id(9)
   int get inferredTypeSlot;
 
   /**
    * Indicates whether the variable is declared using the `const` keyword.
    */
+  @Id(6)
   bool get isConst;
 
   /**
    * Indicates whether the variable is declared using the `final` keyword.
    */
+  @Id(7)
   bool get isFinal;
 
   /**
@@ -1633,17 +1830,20 @@
    * declared using the `static` keyword (even though they are considered
    * static for semantic purposes).
    */
+  @Id(4)
   bool get isStatic;
 
   /**
    * Name of the variable.
    */
+  @Id(0)
   String get name;
 
   /**
    * Offset of the variable name relative to the beginning of the file.
    */
   @informative
+  @Id(1)
   int get nameOffset;
 
   /**
@@ -1654,10 +1854,24 @@
    *
    * Non-propagable variables have a [propagatedTypeSlot] of zero.
    */
+  @Id(2)
   int get propagatedTypeSlot;
 
   /**
    * Declared type of the variable.  Absent if the type is implicit.
    */
+  @Id(3)
   EntityRef get type;
+
+  /**
+   * If a local variable, the length of the visible range; zero otherwise.
+   */
+  @Id(11)
+  int get visibleLength;
+
+  /**
+   * If a local variable, the beginning of the visible range; zero otherwise.
+   */
+  @Id(12)
+  int get visibleOffset;
 }
diff --git a/pkg/analyzer/lib/src/summary/prelink.dart b/pkg/analyzer/lib/src/summary/prelink.dart
index 82ab7c5..688abe5 100644
--- a/pkg/analyzer/lib/src/summary/prelink.dart
+++ b/pkg/analyzer/lib/src/summary/prelink.dart
@@ -194,9 +194,9 @@
         aggregated.putIfAbsent(name.name, () {
           if (name.kind == ReferenceKind.classOrEnum) {
             Map<String, _Meaning> namespace = <String, _Meaning>{};
-            name.constMembers.forEach((executable) {
-              namespace[executable.name] = new _Meaning(unitNum,
-                  executable.kind, 0, executable.numTypeParameters);
+            name.members.forEach((executable) {
+              namespace[executable.name] = new _Meaning(
+                  unitNum, executable.kind, 0, executable.numTypeParameters);
             });
             return new _ClassMeaning(
                 unitNum, dependency, name.numTypeParameters, namespace);
@@ -267,15 +267,14 @@
         });
         cls.executables.forEach((executable) {
           ReferenceKind kind = null;
-          if (executable.kind == UnlinkedExecutableKind.constructor &&
-              executable.isConst) {
+          if (executable.kind == UnlinkedExecutableKind.constructor) {
             kind = ReferenceKind.constructor;
           } else if (executable.kind ==
                   UnlinkedExecutableKind.functionOrMethod &&
               executable.isStatic) {
             kind = ReferenceKind.method;
           }
-          if (kind != null) {
+          if (kind != null && executable.name.isNotEmpty) {
             namespace[executable.name] = new _Meaning(
                 unitNum, kind, 0, executable.typeParameters.length);
           }
@@ -424,6 +423,11 @@
             continue;
           }
         }
+        // Anything prefixed with 'unresolved' is unresolved.
+        if (references[reference.prefixReference].kind ==
+            ReferenceKind.unresolved) {
+          namespace = const <String, _Meaning>{};
+        }
         // Prefix references must always point to proper prefixes.
         assert(namespace != null);
       }
diff --git a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
index 4edd4cd..d6210db 100644
--- a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
+++ b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
@@ -71,7 +71,7 @@
           for (VariableDeclaration field in member.fields.variables) {
             String name = field.name.name;
             if (isPublic(name)) {
-              cls.constMembers.add(new UnlinkedPublicNameBuilder(
+              cls.members.add(new UnlinkedPublicNameBuilder(
                   name: name,
                   kind: ReferenceKind.propertyAccessor,
                   numTypeParameters: 0));
@@ -85,17 +85,18 @@
             !member.isOperator) {
           String name = member.name.name;
           if (isPublic(name)) {
-            cls.constMembers.add(new UnlinkedPublicNameBuilder(
+            cls.members.add(new UnlinkedPublicNameBuilder(
                 name: name,
                 kind: ReferenceKind.method,
                 numTypeParameters:
                     member.typeParameters?.typeParameters?.length ?? 0));
           }
         }
-        if (member is ConstructorDeclaration && member.constKeyword != null) {
-          String name = member.name != null ? member.name.name : '';
+        if (member is ConstructorDeclaration &&
+            member.name != null) {
+          String name = member.name.name;
           if (isPublic(name)) {
-            cls.constMembers.add(new UnlinkedPublicNameBuilder(
+            cls.members.add(new UnlinkedPublicNameBuilder(
                 name: name,
                 kind: ReferenceKind.constructor,
                 numTypeParameters: 0));
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 0a71496..de64232 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -7,6 +7,7 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
@@ -15,7 +16,6 @@
 import 'package:analyzer/src/generated/element_handle.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/testing/ast_factory.dart';
 import 'package:analyzer/src/generated/testing/token_factory.dart';
@@ -57,6 +57,14 @@
   final bool strongMode;
 
   /**
+   * Map of compilation units resynthesized from summaries.  The two map keys
+   * are the first two elements of the element's location (the library URI and
+   * the compilation unit URI).
+   */
+  final Map<String, Map<String, CompilationUnitElement>> _resynthesizedUnits =
+      <String, Map<String, CompilationUnitElement>>{};
+
+  /**
    * Map of top level elements resynthesized from summaries.  The three map
    * keys are the first three elements of the element's location (the library
    * URI, the compilation unit URI, and the name of the top level declaration).
@@ -101,6 +109,20 @@
     // Resynthesize locally.
     if (components.length == 1) {
       return getLibraryElement(libraryUri);
+    } else if (components.length == 2) {
+      Map<String, CompilationUnitElement> libraryMap =
+          _resynthesizedUnits[libraryUri];
+      if (libraryMap == null) {
+        getLibraryElement(libraryUri);
+        libraryMap = _resynthesizedUnits[libraryUri];
+        assert(libraryMap != null);
+      }
+      String unitUri = components[1];
+      CompilationUnitElement element = libraryMap[unitUri];
+      if (element == null) {
+        throw new Exception('Unit element not found in summary: $location');
+      }
+      return element;
     } else if (components.length == 3 || components.length == 4) {
       Map<String, Map<String, Element>> libraryMap =
           _resynthesizedElements[libraryUri];
@@ -169,7 +191,8 @@
       _LibraryResynthesizer libraryResynthesizer = new _LibraryResynthesizer(
           this, serializedLibrary, serializedUnits, librarySource);
       LibraryElement library = libraryResynthesizer.buildLibrary();
-      _resynthesizedElements[uri] = libraryResynthesizer.resummarizedElements;
+      _resynthesizedUnits[uri] = libraryResynthesizer.resynthesizedUnits;
+      _resynthesizedElements[uri] = libraryResynthesizer.resynthesizedElements;
       return library;
     });
   }
@@ -416,13 +439,9 @@
         case UnlinkedConstOperation.pushReference:
           EntityRef ref = uc.references[refPtr++];
           _ReferenceInfo info = resynthesizer.referenceInfos[ref.reference];
-          if (info.element != null) {
-            SimpleIdentifier node = AstFactory.identifier3(info.name);
-            node.staticElement = info.element;
-            _push(node);
-          } else {
-            throw new StateError('Unsupported reference ${ref.toMap()}');
-          }
+          SimpleIdentifier node = AstFactory.identifier3(info.name);
+          node.staticElement = info.element;
+          _push(node);
           break;
         case UnlinkedConstOperation.invokeConstructor:
           _pushInstanceCreation();
@@ -467,28 +486,6 @@
     throw new StateError('Unsupported type $type');
   }
 
-  /**
-   * Return the [ConstructorElement] by applying [typeArgumentRefs] to the
-   * given linked [info].  Both cases when [info] is a [ClassElement] and
-   * [ConstructorElement] are supported.
-   */
-  _DeferredConstructorElement _createConstructorElement(
-      _ReferenceInfo info, List<EntityRef> typeArgumentRefs) {
-    bool isClass = info.element is ClassElement;
-    _ReferenceInfo classInfo = isClass ? info : info.enclosing;
-    List<DartType> typeArguments =
-        typeArgumentRefs.map(resynthesizer.buildType).toList();
-    InterfaceType classType = classInfo.buildType((i) {
-      if (i < typeArguments.length) {
-        return typeArguments[i];
-      } else {
-        return DynamicTypeImpl.instance;
-      }
-    }, const <int>[]);
-    String name = isClass ? '' : info.name;
-    return new _DeferredConstructorElement(classType, name);
-  }
-
   InterpolationElement _newInterpolationElement(Expression expr) {
     if (expr is SimpleStringLiteral) {
       return new InterpolationString(expr.literal, expr.value);
@@ -526,17 +523,51 @@
     EntityRef ref = uc.references[refPtr++];
     _ReferenceInfo info = resynthesizer.referenceInfos[ref.reference];
     // prepare ConstructorElement
+    TypeName typeNode;
     String constructorName;
-    if (info.element is ConstructorElement) {
-      constructorName = info.name;
-    } else if (info.element is ClassElement) {
-      constructorName = null;
+    ConstructorElement constructorElement;
+    if (info.element != null) {
+      if (info.element is ConstructorElement) {
+        constructorName = info.name;
+      } else if (info.element is ClassElement) {
+        constructorName = null;
+      } else {
+        throw new StateError('Unsupported element for invokeConstructor '
+            '${info.element?.runtimeType}');
+      }
+      InterfaceType definingType =
+          resynthesizer._createConstructorDefiningType(info, ref.typeArguments);
+      constructorElement =
+          resynthesizer._createConstructorElement(definingType, info);
+      typeNode = _buildTypeAst(definingType);
     } else {
-      throw new StateError('Unsupported element for invokeConstructor '
-          '${info.element?.runtimeType}');
+      if (info.enclosing != null) {
+        if (info.enclosing.enclosing != null) {
+          PrefixedIdentifier typeName = AstFactory.identifier5(
+              info.enclosing.enclosing.name, info.enclosing.name);
+          typeName.prefix.staticElement = info.enclosing.enclosing.element;
+          typeName.identifier.staticElement = info.enclosing.element;
+          typeName.identifier.staticType = info.enclosing.type;
+          typeNode = AstFactory.typeName3(typeName);
+          typeNode.type = info.enclosing.type;
+          constructorName = info.name;
+        } else if (info.enclosing.element != null) {
+          SimpleIdentifier typeName =
+              AstFactory.identifier3(info.enclosing.name);
+          typeName.staticElement = info.enclosing.element;
+          typeName.staticType = info.enclosing.type;
+          typeNode = AstFactory.typeName3(typeName);
+          typeNode.type = info.enclosing.type;
+          constructorName = info.name;
+        } else {
+          typeNode = AstFactory.typeName3(
+              AstFactory.identifier5(info.enclosing.name, info.name));
+          constructorName = null;
+        }
+      } else {
+        typeNode = AstFactory.typeName4(info.name);
+      }
     }
-    _DeferredConstructorElement constructorElement =
-        _createConstructorElement(info, ref.typeArguments);
     // prepare arguments
     List<Expression> arguments;
     {
@@ -551,8 +582,6 @@
         arguments[index] = AstFactory.namedExpression2(name, arguments[index]);
       }
     }
-    // create TypeName
-    TypeName typeNode = _buildTypeAst(constructorElement.definingType);
     // create ConstructorName
     ConstructorName constructorNode;
     if (constructorName != null) {
@@ -606,11 +635,20 @@
 /**
  * The constructor element that has been resynthesized from a summary.  The
  * actual element won't be constructed until it is requested.  But properties
- * [definingType], [displayName], [enclosingElement] and [name] can be used
- * without creating the actual element.
+ * [displayName], [enclosingElement] and [name] can be used without creating
+ * the actual element.
  */
 class _DeferredConstructorElement extends ConstructorElementHandle {
-  final InterfaceType definingType;
+  /**
+   * The type defining this constructor element.  If [_isMember] is `false`,
+   * then the type parameters of [_definingType] are not guaranteed to be
+   * valid.
+   */
+  final InterfaceType _definingType;
+
+  /**
+   * The constructor name.
+   */
   final String name;
 
   factory _DeferredConstructorElement(InterfaceType definingType, String name) {
@@ -621,24 +659,21 @@
   }
 
   _DeferredConstructorElement._(
-      this.definingType, this.name, ElementLocation location)
+      this._definingType, this.name, ElementLocation location)
       : super(null, location);
 
   @override
-  Element get actualElement {
-    ConstructorElement element = enclosingElement.getNamedConstructor(name);
-    return new ConstructorMember(element, definingType);
-  }
+  Element get actualElement => enclosingElement.getNamedConstructor(name);
 
   @override
-  AnalysisContext get context => definingType.element.context;
+  AnalysisContext get context => _definingType.element.context;
 
   @override
   String get displayName => name;
 
   @override
   ClassElement get enclosingElement {
-    return definingType.element;
+    return _definingType.element;
   }
 }
 
@@ -714,23 +749,32 @@
   ConstructorElementImpl currentConstructor;
 
   /**
+   * Map of compilation unit elements that have been resynthesized so far.  The
+   * key is the URI of the compilation unit.
+   */
+  final Map<String, CompilationUnitElement> resynthesizedUnits =
+      <String, CompilationUnitElement>{};
+
+  /**
    * Map of top level elements that have been resynthesized so far.  The first
    * key is the URI of the compilation unit; the second is the name of the top
    * level element.
    */
-  final Map<String, Map<String, Element>> resummarizedElements =
+  final Map<String, Map<String, Element>> resynthesizedElements =
       <String, Map<String, Element>>{};
 
   /**
    * Type parameters for the generic class, typedef, or executable currently
-   * being resynthesized, if any.  If multiple entities with type parameters
-   * are nested (e.g. a generic executable inside a generic class), this is the
-   * concatenation of all type parameters from all declarations currently in
-   * force, with the outermost declaration appearing first.  If there are no
-   * type parameters, or we are not currently resynthesizing a class, typedef,
-   * or executable, then this is an empty list.
+   * being resynthesized, if any.  This is a list of lists; if multiple
+   * entities with type parameters are nested (e.g. a generic executable inside
+   * a generic class), then the zeroth element of [currentTypeParameters]
+   * contains the type parameters for the outermost nested entity, and further
+   * elements contain the type parameters for entities that are more deeply
+   * nested.  If we are not currently resynthesizing a class, typedef, or
+   * executable, then this is an empty list.
    */
-  List<TypeParameterElement> currentTypeParameters = <TypeParameterElement>[];
+  final List<List<TypeParameterElement>> currentTypeParameters =
+      <List<TypeParameterElement>>[];
 
   /**
    * If a class is currently being resynthesized, map from field name to the
@@ -758,13 +802,6 @@
   }
 
   /**
-   * Return a list of type arguments corresponding to [currentTypeParameters].
-   */
-  List<TypeParameterType> get currentTypeArguments => currentTypeParameters
-      ?.map((TypeParameterElement param) => param.type)
-      ?.toList();
-
-  /**
    * Build the annotations for the given [element].
    */
   void buildAnnotations(
@@ -802,80 +839,78 @@
    * Resynthesize a [ClassElement] and place it in [unitHolder].
    */
   void buildClass(UnlinkedClass serializedClass) {
-    try {
-      currentTypeParameters =
-          serializedClass.typeParameters.map(buildTypeParameter).toList();
-      for (int i = 0; i < serializedClass.typeParameters.length; i++) {
-        finishTypeParameter(
-            serializedClass.typeParameters[i], currentTypeParameters[i]);
+    ClassElementImpl classElement =
+        new ClassElementImpl(serializedClass.name, serializedClass.nameOffset);
+    classElement.typeParameters =
+        buildTypeParameters(serializedClass.typeParameters);
+    classElement.abstract = serializedClass.isAbstract;
+    classElement.mixinApplication = serializedClass.isMixinApplication;
+    InterfaceTypeImpl correspondingType = new InterfaceTypeImpl(classElement);
+    if (serializedClass.supertype != null) {
+      classElement.supertype = buildType(serializedClass.supertype);
+    } else if (!serializedClass.hasNoSupertype) {
+      if (isCoreLibrary) {
+        delayedObjectSubclasses.add(classElement);
+      } else {
+        classElement.supertype = summaryResynthesizer.typeProvider.objectType;
       }
-      ClassElementImpl classElement = new ClassElementImpl(
-          serializedClass.name, serializedClass.nameOffset);
-      classElement.abstract = serializedClass.isAbstract;
-      classElement.mixinApplication = serializedClass.isMixinApplication;
-      InterfaceTypeImpl correspondingType = new InterfaceTypeImpl(classElement);
-      if (serializedClass.supertype != null) {
-        classElement.supertype = buildType(serializedClass.supertype);
-      } else if (!serializedClass.hasNoSupertype) {
-        if (isCoreLibrary) {
-          delayedObjectSubclasses.add(classElement);
-        } else {
-          classElement.supertype = summaryResynthesizer.typeProvider.objectType;
-        }
-      }
-      classElement.interfaces =
-          serializedClass.interfaces.map(buildType).toList();
-      classElement.mixins = serializedClass.mixins.map(buildType).toList();
-      classElement.typeParameters = currentTypeParameters;
-      ElementHolder memberHolder = new ElementHolder();
-      fields = <String, FieldElementImpl>{};
-      for (UnlinkedVariable serializedVariable in serializedClass.fields) {
-        buildVariable(serializedVariable, memberHolder);
-      }
-      bool constructorFound = false;
-      constructors = <String, ConstructorElementImpl>{};
-      for (UnlinkedExecutable serializedExecutable
-          in serializedClass.executables) {
-        switch (serializedExecutable.kind) {
-          case UnlinkedExecutableKind.constructor:
-            constructorFound = true;
-            buildConstructor(
-                serializedExecutable, memberHolder, correspondingType);
-            break;
-          case UnlinkedExecutableKind.functionOrMethod:
-          case UnlinkedExecutableKind.getter:
-          case UnlinkedExecutableKind.setter:
-            buildExecutable(serializedExecutable, memberHolder);
-            break;
-        }
-      }
-      if (!serializedClass.isMixinApplication) {
-        if (!constructorFound) {
-          // Synthesize implicit constructors.
-          ConstructorElementImpl constructor =
-              new ConstructorElementImpl('', -1);
-          constructor.synthetic = true;
-          constructor.returnType = correspondingType;
-          constructor.type = new FunctionTypeImpl.elementWithNameAndArgs(
-              constructor, null, currentTypeArguments, false);
-          memberHolder.addConstructor(constructor);
-        }
-        classElement.constructors = memberHolder.constructors;
-      }
-      classElement.accessors = memberHolder.accessors;
-      classElement.fields = memberHolder.fields;
-      classElement.methods = memberHolder.methods;
-      correspondingType.typeArguments = currentTypeArguments;
-      classElement.type = correspondingType;
-      buildDocumentation(classElement, serializedClass.documentationComment);
-      buildAnnotations(classElement, serializedClass.annotations);
-      resolveConstructorInitializers(classElement);
-      unitHolder.addType(classElement);
-    } finally {
-      currentTypeParameters = <TypeParameterElement>[];
-      fields = null;
-      constructors = null;
     }
+    classElement.interfaces =
+        serializedClass.interfaces.map(buildType).toList();
+    classElement.mixins = serializedClass.mixins.map(buildType).toList();
+    ElementHolder memberHolder = new ElementHolder();
+    fields = <String, FieldElementImpl>{};
+    for (UnlinkedVariable serializedVariable in serializedClass.fields) {
+      buildVariable(serializedVariable, memberHolder);
+    }
+    bool constructorFound = false;
+    constructors = <String, ConstructorElementImpl>{};
+    for (UnlinkedExecutable serializedExecutable
+        in serializedClass.executables) {
+      switch (serializedExecutable.kind) {
+        case UnlinkedExecutableKind.constructor:
+          constructorFound = true;
+          buildConstructor(
+              serializedExecutable, memberHolder, correspondingType);
+          break;
+        case UnlinkedExecutableKind.functionOrMethod:
+        case UnlinkedExecutableKind.getter:
+        case UnlinkedExecutableKind.setter:
+          if (serializedExecutable.isStatic) {
+            currentTypeParameters.removeLast();
+          }
+          buildExecutable(serializedExecutable, memberHolder);
+          if (serializedExecutable.isStatic) {
+            currentTypeParameters.add(classElement.typeParameters);
+          }
+          break;
+      }
+    }
+    if (!serializedClass.isMixinApplication) {
+      if (!constructorFound) {
+        // Synthesize implicit constructors.
+        ConstructorElementImpl constructor = new ConstructorElementImpl('', -1);
+        constructor.synthetic = true;
+        constructor.returnType = correspondingType;
+        constructor.type = new FunctionTypeImpl.elementWithNameAndArgs(
+            constructor, null, getCurrentTypeArguments(), false);
+        memberHolder.addConstructor(constructor);
+      }
+      classElement.constructors = memberHolder.constructors;
+    }
+    classElement.accessors = memberHolder.accessors;
+    classElement.fields = memberHolder.fields;
+    classElement.methods = memberHolder.methods;
+    correspondingType.typeArguments = getCurrentTypeArguments();
+    classElement.type = correspondingType;
+    buildDocumentation(classElement, serializedClass.documentationComment);
+    buildAnnotations(classElement, serializedClass.annotations);
+    resolveConstructorInitializers(classElement);
+    unitHolder.addType(classElement);
+    currentTypeParameters.removeLast();
+    assert(currentTypeParameters.isEmpty);
+    fields = null;
+    constructors = null;
   }
 
   /**
@@ -939,6 +974,26 @@
         .constantInitializers
         .map(buildConstantInitializer)
         .toList();
+    if (serializedExecutable.isRedirectedConstructor) {
+      if (serializedExecutable.isFactory) {
+        EntityRef redirectedConstructor =
+            serializedExecutable.redirectedConstructor;
+        _ReferenceInfo info = referenceInfos[redirectedConstructor.reference];
+        List<EntityRef> typeArguments = redirectedConstructor.typeArguments;
+        currentConstructor.redirectedConstructor = _createConstructorElement(
+            _createConstructorDefiningType(info, typeArguments), info);
+      } else {
+        List<String> locationComponents =
+            currentCompilationUnit.location.components.toList();
+        locationComponents.add(classType.name);
+        locationComponents.add(serializedExecutable.redirectedConstructorName);
+        currentConstructor.redirectedConstructor =
+            new _DeferredConstructorElement._(
+                classType,
+                serializedExecutable.redirectedConstructorName,
+                new ElementLocationImpl.con3(locationComponents));
+      }
+    }
     holder.addConstructor(currentConstructor);
     currentConstructor = null;
   }
@@ -988,6 +1043,7 @@
     for (UnlinkedEnumValue serializedEnumValue in serializedEnum.values) {
       ConstFieldElementImpl valueField = new ConstFieldElementImpl(
           serializedEnumValue.name, serializedEnumValue.nameOffset);
+      buildDocumentation(valueField, serializedEnumValue.documentationComment);
       valueField.const3 = true;
       valueField.static = true;
       valueField.type = enumType;
@@ -1052,9 +1108,6 @@
           type = executableElement.parameters[0].type;
         }
         holder.addAccessor(executableElement);
-        // TODO(paulberry): consider removing implicit variables from the
-        // element model; the spec doesn't call for them, and they cause
-        // trouble when getters/setters exist in different parts.
         PropertyInducingElementImpl implicitVariable;
         if (isTopLevel) {
           implicitVariable = buildImplicitTopLevelVariable(name, kind, holder);
@@ -1084,13 +1137,8 @@
    */
   void buildExecutableCommonParts(ExecutableElementImpl executableElement,
       UnlinkedExecutable serializedExecutable) {
-    List<TypeParameterType> oldTypeArguments = currentTypeArguments;
-    int oldTypeParametersLength = currentTypeParameters.length;
-    if (serializedExecutable.typeParameters.isNotEmpty) {
-      executableElement.typeParameters =
-          serializedExecutable.typeParameters.map(buildTypeParameter).toList();
-      currentTypeParameters.addAll(executableElement.typeParameters);
-    }
+    executableElement.typeParameters =
+        buildTypeParameters(serializedExecutable.typeParameters);
     executableElement.parameters =
         serializedExecutable.parameters.map(buildParameter).toList();
     if (serializedExecutable.kind == UnlinkedExecutableKind.constructor) {
@@ -1107,13 +1155,16 @@
           serializedExecutable.returnType == null;
     }
     executableElement.type = new FunctionTypeImpl.elementWithNameAndArgs(
-        executableElement, null, oldTypeArguments, false);
+        executableElement, null, getCurrentTypeArguments(skipLevels: 1), false);
     executableElement.external = serializedExecutable.isExternal;
-    currentTypeParameters.removeRange(
-        oldTypeParametersLength, currentTypeParameters.length);
     buildDocumentation(
         executableElement, serializedExecutable.documentationComment);
     buildAnnotations(executableElement, serializedExecutable.annotations);
+    executableElement.functions =
+        serializedExecutable.localFunctions.map(buildLocalFunction).toList();
+    executableElement.localVariables =
+        serializedExecutable.localVariables.map(buildLocalVariable).toList();
+    currentTypeParameters.removeLast();
   }
 
   /**
@@ -1412,36 +1463,78 @@
   }
 
   /**
+   * Resynthesize a local [FunctionElement].
+   */
+  FunctionElement buildLocalFunction(UnlinkedExecutable serializedExecutable) {
+    FunctionElementImpl element = new FunctionElementImpl(
+        serializedExecutable.name, serializedExecutable.nameOffset);
+    if (serializedExecutable.visibleOffset != 0) {
+      element.setVisibleRange(serializedExecutable.visibleOffset,
+          serializedExecutable.visibleLength);
+    }
+    buildExecutableCommonParts(element, serializedExecutable);
+    return element;
+  }
+
+  /**
+   * Resynthesize a [LocalVariableElement].
+   */
+  LocalVariableElement buildLocalVariable(UnlinkedVariable serializedVariable) {
+    LocalVariableElementImpl element;
+    if (serializedVariable.constExpr != null) {
+      ConstLocalVariableElementImpl constElement =
+          new ConstLocalVariableElementImpl(
+              serializedVariable.name, serializedVariable.nameOffset);
+      element = constElement;
+      constElement.constantInitializer =
+          _buildConstExpression(serializedVariable.constExpr);
+    } else {
+      element = new LocalVariableElementImpl(
+          serializedVariable.name, serializedVariable.nameOffset);
+    }
+    if (serializedVariable.visibleOffset != 0) {
+      element.setVisibleRange(
+          serializedVariable.visibleOffset, serializedVariable.visibleLength);
+    }
+    buildVariableCommonParts(element, serializedVariable);
+    return element;
+  }
+
+  /**
    * Resynthesize a [ParameterElement].
    */
   ParameterElement buildParameter(UnlinkedParam serializedParameter) {
     ParameterElementImpl parameterElement;
     if (serializedParameter.isInitializingFormal) {
       FieldFormalParameterElementImpl initializingParameter;
-      if (serializedParameter.defaultValue != null) {
+      if (serializedParameter.kind == UnlinkedParamKind.required) {
+        initializingParameter = new FieldFormalParameterElementImpl(
+            serializedParameter.name, serializedParameter.nameOffset);
+      } else {
         DefaultFieldFormalParameterElementImpl defaultParameter =
             new DefaultFieldFormalParameterElementImpl(
                 serializedParameter.name, serializedParameter.nameOffset);
         initializingParameter = defaultParameter;
-        defaultParameter.constantInitializer =
-            _buildConstExpression(serializedParameter.defaultValue);
-      } else {
-        initializingParameter = new FieldFormalParameterElementImpl(
-            serializedParameter.name, serializedParameter.nameOffset);
+        if (serializedParameter.defaultValue != null) {
+          defaultParameter.constantInitializer =
+              _buildConstExpression(serializedParameter.defaultValue);
+        }
       }
       parameterElement = initializingParameter;
       initializingParameter.field = fields[serializedParameter.name];
     } else {
-      if (serializedParameter.defaultValue != null) {
+      if (serializedParameter.kind == UnlinkedParamKind.required) {
+        parameterElement = new ParameterElementImpl(
+            serializedParameter.name, serializedParameter.nameOffset);
+      } else {
         DefaultParameterElementImpl defaultParameter =
             new DefaultParameterElementImpl(
                 serializedParameter.name, serializedParameter.nameOffset);
         parameterElement = defaultParameter;
-        defaultParameter.constantInitializer =
-            _buildConstExpression(serializedParameter.defaultValue);
-      } else {
-        parameterElement = new ParameterElementImpl(
-            serializedParameter.name, serializedParameter.nameOffset);
+        if (serializedParameter.defaultValue != null) {
+          defaultParameter.constantInitializer =
+              _buildConstExpression(serializedParameter.defaultValue);
+        }
       }
     }
     buildAnnotations(parameterElement, serializedParameter.annotations);
@@ -1455,7 +1548,7 @@
       parameterTypeElement.shareParameters(parameterElement.parameters);
       parameterTypeElement.returnType = buildType(serializedParameter.type);
       parameterElement.type = new FunctionTypeImpl.elementWithNameAndArgs(
-          parameterTypeElement, null, currentTypeArguments, false);
+          parameterTypeElement, null, getCurrentTypeArguments(), false);
     } else {
       if (serializedParameter.isInitializingFormal &&
           serializedParameter.type == null) {
@@ -1503,6 +1596,17 @@
   }
 
   /**
+   * Handle the parts that are common to top level variables and fields.
+   */
+  void buildPropertyIntroducingElementCommonParts(
+      PropertyInducingElementImpl element,
+      UnlinkedVariable serializedVariable) {
+    buildVariableCommonParts(element, serializedVariable);
+    element.propagatedType =
+        buildLinkedType(serializedVariable.propagatedTypeSlot);
+  }
+
+  /**
    * Build a [DartType] object based on a [EntityRef].  This [DartType]
    * may refer to elements in other libraries than the library being
    * deserialized, so handles are used to avoid having to deserialize other
@@ -1517,10 +1621,7 @@
       }
     }
     if (type.paramReference != 0) {
-      // TODO(paulberry): make this work for generic methods.
-      return currentTypeParameters[
-              currentTypeParameters.length - type.paramReference]
-          .type;
+      return getTypeParameterFromScope(type.paramReference);
     } else {
       DartType getTypeArgument(int i) {
         if (i < type.typeArguments.length) {
@@ -1540,30 +1641,23 @@
    * [unitHolder].
    */
   void buildTypedef(UnlinkedTypedef serializedTypedef) {
-    try {
-      currentTypeParameters =
-          serializedTypedef.typeParameters.map(buildTypeParameter).toList();
-      for (int i = 0; i < serializedTypedef.typeParameters.length; i++) {
-        finishTypeParameter(
-            serializedTypedef.typeParameters[i], currentTypeParameters[i]);
-      }
-      FunctionTypeAliasElementImpl functionTypeAliasElement =
-          new FunctionTypeAliasElementImpl(
-              serializedTypedef.name, serializedTypedef.nameOffset);
-      functionTypeAliasElement.parameters =
-          serializedTypedef.parameters.map(buildParameter).toList();
-      functionTypeAliasElement.returnType =
-          buildType(serializedTypedef.returnType);
-      functionTypeAliasElement.type =
-          new FunctionTypeImpl.forTypedef(functionTypeAliasElement);
-      functionTypeAliasElement.typeParameters = currentTypeParameters;
-      buildDocumentation(
-          functionTypeAliasElement, serializedTypedef.documentationComment);
-      buildAnnotations(functionTypeAliasElement, serializedTypedef.annotations);
-      unitHolder.addTypeAlias(functionTypeAliasElement);
-    } finally {
-      currentTypeParameters = <TypeParameterElement>[];
-    }
+    FunctionTypeAliasElementImpl functionTypeAliasElement =
+        new FunctionTypeAliasElementImpl(
+            serializedTypedef.name, serializedTypedef.nameOffset);
+    functionTypeAliasElement.typeParameters =
+        buildTypeParameters(serializedTypedef.typeParameters);
+    functionTypeAliasElement.parameters =
+        serializedTypedef.parameters.map(buildParameter).toList();
+    functionTypeAliasElement.returnType =
+        buildType(serializedTypedef.returnType);
+    functionTypeAliasElement.type =
+        new FunctionTypeImpl.forTypedef(functionTypeAliasElement);
+    buildDocumentation(
+        functionTypeAliasElement, serializedTypedef.documentationComment);
+    buildAnnotations(functionTypeAliasElement, serializedTypedef.annotations);
+    unitHolder.addTypeAlias(functionTypeAliasElement);
+    currentTypeParameters.removeLast();
+    assert(currentTypeParameters.isEmpty);
   }
 
   /**
@@ -1585,6 +1679,22 @@
   }
 
   /**
+   * Build [TypeParameterElement]s corresponding to the type parameters in
+   * [serializedTypeParameters] and store them in [currentTypeParameters].
+   * Also return them.
+   */
+  List<TypeParameterElement> buildTypeParameters(
+      List<UnlinkedTypeParam> serializedTypeParameters) {
+    List<TypeParameterElement> typeParameters =
+        serializedTypeParameters.map(buildTypeParameter).toList();
+    currentTypeParameters.add(typeParameters);
+    for (int i = 0; i < serializedTypeParameters.length; i++) {
+      finishTypeParameter(serializedTypeParameters[i], typeParameters[i]);
+    }
+    return typeParameters;
+  }
+
+  /**
    * Resynthesize a [TopLevelVariableElement] or [FieldElement].
    */
   void buildVariable(UnlinkedVariable serializedVariable,
@@ -1602,7 +1712,7 @@
         element = new TopLevelVariableElementImpl(
             serializedVariable.name, serializedVariable.nameOffset);
       }
-      buildVariableCommonParts(element, serializedVariable);
+      buildPropertyIntroducingElementCommonParts(element, serializedVariable);
       unitHolder.addTopLevelVariable(element);
       buildImplicitAccessors(element, unitHolder);
     } else {
@@ -1617,7 +1727,7 @@
         element = new FieldElementImpl(
             serializedVariable.name, serializedVariable.nameOffset);
       }
-      buildVariableCommonParts(element, serializedVariable);
+      buildPropertyIntroducingElementCommonParts(element, serializedVariable);
       element.static = serializedVariable.isStatic;
       holder.addField(element);
       buildImplicitAccessors(element, holder);
@@ -1626,17 +1736,15 @@
   }
 
   /**
-   * Handle the parts that are common to top level variables and fields.
+   * Handle the parts that are common to variables.
    */
-  void buildVariableCommonParts(PropertyInducingElementImpl element,
-      UnlinkedVariable serializedVariable) {
+  void buildVariableCommonParts(
+      VariableElementImpl element, UnlinkedVariable serializedVariable) {
     element.type = buildLinkedType(serializedVariable.inferredTypeSlot) ??
         buildType(serializedVariable.type);
     element.const3 = serializedVariable.isConst;
     element.final2 = serializedVariable.isFinal;
     element.hasImplicitType = serializedVariable.type == null;
-    element.propagatedType =
-        buildLinkedType(serializedVariable.propagatedTypeSlot);
     buildDocumentation(element, serializedVariable.documentationComment);
     buildAnnotations(element, serializedVariable.annotations);
   }
@@ -1665,6 +1773,25 @@
   }
 
   /**
+   * Return a list of type arguments corresponding to [currentTypeParameters],
+   * skipping the innermost [skipLevels] nesting levels.
+   *
+   * Type parameters are listed in nesting order from innermost to outermost,
+   * and then in declaration order.  So for instance if we are resynthesizing a
+   * method declared as `class C<T, U> { void m<V, W>() { ... } }`, then the
+   * type parameters will be returned in the order `[V, W, T, U]`.
+   */
+  List<DartType> getCurrentTypeArguments({int skipLevels: 0}) {
+    assert(currentTypeParameters.length >= skipLevels);
+    List<DartType> result = <DartType>[];
+    for (int i = currentTypeParameters.length - 1 - skipLevels; i >= 0; i--) {
+      result.addAll(currentTypeParameters[i]
+          .map((TypeParameterElement param) => param.type));
+    }
+    return result;
+  }
+
+  /**
    * Build the components of an [ElementLocationImpl] for the entity in the
    * given [unit] of the dependency located at [dependencyIndex], and having
    * the given [name].
@@ -1701,6 +1828,24 @@
   }
 
   /**
+   * Get the type parameter from the surrounding scope whose De Bruijn index is
+   * [index].
+   */
+  DartType getTypeParameterFromScope(int index) {
+    for (int i = currentTypeParameters.length - 1; i >= 0; i--) {
+      List<TypeParameterElement> paramsAtThisNestingLevel =
+          currentTypeParameters[i];
+      int numParamsAtThisNestingLevel = paramsAtThisNestingLevel.length;
+      if (index <= numParamsAtThisNestingLevel) {
+        return paramsAtThisNestingLevel[numParamsAtThisNestingLevel - index]
+            .type;
+      }
+      index -= numParamsAtThisNestingLevel;
+    }
+    throw new StateError('Type parameter not found');
+  }
+
+  /**
    * Populate [referenceInfos] with the correct information for the current
    * compilation unit.
    */
@@ -1710,7 +1855,6 @@
     referenceInfos = new List<_ReferenceInfo>(numLinkedReferences);
     for (int i = 0; i < numLinkedReferences; i++) {
       LinkedReference linkedReference = linkedUnit.references[i];
-      _ReferenceInfo enclosingInfo = null;
       String name;
       int containingReference;
       if (i < numUnlinkedReferences) {
@@ -1720,12 +1864,14 @@
         name = linkedUnit.references[i].name;
         containingReference = linkedUnit.references[i].containingReference;
       }
+      _ReferenceInfo enclosingInfo =
+          containingReference != 0 ? referenceInfos[containingReference] : null;
       Element element;
       DartType type;
       int numTypeParameters = linkedReference.numTypeParameters;
       if (linkedReference.kind == ReferenceKind.unresolved) {
         type = summaryResynthesizer.typeProvider.undefinedType;
-        element = type.element;
+        element = null;
       } else if (name == 'dynamic') {
         type = summaryResynthesizer.typeProvider.dynamicType;
         element = type.element;
@@ -1734,10 +1880,8 @@
         element = type.element;
       } else {
         List<String> locationComponents;
-        if (containingReference != 0 &&
-            referenceInfos[containingReference].element is ClassElement) {
+        if (enclosingInfo != null && enclosingInfo.element is ClassElement) {
           String identifier = _getElementIdentifier(name, linkedReference.kind);
-          enclosingInfo = referenceInfos[containingReference];
           locationComponents =
               enclosingInfo.element.location.components.toList();
           locationComponents.add(identifier);
@@ -1831,7 +1975,9 @@
     for (PropertyAccessorElementImpl accessor in unit.accessors) {
       elementMap[accessor.identifier] = accessor;
     }
-    resummarizedElements[absoluteUri] = elementMap;
+    resynthesizedUnits[absoluteUri] = unit;
+    resynthesizedElements[absoluteUri] = elementMap;
+    assert(currentTypeParameters.isEmpty);
   }
 
   /**
@@ -1891,6 +2037,43 @@
               <String>['dart:core', 'dart:core', 'String', 'length?']));
 
   /**
+   * Return the defining type for a [ConstructorElement] by applying
+   * [typeArgumentRefs] to the given linked [info].
+   */
+  InterfaceType _createConstructorDefiningType(
+      _ReferenceInfo info, List<EntityRef> typeArgumentRefs) {
+    bool isClass = info.element is ClassElement;
+    _ReferenceInfo classInfo = isClass ? info : info.enclosing;
+    List<DartType> typeArguments = typeArgumentRefs.map(buildType).toList();
+    return classInfo.buildType((i) {
+      if (i < typeArguments.length) {
+        return typeArguments[i];
+      } else {
+        return DynamicTypeImpl.instance;
+      }
+    }, const <int>[]);
+  }
+
+  /**
+   * Return the [ConstructorElement] corresponding to the given linked [info],
+   * using the [classType] which has already been computed (e.g. by
+   * [_createConstructorDefiningType]).  Both cases when [info] is a
+   * [ClassElement] and [ConstructorElement] are supported.
+   */
+  ConstructorElement _createConstructorElement(
+      InterfaceType classType, _ReferenceInfo info) {
+    bool isClass = info.element is ClassElement;
+    String name = isClass ? '' : info.name;
+    _DeferredConstructorElement element =
+        new _DeferredConstructorElement(classType, name);
+    if (info.numTypeParameters != 0) {
+      return new ConstructorMember(element, classType);
+    } else {
+      return element;
+    }
+  }
+
+  /**
    * If the given [kind] is a top-level or class member property accessor, and
    * the given [name] does not end with `=`, i.e. does not denote a setter,
    * return the getter identifier by appending `?`.
diff --git a/pkg/analyzer/lib/src/summary/summarize_ast.dart b/pkg/analyzer/lib/src/summary/summarize_ast.dart
index e5f4c4f..a3d915b 100644
--- a/pkg/analyzer/lib/src/summary/summarize_ast.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_ast.dart
@@ -5,8 +5,8 @@
 library serialization.summarize_ast;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
@@ -93,9 +93,8 @@
     Expression target = access.target;
     if (target is Identifier) {
       EntityRefBuilder targetRef = serializeIdentifier(target);
-      return new EntityRefBuilder(
-          reference: visitor.serializeReference(
-              targetRef.reference, access.propertyName.name));
+      return new EntityRefBuilder(reference: visitor.serializeReference(
+          targetRef.reference, access.propertyName.name));
     } else {
       // TODO(scheglov) should we handle other targets in malformed constants?
       throw new StateError('Unexpected target type: ${target.runtimeType}');
@@ -170,7 +169,7 @@
 /**
  * Visitor used to create a summary from an AST.
  */
-class _SummarizeAstVisitor extends SimpleAstVisitor {
+class _SummarizeAstVisitor extends RecursiveAstVisitor {
   /**
    * List of objects which should be written to [UnlinkedUnit.classes].
    */
@@ -182,8 +181,8 @@
   final List<UnlinkedEnumBuilder> enums = <UnlinkedEnumBuilder>[];
 
   /**
-   * List of objects which should be written to [UnlinkedUnit.executables]
-   * or [UnlinkedClass.executables].
+   * List of objects which should be written to [UnlinkedUnit.executables],
+   * [UnlinkedClass.executables] or [UnlinkedExecutable.localFunctions].
    */
   List<UnlinkedExecutableBuilder> executables = <UnlinkedExecutableBuilder>[];
 
@@ -204,8 +203,8 @@
   final List<UnlinkedTypedefBuilder> typedefs = <UnlinkedTypedefBuilder>[];
 
   /**
-   * List of objects which should be written to [UnlinkedUnit.variables] or
-   * [UnlinkedClass.fields].
+   * List of objects which should be written to [UnlinkedUnit.variables],
+   * [UnlinkedClass.fields] or [UnlinkedExecutable.localVariables].
    */
   List<UnlinkedVariableBuilder> variables = <UnlinkedVariableBuilder>[];
 
@@ -285,10 +284,9 @@
   int numSlots = 0;
 
   /**
-   * A flag indicating whether a variable declaration is in the context of a
-   * field declaration.
+   * The [Block] that is being visited now, or `null` for non-local contexts.
    */
-  bool inFieldContext = false;
+  Block enclosingBlock = null;
 
   /**
    * Create a slot id for storing a propagated or inferred type.
@@ -303,8 +301,6 @@
       String className, NodeList<ClassMember> members) {
     _Scope scope = new _Scope();
     for (ClassMember member in members) {
-      // TODO(paulbery): consider replacing these if-tests with dynamic method
-      // dispatch.
       if (member is MethodDeclaration) {
         if (member.isSetter || member.isOperator) {
           // We don't have to handle setters or operators because the only
@@ -330,7 +326,7 @@
    */
   List<UnlinkedConstBuilder> serializeAnnotations(
       NodeList<Annotation> annotations) {
-    if (annotations.isEmpty) {
+    if (annotations == null || annotations.isEmpty) {
       return const <UnlinkedConstBuilder>[];
     }
     return annotations.map((Annotation a) {
@@ -533,11 +529,32 @@
     if (returnType == null && !isSemanticallyStatic) {
       b.inferredReturnTypeSlot = assignTypeSlot();
     }
+    b.visibleOffset = enclosingBlock?.offset;
+    b.visibleLength = enclosingBlock?.length;
+    serializeFunctionBody(b, body);
     scopes.removeLast();
     assert(scopes.length == oldScopesLength);
     return b;
   }
 
+  void serializeFunctionBody(UnlinkedExecutableBuilder b, FunctionBody body) {
+    if (body is BlockFunctionBody || body is ExpressionFunctionBody) {
+      for (UnlinkedParamBuilder parameter in b.parameters) {
+        parameter.visibleOffset = body.offset;
+        parameter.visibleLength = body.length;
+      }
+    }
+    List<UnlinkedExecutableBuilder> oldExecutables = executables;
+    List<UnlinkedVariableBuilder> oldVariables = variables;
+    executables = <UnlinkedExecutableBuilder>[];
+    variables = <UnlinkedVariableBuilder>[];
+    body.accept(this);
+    b.localFunctions = executables;
+    b.localVariables = variables;
+    executables = oldExecutables;
+    variables = oldVariables;
+  }
+
   /**
    * Serialize the return type and parameters of a function-typed formal
    * parameter and store them in [b].
@@ -719,7 +736,8 @@
       b.type = serializeTypeName(variables.type);
       b.documentationComment = serializeDocumentation(documentationComment);
       b.annotations = serializeAnnotations(annotations);
-      if (variable.isConst || variable.isFinal && inFieldContext) {
+      if (variable.isConst ||
+          variable.isFinal && isField && !isDeclaredStatic) {
         Expression initializer = variable.initializer;
         if (initializer != null) {
           b.constExpr = serializeConstExpr(initializer);
@@ -734,11 +752,21 @@
           (variable.initializer != null || !isSemanticallyStatic)) {
         b.inferredTypeSlot = assignTypeSlot();
       }
+      b.visibleOffset = enclosingBlock?.offset;
+      b.visibleLength = enclosingBlock?.length;
       this.variables.add(b);
     }
   }
 
   @override
+  void visitBlock(Block node) {
+    Block oldBlock = enclosingBlock;
+    enclosingBlock = node;
+    super.visitBlock(node);
+    enclosingBlock = oldBlock;
+  }
+
+  @override
   void visitClassDeclaration(ClassDeclaration node) {
     TypeName superclass =
         node.extendsClause == null ? null : node.extendsClause.superclass;
@@ -785,7 +813,22 @@
         .map((FormalParameter p) => p.accept(this))
         .toList();
     b.kind = UnlinkedExecutableKind.constructor;
-    b.isFactory = node.factoryKeyword != null;
+    if (node.factoryKeyword != null) {
+      b.isFactory = true;
+      if (node.redirectedConstructor != null) {
+        b.isRedirectedConstructor = true;
+        b.redirectedConstructor = new _ConstExprSerializer(this, null)
+            .serializeConstructorName(node.redirectedConstructor.type,
+                node.redirectedConstructor.name);
+      }
+    } else {
+      for (ConstructorInitializer initializer in node.initializers) {
+        if (initializer is RedirectingConstructorInvocation) {
+          b.isRedirectedConstructor = true;
+          b.redirectedConstructorName = initializer.constructorName?.name;
+        }
+      }
+    }
     b.isConst = node.constKeyword != null;
     b.isExternal = node.externalKeyword != null;
     b.documentationComment = serializeDocumentation(node.documentationComment);
@@ -800,6 +843,7 @@
               }))
           .toList();
     }
+    serializeFunctionBody(b, node.body);
     executables.add(b);
   }
 
@@ -820,7 +864,10 @@
     b.nameOffset = node.name.offset;
     b.values = node.constants
         .map((EnumConstantDeclaration value) => new UnlinkedEnumValueBuilder(
-            name: value.name.name, nameOffset: value.name.offset))
+            documentationComment:
+                serializeDocumentation(value.documentationComment),
+            name: value.name.name,
+            nameOffset: value.name.offset))
         .toList();
     b.documentationComment = serializeDocumentation(node.documentationComment);
     b.annotations = serializeAnnotations(node.metadata);
@@ -837,13 +884,8 @@
 
   @override
   void visitFieldDeclaration(FieldDeclaration node) {
-    try {
-      inFieldContext = true;
-      serializeVariables(node.fields, node.staticKeyword != null,
-          node.documentationComment, node.metadata, true);
-    } finally {
-      inFieldContext = false;
-    }
+    serializeVariables(node.fields, node.staticKeyword != null,
+        node.documentationComment, node.metadata, true);
   }
 
   @override
@@ -995,6 +1037,11 @@
     return b;
   }
 
+  @override
+  void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
+    serializeVariables(node.variables, false, null, null, false);
+  }
+
   /**
    * Helper method to determine if a given [typeName] refers to `dynamic`.
    */
diff --git a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
index b644788..9e63ff8 100644
--- a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
@@ -4,8 +4,8 @@
 
 library serialization.summarize_const_expr;
 
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
 
diff --git a/pkg/analyzer/lib/src/summary/summarize_elements.dart b/pkg/analyzer/lib/src/summary/summarize_elements.dart
index 168e91b..b631287 100644
--- a/pkg/analyzer/lib/src/summary/summarize_elements.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_elements.dart
@@ -7,9 +7,11 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
@@ -187,7 +189,7 @@
             kind: ReferenceKind.classOrEnum,
             name: cls.name,
             numTypeParameters: cls.typeParameters.length,
-            constMembers: serializeClassConstMembers(cls)));
+            members: serializeClassConstMembers(cls)));
       }
     }
     for (ClassElement enm in compilationUnit.enums) {
@@ -293,6 +295,7 @@
    * parameter [type].
    */
   int findTypeParameterIndex(TypeParameterType type, Element context) {
+    Element originalContext = context;
     int index = 0;
     while (context != null) {
       List<TypeParameterElement> typeParameters;
@@ -314,7 +317,8 @@
       }
       context = context.enclosingElement;
     }
-    throw new StateError('Unbound type parameter $type');
+    throw new StateError(
+        'Unbound type parameter $type (${originalContext?.location})');
   }
 
   /**
@@ -404,6 +408,12 @@
    * Otherwise return `null`.
    */
   List<UnlinkedPublicNameBuilder> serializeClassConstMembers(ClassElement cls) {
+    if (cls.isMixinApplication) {
+      // Mixin application members can't be determined directly from the AST so
+      // we can't store them in UnlinkedPublicName.
+      // TODO(paulberry): find somewhere else to store them.
+      return null;
+    }
     if (cls.kind == ElementKind.CLASS) {
       List<UnlinkedPublicNameBuilder> bs = <UnlinkedPublicNameBuilder>[];
       for (FieldElement field in cls.fields) {
@@ -425,7 +435,7 @@
         }
       }
       for (ConstructorElement constructor in cls.constructors) {
-        if (constructor.isConst && constructor.isPublic) {
+        if (constructor.isPublic && constructor.name.isNotEmpty) {
           // TODO(paulberry): should numTypeParameters include class params?
           bs.add(new UnlinkedPublicNameBuilder(
               name: constructor.name,
@@ -532,6 +542,32 @@
       b.kind = UnlinkedExecutableKind.constructor;
       b.isConst = executableElement.isConst;
       b.isFactory = executableElement.isFactory;
+      ConstructorElement redirectedConstructor =
+          executableElement.redirectedConstructor;
+      if (redirectedConstructor != null) {
+        b.isRedirectedConstructor = true;
+        if (executableElement.isFactory) {
+          InterfaceType returnType = redirectedConstructor is ConstructorMember
+              ? redirectedConstructor.definingType
+              : redirectedConstructor.enclosingElement.type;
+          EntityRefBuilder typeRef =
+              serializeTypeRef(returnType, executableElement);
+          if (redirectedConstructor.name.isNotEmpty) {
+            String name = redirectedConstructor.name;
+            int typeId = typeRef.reference;
+            LinkedReference typeLinkedRef = linkedReferences[typeId];
+            int refId = serializeUnlinkedReference(
+                name, ReferenceKind.constructor,
+                unit: typeLinkedRef.unit, prefixReference: typeId);
+            b.redirectedConstructor = new EntityRefBuilder(
+                reference: refId, typeArguments: typeRef.typeArguments);
+          } else {
+            b.redirectedConstructor = typeRef;
+          }
+        } else {
+          b.redirectedConstructorName = redirectedConstructor.name;
+        }
+      }
       if (executableElement.isConst &&
           executableElement.constantInitializers != null) {
         Set<String> constructorParameterNames =
@@ -553,6 +589,17 @@
     b.isExternal = executableElement.isExternal;
     b.documentationComment = serializeDocumentation(executableElement);
     b.annotations = serializeAnnotations(executableElement);
+    if (executableElement is FunctionElement) {
+      SourceRange visibleRange = executableElement.visibleRange;
+      if (visibleRange != null) {
+        b.visibleOffset = visibleRange.offset;
+        b.visibleLength = visibleRange.length;
+      }
+    }
+    b.localFunctions =
+        executableElement.functions.map(serializeExecutable).toList();
+    b.localVariables =
+        executableElement.localVariables.map(serializeVariable).toList();
     return b;
   }
 
@@ -653,6 +700,13 @@
         b.defaultValue = serializeConstExpr(initializer);
       }
     }
+    {
+      SourceRange visibleRange = parameter.visibleRange;
+      if (visibleRange != null) {
+        b.visibleOffset = visibleRange.offset;
+        b.visibleLength = visibleRange.length;
+      }
+    }
     return b;
   }
 
@@ -660,14 +714,8 @@
    * Serialize the given [prefix] into an index into the references table.
    */
   int serializePrefix(PrefixElement element) {
-    return referenceMap.putIfAbsent(element, () {
-      assert(unlinkedReferences.length == linkedReferences.length);
-      int index = unlinkedReferences.length;
-      unlinkedReferences.add(new UnlinkedReferenceBuilder(name: element.name));
-      linkedReferences
-          .add(new LinkedReferenceBuilder(kind: ReferenceKind.prefix));
-      return index;
-    });
+    return referenceMap.putIfAbsent(element,
+        () => serializeUnlinkedReference(element.name, ReferenceKind.prefix));
   }
 
   /**
@@ -789,6 +837,23 @@
   }
 
   /**
+   * Create a new entry in the references table ([UnlinkedLibrary.references]
+   * and [LinkedLibrary.references]) representing an entity having the given
+   * [name] and [kind].  If [unit] is given, it is the index of the compilation
+   * unit containing the entity being referred to.  If [prefixReference] is
+   * given, it indicates the entry in the references table for the prefix.
+   */
+  int serializeUnlinkedReference(String name, ReferenceKind kind,
+      {int unit: 0, int prefixReference: 0}) {
+    assert(unlinkedReferences.length == linkedReferences.length);
+    int index = unlinkedReferences.length;
+    unlinkedReferences.add(new UnlinkedReferenceBuilder(
+        name: name, prefixReference: prefixReference));
+    linkedReferences.add(new LinkedReferenceBuilder(kind: kind, unit: unit));
+    return index;
+  }
+
+  /**
    * Return the index of the entry in the references table
    * ([UnlinkedLibrary.references] and [LinkedLibrary.references]) used for
    * unresolved references.  A new entry is added to the table if necessary to
@@ -800,12 +865,8 @@
     // the element model.  For the moment we use a name that can't possibly
     // ever exist.
     if (unresolvedReferenceIndex == null) {
-      assert(unlinkedReferences.length == linkedReferences.length);
-      unresolvedReferenceIndex = unlinkedReferences.length;
-      unlinkedReferences
-          .add(new UnlinkedReferenceBuilder(name: '*unresolved*'));
-      linkedReferences
-          .add(new LinkedReferenceBuilder(kind: ReferenceKind.unresolved));
+      return serializeUnlinkedReference(
+          '*unresolved*', ReferenceKind.unresolved);
     }
     return unresolvedReferenceIndex;
   }
@@ -813,7 +874,7 @@
   /**
    * Serialize the given [variable], creating an [UnlinkedVariable].
    */
-  UnlinkedVariableBuilder serializeVariable(PropertyInducingElement variable) {
+  UnlinkedVariableBuilder serializeVariable(VariableElement variable) {
     UnlinkedVariableBuilder b = new UnlinkedVariableBuilder();
     b.name = variable.name;
     b.nameOffset = variable.nameOffset;
@@ -832,16 +893,26 @@
         b.constExpr = serializeConstExpr(initializer);
       }
     }
-    if (b.isFinal || b.isConst) {
-      b.propagatedTypeSlot = storeLinkedType(variable.propagatedType, variable);
-    } else {
-      // Variable is not propagable.
-      assert(variable.propagatedType == null);
+    if (variable is PropertyInducingElement) {
+      if (b.isFinal || b.isConst) {
+        b.propagatedTypeSlot =
+            storeLinkedType(variable.propagatedType, variable);
+      } else {
+        // Variable is not propagable.
+        assert(variable.propagatedType == null);
+      }
     }
     if (variable.hasImplicitType &&
         (variable.initializer != null || !variable.isStatic)) {
       b.inferredTypeSlot = storeInferredType(variable.type, variable);
     }
+    if (variable is LocalVariableElement) {
+      SourceRange visibleRange = variable.visibleRange;
+      if (visibleRange != null) {
+        b.visibleOffset = visibleRange.offset;
+        b.visibleLength = visibleRange.length;
+      }
+    }
     return b;
   }
 
@@ -896,22 +967,21 @@
         unit = dependentLibrary.units.indexOf(unitElement);
         assert(unit != -1);
       }
-      LinkedReferenceBuilder linkedReference = new LinkedReferenceBuilder(
-          dependency: librarySerializer.serializeDependency(dependentLibrary),
-          kind: _getReferenceKind(element),
-          unit: unit);
-      if (element is TypeParameterizedElement) {
-        linkedReference.numTypeParameters = element.typeParameters.length;
-      }
+      ReferenceKind kind = _getReferenceKind(element);
       String name = element == null ? 'void' : element.name;
+      int index;
+      LinkedReferenceBuilder linkedReference;
       if (linked) {
-        linkedReference.name = name;
+        linkedReference =
+            new LinkedReferenceBuilder(kind: kind, unit: unit, name: name);
         Element enclosing = element?.enclosingElement;
         if (enclosing is ClassElement) {
           linkedReference.containingReference =
               _getElementReferenceId(enclosing, linked: linked);
-          linkedReference.numTypeParameters += enclosing.typeParameters.length;
+          linkedReference.numTypeParameters = enclosing.typeParameters.length;
         }
+        index = linkedReferences.length;
+        linkedReferences.add(linkedReference);
       } else {
         assert(unlinkedReferences.length == linkedReferences.length);
         int prefixReference = 0;
@@ -929,24 +999,22 @@
         } else {
           prefixReference = _getElementReferenceId(enclosing, linked: linked);
         }
-        unlinkedReferences.add(new UnlinkedReferenceBuilder(
-            name: name, prefixReference: prefixReference));
+        index = serializeUnlinkedReference(name, kind,
+            prefixReference: prefixReference, unit: unit);
+        linkedReference = linkedReferences[index];
       }
-      int index = linkedReferences.length;
-      linkedReferences.add(linkedReference);
+      linkedReference.dependency =
+          librarySerializer.serializeDependency(dependentLibrary);
+      if (element is TypeParameterizedElement) {
+        linkedReference.numTypeParameters += element.typeParameters.length;
+      }
       return index;
     });
   }
 
   int _getLengthPropertyReference(int prefix) {
-    assert(unlinkedReferences.length == linkedReferences.length);
-    int index = linkedReferences.length;
-    unlinkedReferences.add(
-        new UnlinkedReferenceBuilder(name: 'length', prefixReference: prefix));
-    LinkedReferenceBuilder linkedReference =
-        new LinkedReferenceBuilder(kind: ReferenceKind.length);
-    linkedReferences.add(linkedReference);
-    return index;
+    return serializeUnlinkedReference('length', ReferenceKind.length,
+        prefixReference: prefix);
   }
 }
 
@@ -999,25 +1067,42 @@
   @override
   EntityRefBuilder serializeConstructorName(
       TypeName type, SimpleIdentifier name) {
-    EntityRefBuilder typeRef = serializer.serializeTypeRef(type.type, null);
+    EntityRefBuilder typeRef = serializeType(type);
     if (name == null) {
       return typeRef;
     } else {
-      int typeId = typeRef.reference;
-      LinkedReference typeLinkedRef = serializer.linkedReferences[typeId];
-      serializer.unlinkedReferences.add(new UnlinkedReferenceBuilder(
-          name: name.name, prefixReference: typeId));
-      int refId = serializer.linkedReferences.length;
-      serializer.linkedReferences.add(new LinkedReferenceBuilder(
-          kind: ReferenceKind.constructor, unit: typeLinkedRef.unit));
+      LinkedReference typeLinkedRef =
+          serializer.linkedReferences[typeRef.reference];
+      int refId = serializer.serializeUnlinkedReference(
+          name.name,
+          name.staticElement != null
+              ? ReferenceKind.constructor
+              : ReferenceKind.unresolved,
+          prefixReference: typeRef.reference,
+          unit: typeLinkedRef.unit);
       return new EntityRefBuilder(
           reference: refId, typeArguments: typeRef.typeArguments);
     }
   }
 
-  EntityRefBuilder serializeIdentifier(Identifier identifier) {
+  EntityRefBuilder serializeIdentifier(Identifier identifier,
+      {int prefixReference: 0}) {
     Element element = identifier.staticElement;
-    assert(element != null);
+    // Unresolved identifier.
+    if (element == null) {
+      int reference;
+      if (identifier is PrefixedIdentifier) {
+        int prefix = serializeIdentifier(identifier.prefix).reference;
+        reference = serializer.serializeUnlinkedReference(
+            identifier.identifier.name, ReferenceKind.unresolved,
+            prefixReference: prefix);
+      } else {
+        reference = serializer.serializeUnlinkedReference(
+            identifier.name, ReferenceKind.unresolved,
+            prefixReference: prefixReference);
+      }
+      return new EntityRefBuilder(reference: reference);
+    }
     // The only supported instance property accessor - `length`.
     if (identifier is PrefixedIdentifier &&
         element is PropertyAccessorElement &&
@@ -1040,7 +1125,19 @@
   @override
   EntityRefBuilder serializePropertyAccess(PropertyAccess access) {
     Element element = access.propertyName.staticElement;
-    assert(element != null);
+    // Unresolved property access.
+    if (element == null) {
+      Expression target = access.target;
+      if (target is Identifier) {
+        EntityRefBuilder targetRef = serializeIdentifier(target);
+        EntityRefBuilder propertyRef = serializeIdentifier(access.propertyName,
+            prefixReference: targetRef.reference);
+        return new EntityRefBuilder(reference: propertyRef.reference);
+      } else {
+        // TODO(scheglov) should we handle other targets in malformed constants?
+        throw new StateError('Unexpected target type: ${target.runtimeType}');
+      }
+    }
     // The only supported instance property accessor - `length`.
     Expression target = access.target;
     if (target is Identifier &&
@@ -1058,6 +1155,12 @@
 
   @override
   EntityRefBuilder serializeType(TypeName typeName) {
+    if (typeName != null) {
+      DartType type = typeName.type;
+      if (type == null || type.isUndefined) {
+        return serializeIdentifier(typeName.name);
+      }
+    }
     DartType type = typeName != null ? typeName.type : DynamicTypeImpl.instance;
     return serializer.serializeTypeRef(type, null);
   }
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart
index b12a34e..2108b74 100644
--- a/pkg/analyzer/lib/src/summary/summary_sdk.dart
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -16,21 +16,7 @@
     show DartUriResolver, Source, SourceFactory, SourceKind;
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/resynthesize.dart';
-import 'package:analyzer/src/task/dart.dart'
-    show
-        CONSTANT_VALUE,
-        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/src/task/dart.dart';
 import 'package:analyzer/task/dart.dart';
 import 'package:analyzer/task/model.dart'
     show AnalysisTarget, ResultDescriptor, TargetedResult;
@@ -55,20 +41,22 @@
   @override
   bool compute(CacheEntry entry, ResultDescriptor result) {
     if (result == TYPE_PROVIDER) {
-//      print('SummarySdkAnalysisContext: $result');
       entry.setValue(result, typeProvider, TargetedResult.EMPTY_LIST);
       return true;
     }
     AnalysisTarget target = entry.target;
-    // TODO(scheglov) we don't actually update "evaluationResult" yet
-    if (result == CONSTANT_VALUE) {
-      if (target.source != null && target.source.isInSystemLibrary) {
-        entry.setValue(result, target, TargetedResult.EMPTY_LIST);
-        return true;
-      }
+    // Only SDK sources after this point.
+    if (target.source == null || !target.source.isInSystemLibrary) {
+      return false;
     }
-    if (target is Source && target.isInSystemLibrary) {
-//      print('SummarySdkAnalysisContext: $result of $target');
+//    print('SummarySdkAnalysisContext: $result of $target');
+    // Constant expressions are always resolved in summaries.
+    if (result == CONSTANT_EXPRESSION_RESOLVED &&
+        target is ConstantEvaluationTarget) {
+      entry.setValue(result, true, TargetedResult.EMPTY_LIST);
+      return true;
+    }
+    if (target is Source) {
       if (result == LIBRARY_ELEMENT1 ||
           result == LIBRARY_ELEMENT2 ||
           result == LIBRARY_ELEMENT3 ||
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index c001aed..b492bb2 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -7,6 +7,7 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -15,6 +16,8 @@
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/builder.dart';
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
@@ -23,9 +26,9 @@
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/generated/visitors.dart';
 import 'package:analyzer/src/plugin/engine_plugin.dart';
 import 'package:analyzer/src/services/lint.dart';
@@ -268,6 +271,13 @@
     new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT9', false);
 
 /**
+ * The [Element]s defined in a [LibrarySpecificUnit].
+ */
+final ListResultDescriptor<Element> DEFINED_ELEMENTS =
+    new ListResultDescriptor<Element>('DEFINED_ELEMENTS', null,
+        cachingPolicy: ELEMENT_CACHING_POLICY);
+
+/**
  * The sources representing the export closure of a library.
  * The [Source]s include only library sources, not their units.
  *
@@ -1358,7 +1368,8 @@
     // set the library documentation to the docs associated with the first
     // directive in the compilation unit.
     if (definingCompilationUnit.directives.isNotEmpty) {
-      _setDoc(libraryElement, definingCompilationUnit.directives.first);
+      setElementDocumentationComment(
+          libraryElement, definingCompilationUnit.directives.first);
     }
 
     //
@@ -1401,19 +1412,6 @@
   }
 
   /**
-   * If the given [node] has a documentation comment, remember its content
-   * and range into the given [element].
-   */
-  void _setDoc(ElementImpl element, AnnotatedNode node) {
-    Comment comment = node.documentationComment;
-    if (comment != null && comment.isDocumentation) {
-      element.documentationComment =
-          comment.tokens.map((Token t) => t.lexeme).join('\n');
-      element.setDocRange(comment.offset, comment.length);
-    }
-  }
-
-  /**
    * Return a map from the names of the inputs of this kind of task to the task
    * input descriptors describing those inputs for a task with the given
    * [libSource].
@@ -2226,6 +2224,9 @@
   static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('DartErrorsTask',
       createTask, buildInputs, <ResultDescriptor>[DART_ERRORS]);
 
+  // Prefix for comments ignoring error codes.
+  static const String _normalizedIgnorePrefix = '//#ignore:';
+
   DartErrorsTask(InternalAnalysisContext context, AnalysisTarget target)
       : super(context, target);
 
@@ -2250,12 +2251,91 @@
         errorLists.add(errors);
       }
     }
+
+    //
+    // Filter ignored errors.
+    //
+    List<AnalysisError> errors =
+        _filterIgnores(AnalysisError.mergeLists(errorLists));
+
     //
     // Record outputs.
     //
-    outputs[DART_ERRORS] = AnalysisError.mergeLists(errorLists);
+    outputs[DART_ERRORS] = errors;
   }
 
+  List<AnalysisError> _filterIgnores(List<AnalysisError> errors) {
+    if (errors.isEmpty) {
+      return errors;
+    }
+
+    List<AnalysisError> filtered = <AnalysisError>[];
+
+    // Sort errors.
+    errors.sort((AnalysisError e1, AnalysisError e2) => e1.offset - e2.offset);
+
+    Source source = target;
+    String contents = context.getContents(source).data;
+    Scanner scanner = new Scanner(source, new CharSequenceReader(contents),
+        AnalysisErrorListener.NULL_LISTENER);
+
+    // Scan.
+    Token token = scanner.tokenize();
+    LineInfo lineInfo = new LineInfo(scanner.lineStarts);
+
+    int errorIndex = 0;
+
+    // Step through tokens looking for comments.
+    while (errorIndex < errors.length && token.type != TokenType.EOF) {
+      // Find leading comment.
+      Token comments = token.precedingComments;
+      while (comments?.next != null) {
+        comments = comments.next;
+      }
+
+      // Normalize content.
+      String comment =
+          comments?.lexeme?.toLowerCase()?.replaceAll(new RegExp(r'\s+'), '');
+
+      // Check for ignores.
+      if (comment != null && comment.startsWith(_normalizedIgnorePrefix)) {
+        int affectedLine = lineInfo.getLocation(token.offset).lineNumber;
+
+        // Process all affected errors.
+        while (errorIndex < errors.length) {
+          AnalysisError currentError = errors[errorIndex++];
+          int errorLine = lineInfo.getLocation(currentError.offset).lineNumber;
+          if (errorLine < affectedLine) {
+            filtered.add(currentError);
+          } else if (errorLine == affectedLine) {
+            // Check for an ignore.
+            if (!_isIgnoredBy(currentError, comment)) {
+              filtered.add(currentError);
+            }
+          } else {
+            // Back up index and break.
+            --errorIndex;
+            break;
+          }
+        }
+      }
+
+      token = token.next;
+    }
+
+    // Add remaining errors.
+    if (errorIndex < errors.length) {
+      filtered.addAll(errors.sublist(errorIndex));
+    }
+
+    return filtered;
+  }
+
+  bool _isIgnoredBy(AnalysisError error, String comment) => comment
+      .substring(_normalizedIgnorePrefix.length)
+      .split(',')
+      .contains(error.errorCode.name.toLowerCase());
+
   /**
    * Return a map from the names of the inputs of this kind of task to the task
    * input descriptors describing those inputs for a task with the
@@ -2538,7 +2618,7 @@
       'GatherUsedLocalElementsTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[USED_LOCAL_ELEMENTS]);
+      <ResultDescriptor>[DEFINED_ELEMENTS, USED_LOCAL_ELEMENTS]);
 
   GatherUsedLocalElementsTask(
       InternalAnalysisContext context, AnalysisTarget target)
@@ -2553,7 +2633,7 @@
     CompilationUnitElement unitElement = unit.element;
     LibraryElement libraryElement = unitElement.library;
     //
-    // Prepare used local elements.
+    // Prepare defined and used local elements.
     //
     GatherUsedLocalElementsVisitor visitor =
         new GatherUsedLocalElementsVisitor(libraryElement);
@@ -2561,6 +2641,7 @@
     //
     // Record outputs.
     //
+    outputs[DEFINED_ELEMENTS] = visitor.definedElements;
     outputs[USED_LOCAL_ELEMENTS] = visitor.usedElements;
   }
 
@@ -2594,6 +2675,11 @@
   static const String RESOLVED_UNIT_INPUT = 'RESOLVED_UNIT';
 
   /**
+   * The name of a list of [DEFINED_ELEMENTS] for each library unit input.
+   */
+  static const String DEFINED_ELEMENTS_INPUT = 'DEFINED_ELEMENTS';
+
+  /**
    * The name of a list of [USED_LOCAL_ELEMENTS] for each library unit input.
    */
   static const String USED_LOCAL_ELEMENTS_INPUT = 'USED_LOCAL_ELEMENTS';
@@ -2639,6 +2725,8 @@
     CompilationUnit unit = getRequiredInput(RESOLVED_UNIT_INPUT);
     List<UsedImportedElements> usedImportedElementsList =
         getRequiredInput(USED_IMPORTED_ELEMENTS_INPUT);
+    List<List<Element>> definedElementsList =
+        getRequiredInput(DEFINED_ELEMENTS_INPUT);
     List<UsedLocalElements> usedLocalElementsList =
         getRequiredInput(USED_LOCAL_ELEMENTS_INPUT);
     CompilationUnitElement unitElement = unit.element;
@@ -2663,7 +2751,11 @@
           new UsedLocalElements.merge(usedLocalElementsList);
       UnusedLocalElementsVerifier visitor =
           new UnusedLocalElementsVerifier(errorListener, usedElements);
-      unitElement.accept(visitor);
+      for (List<Element> definedElements in definedElementsList) {
+        for (Element element in definedElements) {
+          element.accept(visitor);
+        }
+      }
     }
     // Dart2js analysis.
     if (analysisOptions.dart2jsHint) {
@@ -2695,6 +2787,8 @@
     Source libSource = unit.library;
     return <String, TaskInput>{
       RESOLVED_UNIT_INPUT: RESOLVED_UNIT.of(unit),
+      DEFINED_ELEMENTS_INPUT:
+          LIBRARY_SPECIFIC_UNITS.of(libSource).toListOf(DEFINED_ELEMENTS),
       USED_LOCAL_ELEMENTS_INPUT:
           LIBRARY_SPECIFIC_UNITS.of(libSource).toListOf(USED_LOCAL_ELEMENTS),
       USED_IMPORTED_ELEMENTS_INPUT:
diff --git a/pkg/analyzer/lib/src/task/html.dart b/pkg/analyzer/lib/src/task/html.dart
index 01cdd5a..90e78bd 100644
--- a/pkg/analyzer/lib/src/task/html.dart
+++ b/pkg/analyzer/lib/src/task/html.dart
@@ -7,10 +7,10 @@
 import 'dart:collection';
 
 import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/plugin/engine_plugin.dart';
 import 'package:analyzer/src/task/general.dart';
diff --git a/pkg/analyzer/lib/src/task/incremental_element_builder.dart b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
index 4f674ef..b3b3512 100644
--- a/pkg/analyzer/lib/src/task/incremental_element_builder.dart
+++ b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
@@ -7,13 +7,14 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/visitor.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/builder.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 
 /**
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index 4a6483c..9b96c6a 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -30,6 +30,11 @@
 
 final _OptionsProcessor _processor = new _OptionsProcessor();
 
+void applyToAnalysisOptions(
+    AnalysisOptionsImpl options, Map<String, Object> optionMap) {
+  _processor.applyToAnalysisOptions(options, optionMap);
+}
+
 /// Configure this [context] based on configuration details specified in
 /// the given [options].  If [options] is `null`, default values are applied.
 void configureContextOptions(
@@ -412,6 +417,28 @@
 class _OptionsProcessor {
   static final Map<String, Object> defaults = {'analyzer': {}};
 
+  /**
+   * Apply the options in the given [optionMap] to the given analysis [options].
+   */
+  void applyToAnalysisOptions(
+      AnalysisOptionsImpl options, Map<String, Object> optionMap) {
+    if (optionMap == null) {
+      return;
+    }
+    var analyzer = optionMap[AnalyzerOptions.analyzer];
+    if (analyzer is! Map) {
+      return;
+    }
+    // Process strong mode option.
+    var strongMode = analyzer[AnalyzerOptions.strong_mode];
+    if (strongMode is bool) {
+      options.strongMode = strongMode;
+    }
+    // Process language options.
+    var language = analyzer[AnalyzerOptions.language];
+    _applyLanguageOptions(options, language);
+  }
+
   /// Configure [context] based on the given [options] (which can be `null`
   /// to restore [defaults]).
   void configure(AnalysisContext context, Map<String, Object> options) {
@@ -493,4 +520,34 @@
       context.analysisOptions = options;
     }
   }
+
+  void _applyLanguageOption(
+      AnalysisOptionsImpl options, Object feature, Object value) {
+    bool boolValue = toBool(value);
+    if (boolValue != null) {
+      if (feature == AnalyzerOptions.enableAsync) {
+        options.enableAsync = boolValue;
+      }
+      if (feature == AnalyzerOptions.enableSuperMixins) {
+        options.enableSuperMixins = boolValue;
+      }
+      if (feature == AnalyzerOptions.enableGenericMethods) {
+        options.enableGenericMethods = boolValue;
+      }
+    }
+  }
+
+  void _applyLanguageOptions(AnalysisOptionsImpl options, Object configs) {
+    if (configs is YamlMap) {
+      configs.nodes.forEach((key, value) {
+        if (key is YamlScalar && value is YamlScalar) {
+          String feature = key.value?.toString();
+          _applyLanguageOption(options, feature, value.value);
+        }
+      });
+    } else if (configs is Map) {
+      configs
+          .forEach((key, value) => _applyLanguageOption(options, key, value));
+    }
+  }
 }
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index a67251e7..b391517 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -8,12 +8,12 @@
 
 import 'package:analyzer/analyzer.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
-import 'package:analyzer/src/generated/scanner.dart' show Token, TokenType;
 import 'package:analyzer/src/generated/type_system.dart';
 
 import 'info.dart';
@@ -569,15 +569,7 @@
     final Coercion c = _coerceTo(fromT, toT);
     if (c is Identity) return null;
     if (c is CoercionError) return new StaticTypeError(rules, expr, toT);
-    var reason = null;
-
-    var errors = <String>[];
-
-    var ok = _inferExpression(expr, toT, errors);
-    if (ok) return InferredType.create(rules, expr, toT);
-    reason = (errors.isNotEmpty) ? errors.first : null;
-
-    if (c is Cast) return DownCast.create(rules, expr, c, reason: reason);
+    if (c is Cast) return DownCast.create(rules, expr, c);
     assert(false);
     return null;
   }
@@ -800,17 +792,6 @@
     return null;
   }
 
-  /// Checks if we can perform downwards inference on [e] tp get type [t].
-  /// If it is not possible, this will add a message to [errors].
-  bool _inferExpression(Expression e, DartType t, List<String> errors) {
-    DartType staticType = e.staticType ?? DynamicTypeImpl.instance;
-    if (rules.isSubtypeOf(staticType, t)) {
-      return true;
-    }
-    errors.add("$e cannot be typed as $t");
-    return false;
-  }
-
   /// Returns `true` if the expression is a dynamic function call or method
   /// invocation.
   bool _isDynamicCall(Expression call) {
diff --git a/pkg/analyzer/lib/src/task/strong/info.dart b/pkg/analyzer/lib/src/task/strong/info.dart
index 8295439..c3a5839 100644
--- a/pkg/analyzer/lib/src/task/strong/info.dart
+++ b/pkg/analyzer/lib/src/task/strong/info.dart
@@ -107,8 +107,7 @@
 
   // Factory to create correct DownCast variant.
   static StaticInfo create(
-      StrongTypeSystemImpl rules, Expression expression, Cast cast,
-      {String reason}) {
+      StrongTypeSystemImpl rules, Expression expression, Cast cast) {
     final fromT = cast.fromType;
     final toT = cast.toType;
 
@@ -127,14 +126,15 @@
     if (expression is Literal || expression is FunctionExpression) {
       // fromT should be an exact type - this will almost certainly fail at
       // runtime.
-      return new StaticTypeError(rules, expression, toT, reason: reason);
+      return new StaticTypeError(rules, expression, toT);
     }
+
     if (expression is InstanceCreationExpression) {
       ConstructorElement e = expression.staticElement;
       if (e == null || !e.isFactory) {
         // fromT should be an exact type - this will almost certainly fail at
         // runtime.
-        return new StaticTypeError(rules, expression, toT, reason: reason);
+        return new StaticTypeError(rules, expression, toT);
       }
     }
 
@@ -148,7 +148,7 @@
     // declaration, will have an exact type, so we know a downcast will fail.
     if (element is FunctionElement ||
         element is MethodElement && element.isStatic) {
-      return new StaticTypeError(rules, expression, toT, reason: reason);
+      return new StaticTypeError(rules, expression, toT);
     }
 
     // TODO(vsm): Change this to an assert when we have generic methods and
@@ -556,19 +556,15 @@
 class StaticTypeError extends StaticError {
   final DartType baseType;
   final DartType expectedType;
-  String reason = null;
 
-  StaticTypeError(TypeSystem rules, Expression expression, this.expectedType,
-      {this.reason})
+  StaticTypeError(TypeSystem rules, Expression expression, this.expectedType)
       : baseType = expression.staticType ?? DynamicTypeImpl.instance,
         super(expression);
 
   @override
   List<Object> get arguments => [node, baseType, expectedType];
   @override
-  String get message =>
-      'Type check failed: {0} ({1}) is not of type {2}' +
-      ((reason == null) ? '' : ' because $reason');
+  String get message => 'Type check failed: {0} ({1}) is not of type {2}';
 
   @override
   String get name => 'STRONG_MODE_STATIC_TYPE_ERROR';
diff --git a/pkg/analyzer/lib/src/task/yaml.dart b/pkg/analyzer/lib/src/task/yaml.dart
index 8ce7ec1..1e1951c 100644
--- a/pkg/analyzer/lib/src/task/yaml.dart
+++ b/pkg/analyzer/lib/src/task/yaml.dart
@@ -5,10 +5,10 @@
 library analyzer.src.task.yaml;
 
 import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask;
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/general.dart';
 import 'package:analyzer/task/general.dart';
diff --git a/pkg/analyzer/lib/task/dart.dart b/pkg/analyzer/lib/task/dart.dart
index ea132e3..3dbea46 100644
--- a/pkg/analyzer/lib/task/dart.dart
+++ b/pkg/analyzer/lib/task/dart.dart
@@ -5,9 +5,9 @@
 library analyzer.task.dart;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
 import 'package:analyzer/src/task/dart.dart';
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 893b888..c376533 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.27.2-alpha.1
+version: 0.27.2
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: http://www.dartlang.org
diff --git a/pkg/analyzer/test/dart/ast/ast_test.dart b/pkg/analyzer/test/dart/ast/ast_test.dart
index f8d51f1..7be2b72 100644
--- a/pkg/analyzer/test/dart/ast/ast_test.dart
+++ b/pkg/analyzer/test/dart/ast/ast_test.dart
@@ -5,8 +5,8 @@
 library analyzer.test.dart.ast.ast_test;
 
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/generated/testing/ast_factory.dart';
 import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:unittest/unittest.dart';
@@ -502,7 +502,7 @@
     list.addAll(nodes);
     expect(list, hasLength(3));
     AstNode fourthNode = AstFactory.integer(0);
-    expect(javaListSet(list, 1, fourthNode), same(secondNode));
+    list[1] = fourthNode;
     expect(list, hasLength(3));
     expect(list[0], same(firstNode));
     expect(list[1], same(fourthNode));
@@ -513,7 +513,7 @@
     AstNode node = AstFactory.booleanLiteral(true);
     NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
     try {
-      javaListSet(list, -1, node);
+      list[-1] = node;
       fail("Expected IndexOutOfBoundsException");
     } on RangeError {
       // Expected
@@ -524,7 +524,7 @@
     AstNode node = AstFactory.booleanLiteral(true);
     NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
     try {
-      javaListSet(list, 1, node);
+      list[1] = node;
       fail("Expected IndexOutOfBoundsException");
     } on RangeError {
       // Expected
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index 2061e63..3eb5cd0 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -5,6 +5,7 @@
 library analyzer.test.generated.all_the_rest_test;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
@@ -18,7 +19,6 @@
 import 'package:analyzer/src/generated/java_engine_io.dart';
 import 'package:analyzer/src/generated/java_io.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/sdk_io.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -606,6 +606,7 @@
     expect(type.isAbstract, isFalse);
     expect(type.isMixinApplication, isFalse);
     expect(type.isSynthetic, isFalse);
+    expect(type.documentationComment, '/// aaa');
     _assertHasDocRange(type, 50, 7);
   }
 
@@ -849,6 +850,7 @@
     expect(constructors, hasLength(1));
     ConstructorElement constructor = constructors[0];
     expect(constructor, isNotNull);
+    expect(constructor.documentationComment, '/// aaa');
     _assertHasDocRange(constructor, 50, 7);
     expect(constructor.isExternal, isFalse);
     expect(constructor.isFactory, isFalse);
@@ -1034,6 +1036,7 @@
     expect(enums, hasLength(1));
     ClassElement enumElement = enums[0];
     expect(enumElement, isNotNull);
+    expect(enumElement.documentationComment, '/// aaa');
     _assertHasDocRange(enumElement, 50, 7);
     expect(enumElement.name, enumName);
   }
@@ -1057,6 +1060,7 @@
 
     FieldElement firstField = fields[0];
     expect(firstField, isNotNull);
+    expect(firstField.documentationComment, '/// aaa');
     _assertHasDocRange(firstField, 50, 7);
     expect(firstField.name, firstFieldName);
     expect(firstField.initializer, isNull);
@@ -1066,6 +1070,7 @@
 
     FieldElement secondField = fields[1];
     expect(secondField, isNotNull);
+    expect(secondField.documentationComment, '/// aaa');
     _assertHasDocRange(secondField, 50, 7);
     expect(secondField.name, secondFieldName);
     expect(secondField.initializer, isNull);
@@ -1181,6 +1186,7 @@
     expect(accessors, hasLength(1));
     PropertyAccessorElement accessor = accessors[0];
     expect(accessor, isNotNull);
+    expect(accessor.documentationComment, '/// aaa');
     _assertHasDocRange(accessor, 50, 7);
     expect(accessor.name, functionName);
     expect(declaration.element, same(accessor));
@@ -1216,6 +1222,7 @@
     expect(functions, hasLength(1));
     FunctionElement function = functions[0];
     expect(function, isNotNull);
+    expect(function.documentationComment, '/// aaa');
     _assertHasDocRange(function, 50, 7);
     expect(function.hasImplicitReturnType, isFalse);
     expect(function.name, functionName);
@@ -1245,6 +1252,7 @@
     expect(accessors, hasLength(1));
     PropertyAccessorElement accessor = accessors[0];
     expect(accessor, isNotNull);
+    expect(accessor.documentationComment, '/// aaa');
     _assertHasDocRange(accessor, 50, 7);
     expect(accessor.hasImplicitReturnType, isTrue);
     expect(accessor.name, "$functionName=");
@@ -1323,6 +1331,7 @@
     expect(aliases, hasLength(1));
     FunctionTypeAliasElement alias = aliases[0];
     expect(alias, isNotNull);
+    expect(alias.documentationComment, '/// aaa');
     _assertHasDocRange(alias, 50, 7);
     expect(alias.name, aliasName);
     expect(alias.parameters, hasLength(0));
@@ -1488,6 +1497,7 @@
     expect(field.setter, isNull);
     PropertyAccessorElement getter = field.getter;
     expect(getter, isNotNull);
+    expect(getter.documentationComment, '/// aaa');
     _assertHasDocRange(getter, 50, 7);
     expect(getter.hasImplicitReturnType, isTrue);
     expect(getter.isAbstract, isFalse);
@@ -1598,6 +1608,7 @@
     expect(methods, hasLength(1));
     MethodElement method = methods[0];
     expect(method, isNotNull);
+    expect(method.documentationComment, '/// aaa');
     _assertHasDocRange(method, 50, 7);
     expect(method.hasImplicitReturnType, isFalse);
     expect(method.name, methodName);
@@ -1672,6 +1683,7 @@
 
     PropertyAccessorElement setter = field.setter;
     expect(setter, isNotNull);
+    expect(setter.documentationComment, '/// aaa');
     _assertHasDocRange(setter, 50, 7);
     expect(setter.hasImplicitReturnType, isTrue);
     expect(setter.isAbstract, isFalse);
@@ -2235,10 +2247,12 @@
 
     TopLevelVariableElement variable1 = variables[0];
     expect(variable1, isNotNull);
+    expect(variable1.documentationComment, '/// aaa');
     _assertHasDocRange(variable1, 50, 7);
 
     TopLevelVariableElement variable2 = variables[1];
     expect(variable2, isNotNull);
+    expect(variable2.documentationComment, '/// aaa');
     _assertHasDocRange(variable2, 50, 7);
   }
 
@@ -2782,6 +2796,9 @@
     String firstName = "ONE";
     EnumDeclaration enumDeclaration =
         AstFactory.enumDeclaration2("E", [firstName]);
+    enumDeclaration.constants[0].documentationComment = AstFactory
+        .documentationComment(
+            [TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
 
     ClassElement enumElement = _buildElement(enumDeclaration);
     List<FieldElement> fields = enumElement.fields;
@@ -2807,6 +2824,9 @@
     expect(constant.name, firstName);
     expect(constant.isStatic, isTrue);
     expect((constant as FieldElementImpl).evaluationResult, isNotNull);
+    expect(constant.documentationComment, '/// aaa');
+    expect(constant.docRange.offset, 50);
+    expect(constant.docRange.length, 7);
     _assertGetter(constant);
   }
 
@@ -3951,32 +3971,6 @@
   }
 }
 
-/**
- * Instances of the class `MockDartSdk` implement a [DartSdk].
- */
-class MockDartSdk implements DartSdk {
-  @override
-  AnalysisContext get context => null;
-
-  @override
-  List<SdkLibrary> get sdkLibraries => null;
-
-  @override
-  String get sdkVersion => null;
-
-  @override
-  List<String> get uris => null;
-
-  @override
-  Source fromFileUri(Uri uri) => null;
-
-  @override
-  SdkLibrary getSdkLibrary(String dartUri) => null;
-
-  @override
-  Source mapDartUri(String dartUri) => null;
-}
-
 @reflectiveTest
 class SDKLibrariesReaderTest extends EngineTestCase {
   void test_readFrom_dart2js() {
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index 4b611b7..bb9ba02 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -5,15 +5,15 @@
 library analyzer.test.constant_test;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/testing/ast_factory.dart';
@@ -41,6 +41,8 @@
   runReflectiveTests(ReferenceFinderTest);
 }
 
+const int LONG_MAX_VALUE = 0x7fffffffffffffff;
+
 /**
  * Implementation of [ConstantEvaluationValidator] used during unit tests;
  * verifies that any nodes referenced during constant evaluation are present in
@@ -622,10 +624,10 @@
     return new List<Annotation>.from(annotations);
   }
 
-  Set<ConstantEvaluationTarget> _findConstants() {
+  List<ConstantEvaluationTarget> _findConstants() {
     ConstantFinder finder = new ConstantFinder(_context, _source, _source);
     _node.accept(finder);
-    Set<ConstantEvaluationTarget> constants = finder.constantsToCompute;
+    List<ConstantEvaluationTarget> constants = finder.constantsToCompute;
     expect(constants, isNotNull);
     return constants;
   }
@@ -4213,7 +4215,7 @@
    *
    * @param expected the expected result of the operation
    * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
+   * @param rightOperand the right operand to the operation
    * @throws EvaluationException if the result is an exception when it should not be
    */
   void _assertShiftRight(DartObjectImpl expected, DartObjectImpl leftOperand,
diff --git a/pkg/analyzer/test/generated/declaration_resolver_test.dart b/pkg/analyzer/test/generated/declaration_resolver_test.dart
index 4620528..8d6bf51 100644
--- a/pkg/analyzer/test/generated/declaration_resolver_test.dart
+++ b/pkg/analyzer/test/generated/declaration_resolver_test.dart
@@ -302,6 +302,18 @@
     expect(setterName.staticElement, same(setterElement));
   }
 
+  void test_visitFunctionExpression() {
+    String code = r'''
+main(List<String> items) {
+  items.forEach((item) {});
+}
+''';
+    CompilationUnit unit = resolveSource(code);
+    // re-resolve
+    _cloneResolveUnit(unit);
+    // no other validations than built into DeclarationResolver
+  }
+
   void test_visitMethodDeclaration_getter_duplicate() {
     String code = r'''
 class C {
diff --git a/pkg/analyzer/test/generated/error_suppression_test.dart b/pkg/analyzer/test/generated/error_suppression_test.dart
new file mode 100644
index 0000000..560a2c2
--- /dev/null
+++ b/pkg/analyzer/test/generated/error_suppression_test.dart
@@ -0,0 +1,152 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+
+import '../reflective_tests.dart';
+import '../utils.dart';
+import 'resolver_test.dart';
+
+main() {
+  initializeTestEnvironment();
+  runReflectiveTests(ErrorSuppressionTest);
+}
+
+@reflectiveTest
+class ErrorSuppressionTest extends ResolverTestCase {
+  void test_error_code_mismatch() {
+    Source source = addSource('''
+//# ignore: const_initialized_with_non_constant_value
+int x = '';
+const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [
+      StaticTypeWarningCode.INVALID_ASSIGNMENT,
+      CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+    ]);
+  }
+
+  void test_ignore_first() {
+    Source source = addSource('''
+//# ignore: invalid_assignment
+int x = '';
+// ... but no ignore here ...
+const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source,
+        [CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE]);
+  }
+
+  void test_ignore_second() {
+    Source source = addSource('''
+//INVALID_ASSIGNMENT
+int x = '';
+//# ignore: const_initialized_with_non_constant_value
+const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+  }
+
+  void test_invalid_error_code() {
+    Source source = addSource('''
+//# ignore: right_format_wrong_code
+int x = '';
+const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [
+      StaticTypeWarningCode.INVALID_ASSIGNMENT,
+      CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+    ]);
+  }
+
+  void test_missing_error_codes() {
+    Source source = addSource('''
+    int x = 3;
+//# ignore:
+const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [
+      StaticTypeWarningCode.INVALID_ASSIGNMENT,
+      CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+    ]);
+  }
+
+  void test_missing_metadata_prefix() {
+    Source source = addSource('''
+// ignore: invalid_assignment
+String y = 3; //INVALID_ASSIGNMENT
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+  }
+
+  void test_multiple_comments() {
+    Source source = addSource('''
+int x = ''; //This is the first comment...
+//# ignore: const_initialized_with_non_constant_value
+const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+  }
+
+  void test_multiple_ignores() {
+    Source source = addSource('''
+int x = 3;
+//# ignore: invalid_assignment, const_initialized_with_non_constant_value
+const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, []);
+  }
+
+  void test_multiple_ignores_whitespace_variant_1() {
+    Source source = addSource('''
+int x = 3;
+//#ignore:invalid_assignment,const_initialized_with_non_constant_value
+const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, []);
+  }
+
+  void test_multiple_ignores_whitespace_variant_2() {
+    Source source = addSource('''
+int x = 3;
+//#ignore: invalid_assignment,const_initialized_with_non_constant_value
+const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, []);
+  }
+
+  void test_multiple_ignores_whitespace_variant_3() {
+    Source source = addSource('''
+int x = 3;
+//# ignore: invalid_assignment,const_initialized_with_non_constant_value
+const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, []);
+  }
+
+  void test_no_ignores() {
+    Source source = addSource('''
+int x = '';  //INVALID_ASSIGNMENT
+const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [
+      StaticTypeWarningCode.INVALID_ASSIGNMENT,
+      CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index 9e3b75a..5c52f17 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -5,11 +5,14 @@
 library analyzer.test.generated.incremental_resolver_test;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/builder.dart';
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/incremental_logger.dart' as logging;
@@ -18,7 +21,6 @@
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/testing/ast_factory.dart';
 import 'package:analyzer/src/generated/testing/element_factory.dart';
@@ -42,81 +44,81 @@
 
 void initializeTestEnvironment() {}
 
-void _assertEqualError(AnalysisError incrError, AnalysisError fullError) {
-  if (incrError.errorCode != fullError.errorCode ||
-      incrError.source != fullError.source ||
-      incrError.offset != fullError.offset ||
-      incrError.length != fullError.length ||
-      incrError.message != fullError.message) {
+void _assertEqualError(AnalysisError incError, AnalysisError fullError) {
+  if (incError.errorCode != fullError.errorCode ||
+      incError.source != fullError.source ||
+      incError.offset != fullError.offset ||
+      incError.length != fullError.length ||
+      incError.message != fullError.message) {
     StringBuffer buffer = new StringBuffer();
     buffer.writeln('Found error does not match expected error:');
-    if (incrError.errorCode == fullError.errorCode) {
+    if (incError.errorCode == fullError.errorCode) {
       buffer.write('  errorCode = ');
       buffer.write(fullError.errorCode.uniqueName);
     } else {
       buffer.write('  Expected errorCode = ');
       buffer.write(fullError.errorCode.uniqueName);
       buffer.write(' found ');
-      buffer.write(incrError.errorCode.uniqueName);
+      buffer.write(incError.errorCode.uniqueName);
     }
     buffer.writeln();
-    if (incrError.source == fullError.source) {
+    if (incError.source == fullError.source) {
       buffer.write('  source = ');
       buffer.write(fullError.source);
     } else {
       buffer.write('  Expected source = ');
       buffer.write(fullError.source);
       buffer.write(' found ');
-      buffer.write(incrError.source);
+      buffer.write(incError.source);
     }
     buffer.writeln();
-    if (incrError.offset == fullError.offset) {
+    if (incError.offset == fullError.offset) {
       buffer.write('  offset = ');
       buffer.write(fullError.offset);
     } else {
       buffer.write('  Expected offset = ');
       buffer.write(fullError.offset);
       buffer.write(' found ');
-      buffer.write(incrError.offset);
+      buffer.write(incError.offset);
     }
     buffer.writeln();
-    if (incrError.length == fullError.length) {
+    if (incError.length == fullError.length) {
       buffer.write('  length = ');
       buffer.write(fullError.length);
     } else {
       buffer.write('  Expected length = ');
       buffer.write(fullError.length);
       buffer.write(' found ');
-      buffer.write(incrError.length);
+      buffer.write(incError.length);
     }
     buffer.writeln();
-    if (incrError.message == fullError.message) {
+    if (incError.message == fullError.message) {
       buffer.write('  message = ');
       buffer.write(fullError.message);
     } else {
       buffer.write('  Expected message = ');
       buffer.write(fullError.message);
       buffer.write(' found ');
-      buffer.write(incrError.message);
+      buffer.write(incError.message);
     }
     fail(buffer.toString());
   }
 }
 
 void _assertEqualErrors(
-    List<AnalysisError> incrErrors, List<AnalysisError> fullErrors) {
-  expect(incrErrors, hasLength(fullErrors.length));
-  if (incrErrors.isNotEmpty) {
-    incrErrors.sort((a, b) => a.offset - b.offset);
+    List<AnalysisError> incErrors, List<AnalysisError> fullErrors) {
+  expect(incErrors, hasLength(fullErrors.length));
+  if (incErrors.isNotEmpty) {
+    incErrors.sort((a, b) => a.offset - b.offset);
   }
   if (fullErrors.isNotEmpty) {
     fullErrors.sort((a, b) => a.offset - b.offset);
   }
-  int length = incrErrors.length;
+  int length = incErrors.length;
   for (int i = 0; i < length; i++) {
-    AnalysisError incrError = incrErrors[i];
+    AnalysisError incError = incErrors[i];
     AnalysisError fullError = fullErrors[i];
-    _assertEqualError(incrError, fullError);
+    _assertEqualError(incError, fullError);
   }
 }
 
@@ -3611,13 +3613,15 @@
   print(x + 1);
 }
 ''');
-    _updateAndValidate(r'''
+    _updateAndValidate(
+        r'''
 int f() => 0;
 main() {
   const x = f();
   print(x + 2);
 }
-''');
+''',
+        expectCachePostConstantsValid: false);
   }
 
   void test_dartDoc_beforeField() {
@@ -4206,6 +4210,21 @@
 ''');
   }
 
+  void test_hasElementAfter_defaultParameter() {
+    _resolveUnit(r'''
+main() {
+  print(1);
+}
+otherFunction([p = 0]) {}
+''');
+    _updateAndValidate(r'''
+main() {
+  print(2);
+}
+otherFunction([p = 0]) {}
+''');
+  }
+
   void test_inBody_expression() {
     _resolveUnit(r'''
 class A {
@@ -4550,11 +4569,13 @@
   const v = const [Unknown];
 }
 ''');
-    _updateAndValidate(r'''
+    _updateAndValidate(
+        r'''
 main() {
    const v = const [Unknown];
 }
-''');
+''',
+        expectCachePostConstantsValid: false);
   }
 
   void test_updateErrors_addNew_hint1() {
@@ -4828,14 +4849,65 @@
     }
   }
 
-  void _assertEqualLineInfo(LineInfo incrLineInfo, LineInfo fullLineInfo) {
+  void _assertCacheResults({bool expectCachePostConstantsValid: true}) {
+    _assertCacheSourceResult(TOKEN_STREAM);
+    _assertCacheSourceResult(SCAN_ERRORS);
+    _assertCacheSourceResult(PARSED_UNIT);
+    _assertCacheSourceResult(PARSE_ERRORS);
+    _assertCacheSourceResult(LIBRARY_ELEMENT1);
+    _assertCacheSourceResult(LIBRARY_ELEMENT2);
+    _assertCacheSourceResult(LIBRARY_ELEMENT3);
+    _assertCacheSourceResult(LIBRARY_ELEMENT4);
+    _assertCacheSourceResult(LIBRARY_ELEMENT5);
+    _assertCacheSourceResult(LIBRARY_ELEMENT6);
+    _assertCacheSourceResult(LIBRARY_ELEMENT7);
+    _assertCacheSourceResult(LIBRARY_ELEMENT8);
+    if (expectCachePostConstantsValid) {
+      _assertCacheSourceResult(LIBRARY_ELEMENT);
+    }
+    _assertCacheUnitResult(RESOLVED_UNIT1);
+    _assertCacheUnitResult(RESOLVED_UNIT2);
+    _assertCacheUnitResult(RESOLVED_UNIT3);
+    _assertCacheUnitResult(RESOLVED_UNIT4);
+    _assertCacheUnitResult(RESOLVED_UNIT5);
+    _assertCacheUnitResult(RESOLVED_UNIT6);
+    _assertCacheUnitResult(RESOLVED_UNIT7);
+    _assertCacheUnitResult(RESOLVED_UNIT8);
+    _assertCacheUnitResult(RESOLVED_UNIT9);
+    _assertCacheUnitResult(RESOLVED_UNIT10);
+    if (expectCachePostConstantsValid) {
+      _assertCacheUnitResult(RESOLVED_UNIT11);
+      _assertCacheUnitResult(RESOLVED_UNIT);
+    }
+  }
+
+  /**
+   * Assert that the [result] of [source] is not INVALID.
+   */
+  void _assertCacheSourceResult(ResultDescriptor result) {
+    AnalysisCache cache = analysisContext2.analysisCache;
+    CacheState state = cache.getState(source, result);
+    expect(state, isNot(CacheState.INVALID), reason: result.toString());
+  }
+
+  /**
+   * Assert that the [result] of the defining unit [source] is not INVALID.
+   */
+  void _assertCacheUnitResult(ResultDescriptor result) {
+    AnalysisCache cache = analysisContext2.analysisCache;
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    CacheState state = cache.getState(target, result);
+    expect(state, isNot(CacheState.INVALID), reason: result.toString());
+  }
+
+  void _assertEqualLineInfo(LineInfo incLineInfo, LineInfo fullLineInfo) {
     for (int offset = 0; offset < 1000; offset++) {
-      LineInfo_Location incrLocation = incrLineInfo.getLocation(offset);
+      LineInfo_Location incLocation = incLineInfo.getLocation(offset);
       LineInfo_Location fullLocation = fullLineInfo.getLocation(offset);
-      if (incrLocation.lineNumber != fullLocation.lineNumber ||
-          incrLocation.columnNumber != fullLocation.columnNumber) {
+      if (incLocation.lineNumber != fullLocation.lineNumber ||
+          incLocation.columnNumber != fullLocation.columnNumber) {
         fail('At offset $offset ' +
-            '(${incrLocation.lineNumber}, ${incrLocation.columnNumber})' +
+            '(${incLocation.lineNumber}, ${incLocation.columnNumber})' +
             ' != ' +
             '(${fullLocation.lineNumber}, ${fullLocation.columnNumber})');
       }
@@ -4871,6 +4943,7 @@
 
   void _updateAndValidate(String newCode,
       {bool expectedSuccess: true,
+      bool expectCachePostConstantsValid: true,
       bool compareWithFull: true,
       bool runTasksBeforeIncremental: true}) {
     // Run any pending tasks tasks.
@@ -4890,6 +4963,10 @@
       expect(newUnit.element, isNot(same(oldUnitElement)));
       return;
     }
+    // The cache must still have enough results to make the incremental
+    // resolution useful.
+    _assertCacheResults(
+        expectCachePostConstantsValid: expectCachePostConstantsValid);
     // The existing CompilationUnit[Element] should be updated.
     expect(newUnit, same(oldUnit));
     expect(newUnit.element, same(oldUnitElement));
@@ -4925,37 +5002,37 @@
     _checkCacheEntries(analysisContext2.analysisCache);
   }
 
-  static void _assertEqualToken(Token incrToken, Token fullToken) {
-//    print('[${incrToken.offset}] |$incrToken| vs. [${fullToken.offset}] |$fullToken|');
-    expect(incrToken.type, fullToken.type);
-    expect(incrToken.offset, fullToken.offset);
-    expect(incrToken.length, fullToken.length);
-    expect(incrToken.lexeme, fullToken.lexeme);
+  static void _assertEqualToken(Token incToken, Token fullToken) {
+//    print('[${incToken.offset}] |$incToken| vs. [${fullToken.offset}] |$fullToken|');
+    expect(incToken.type, fullToken.type);
+    expect(incToken.offset, fullToken.offset);
+    expect(incToken.length, fullToken.length);
+    expect(incToken.lexeme, fullToken.lexeme);
   }
 
   static void _assertEqualTokens(
-      CompilationUnit incrUnit, CompilationUnit fullUnit) {
-    Token incrToken = incrUnit.beginToken;
+      CompilationUnit incUnit, CompilationUnit fullUnit) {
+    Token incToken = incUnit.beginToken;
     Token fullToken = fullUnit.beginToken;
-    while (incrToken.type != TokenType.EOF && fullToken.type != TokenType.EOF) {
-      _assertEqualToken(incrToken, fullToken);
+    while (incToken.type != TokenType.EOF && fullToken.type != TokenType.EOF) {
+      _assertEqualToken(incToken, fullToken);
       // comments
       {
-        Token incrComment = incrToken.precedingComments;
+        Token incComment = incToken.precedingComments;
         Token fullComment = fullToken.precedingComments;
         while (true) {
           if (fullComment == null) {
-            expect(incrComment, isNull);
+            expect(incComment, isNull);
             break;
           }
-          expect(incrComment, isNotNull);
-          _assertEqualToken(incrComment, fullComment);
-          incrComment = incrComment.next;
+          expect(incComment, isNotNull);
+          _assertEqualToken(incComment, fullComment);
+          incComment = incComment.next;
           fullComment = fullComment.next;
         }
       }
       // next tokens
-      incrToken = incrToken.next;
+      incToken = incToken.next;
       fullToken = fullToken.next;
     }
   }
diff --git a/pkg/analyzer/test/generated/incremental_scanner_test.dart b/pkg/analyzer/test/generated/incremental_scanner_test.dart
index fad6244..2c21e61 100644
--- a/pkg/analyzer/test/generated/incremental_scanner_test.dart
+++ b/pkg/analyzer/test/generated/incremental_scanner_test.dart
@@ -4,9 +4,11 @@
 
 library analyzer.test.generated.incremental_scanner_test;
 
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/incremental_scanner.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:unittest/unittest.dart';
 
diff --git a/pkg/analyzer/test/generated/java_core_test.dart b/pkg/analyzer/test/generated/java_core_test.dart
index 0a914ec..f98895e 100644
--- a/pkg/analyzer/test/generated/java_core_test.dart
+++ b/pkg/analyzer/test/generated/java_core_test.dart
@@ -12,30 +12,6 @@
 main() {
   initializeTestEnvironment();
   group('Character', () {
-    group('isDigit', () {
-      test('digits', () {
-        expect(Character.isDigit('0'.codeUnitAt(0)), isTrue);
-        expect(Character.isDigit('1'.codeUnitAt(0)), isTrue);
-        expect(Character.isDigit('9'.codeUnitAt(0)), isTrue);
-      });
-
-      test('letters', () {
-        expect(Character.isDigit('a'.codeUnitAt(0)), isFalse);
-        expect(Character.isDigit('b'.codeUnitAt(0)), isFalse);
-        expect(Character.isDigit('z'.codeUnitAt(0)), isFalse);
-        expect(Character.isDigit('C'.codeUnitAt(0)), isFalse);
-        expect(Character.isDigit('D'.codeUnitAt(0)), isFalse);
-        expect(Character.isDigit('Y'.codeUnitAt(0)), isFalse);
-      });
-
-      test('other', () {
-        expect(Character.isDigit(' '.codeUnitAt(0)), isFalse);
-        expect(Character.isDigit('.'.codeUnitAt(0)), isFalse);
-        expect(Character.isDigit('-'.codeUnitAt(0)), isFalse);
-        expect(Character.isDigit('+'.codeUnitAt(0)), isFalse);
-      });
-    });
-
     group('isLetter', () {
       test('digits', () {
         expect(Character.isLetter('0'.codeUnitAt(0)), isFalse);
@@ -83,73 +59,5 @@
         expect(Character.isLetterOrDigit('+'.codeUnitAt(0)), isFalse);
       });
     });
-
-    group('isLowerCase', () {
-      test('ASCII digits', () {
-        expect(Character.isLowerCase('0'.codeUnitAt(0)), isFalse);
-        expect(Character.isLowerCase('9'.codeUnitAt(0)), isFalse);
-      });
-
-      test('ASCII lower', () {
-        expect(Character.isLowerCase('a'.codeUnitAt(0)), isTrue);
-        expect(Character.isLowerCase('s'.codeUnitAt(0)), isTrue);
-        expect(Character.isLowerCase('z'.codeUnitAt(0)), isTrue);
-      });
-
-      test('ASCII upper', () {
-        expect(Character.isLowerCase('A'.codeUnitAt(0)), isFalse);
-        expect(Character.isLowerCase('S'.codeUnitAt(0)), isFalse);
-        expect(Character.isLowerCase('Z'.codeUnitAt(0)), isFalse);
-      });
-    });
-
-    group('isUpperCase', () {
-      test('ASCII digits', () {
-        expect(Character.isUpperCase('0'.codeUnitAt(0)), isFalse);
-        expect(Character.isUpperCase('9'.codeUnitAt(0)), isFalse);
-      });
-
-      test('ASCII lower', () {
-        expect(Character.isUpperCase('a'.codeUnitAt(0)), isFalse);
-        expect(Character.isUpperCase('s'.codeUnitAt(0)), isFalse);
-        expect(Character.isUpperCase('z'.codeUnitAt(0)), isFalse);
-      });
-
-      test('ASCII upper', () {
-        expect(Character.isUpperCase('A'.codeUnitAt(0)), isTrue);
-        expect(Character.isUpperCase('S'.codeUnitAt(0)), isTrue);
-        expect(Character.isUpperCase('Z'.codeUnitAt(0)), isTrue);
-      });
-    });
-
-    test('toLowerCase', () {
-      expect(Character.toLowerCase('A'.codeUnitAt(0)), 'a'.codeUnitAt(0));
-      expect(Character.toLowerCase('B'.codeUnitAt(0)), 'b'.codeUnitAt(0));
-      expect(Character.toLowerCase('Z'.codeUnitAt(0)), 'z'.codeUnitAt(0));
-      expect(Character.toLowerCase('c'.codeUnitAt(0)), 'c'.codeUnitAt(0));
-      expect(Character.toLowerCase('0'.codeUnitAt(0)), '0'.codeUnitAt(0));
-    });
-
-    test('toUpperCase', () {
-      expect(Character.toUpperCase('a'.codeUnitAt(0)), 'A'.codeUnitAt(0));
-      expect(Character.toUpperCase('b'.codeUnitAt(0)), 'B'.codeUnitAt(0));
-      expect(Character.toUpperCase('z'.codeUnitAt(0)), 'Z'.codeUnitAt(0));
-      expect(Character.toUpperCase('C'.codeUnitAt(0)), 'C'.codeUnitAt(0));
-      expect(Character.toUpperCase('0'.codeUnitAt(0)), '0'.codeUnitAt(0));
-    });
-
-    test('isWhitespace', () {
-      expect(Character.isWhitespace('\t'.codeUnitAt(0)), isTrue);
-      expect(Character.isWhitespace(' '.codeUnitAt(0)), isTrue);
-      expect(Character.isWhitespace('\n'.codeUnitAt(0)), isTrue);
-      expect(Character.isWhitespace('\r'.codeUnitAt(0)), isTrue);
-      expect(Character.isWhitespace('.'.codeUnitAt(0)), isFalse);
-      expect(Character.isWhitespace('0'.codeUnitAt(0)), isFalse);
-      expect(Character.isWhitespace('9'.codeUnitAt(0)), isFalse);
-      expect(Character.isWhitespace('a'.codeUnitAt(0)), isFalse);
-      expect(Character.isWhitespace('z'.codeUnitAt(0)), isFalse);
-      expect(Character.isWhitespace('A'.codeUnitAt(0)), isFalse);
-      expect(Character.isWhitespace('Z'.codeUnitAt(0)), isFalse);
-    });
   });
 }
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 2b33566..72186b4 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -5,16 +5,19 @@
 library analyzer.test.generated.parser_test;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/incremental_scanner.dart';
 import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart' show Source;
 import 'package:analyzer/src/generated/testing/ast_factory.dart';
 import 'package:analyzer/src/generated/testing/element_factory.dart';
@@ -505,6 +508,16 @@
         BinaryExpression, expression.leftOperand);
   }
 
+  void test_topLevelFunction_nestedGenericFunction() {
+    enableGenericMethods = true;
+    parseCompilationUnitWithOptions('''
+void f() {
+  void g<T>() {
+  }
+}
+''');
+  }
+
   void _validate_assignableExpression_arguments_normal_chain_typeArguments(
       String code) {
     PropertyAccess propertyAccess1 = parseExpression(code);
@@ -2871,6 +2884,30 @@
       parse3(methodName, _EMPTY_ARGUMENTS, source, errorCodes);
 
   /**
+   * Parse the given [source] as a compilation unit. Throw an exception if the
+   * source could not be parsed, if the compilation errors in the source do not
+   * match those that are expected, or if the result would have been `null`.
+   */
+  CompilationUnit parseCompilationUnitWithOptions(String source,
+      [List<ErrorCode> errorCodes = ErrorCode.EMPTY_LIST]) {
+    GatheringErrorListener listener = new GatheringErrorListener();
+    Scanner scanner =
+        new Scanner(null, new CharSequenceReader(source), listener);
+    listener.setLineInfo(new TestSource(), scanner.lineStarts);
+    Token token = scanner.tokenize();
+    Parser parser = createParser(listener);
+    parser.parseAsync = parseAsync;
+    parser.parseFunctionBodies = parseFunctionBodies;
+    parser.parseConditionalDirectives = enableConditionalDirectives;
+    parser.parseGenericMethods = enableGenericMethods;
+    parser.parseGenericMethodComments = enableGenericMethodComments;
+    CompilationUnit unit = parser.parseCompilationUnit(token);
+    expect(unit, isNotNull);
+    listener.assertErrorsWithCodes(errorCodes);
+    return unit;
+  }
+
+  /**
    * Parse the given source as an expression.
    *
    * @param source the source to be parsed
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 01b0b73..4210fef 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -7,6 +7,7 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -23,7 +24,6 @@
 import 'package:analyzer/src/generated/java_io.dart';
 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk;
 import 'package:analyzer/src/generated/source_io.dart';
@@ -7868,6 +7868,11 @@
     if (node.name == "void") {
       return null;
     }
+    if (node.staticType != null &&
+        node.staticType.isDynamic &&
+        node.staticElement == null) {
+      return null;
+    }
     AstNode parent = node.parent;
     if (parent is MethodInvocation) {
       MethodInvocation invocation = parent;
@@ -10225,6 +10230,79 @@
       expect(type.name, 'Foo');
     }
   }
+
+  void test_staticMethods_classTypeParameters() {
+    String code = r'''
+class C<T> {
+  static void m() => null;
+}
+main() {
+  print(C.m);
+}
+''';
+    _resolveTestUnit(code);
+    SimpleIdentifier identifier = _findIdentifier('m);');
+    FunctionTypeImpl type = identifier.staticType;
+    expect(type.toString(), '() → void');
+    expect(type.typeParameters, isEmpty,
+        reason: 'static methods should not have type parameters');
+    expect(type.typeArguments, isEmpty,
+        reason: 'static methods should not have type arguments');
+    expect(type.typeFormals, isEmpty,
+        reason: 'this static method is not generic');
+  }
+
+  void test_staticMethods_classTypeParameters_genericMethod() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableGenericMethods = true;
+    resetWithOptions(options);
+    String code = r'''
+class C<T> {
+  static void m<S>(S s) {
+    void f<U>(S s, U u) {}
+    print(f);
+  }
+}
+main() {
+  print(C.m);
+}
+''';
+    _resolveTestUnit(code);
+    // C - m
+    TypeParameterType typeS;
+    {
+      SimpleIdentifier identifier = _findIdentifier('m);');
+      FunctionTypeImpl type = identifier.staticType;
+      expect(type.toString(), '<S>(S) → void');
+      expect(type.typeParameters, isEmpty,
+          reason: 'static methods should not have type parameters');
+      expect(type.typeArguments, isEmpty,
+          reason: 'static methods should not have type arguments');
+      expect(type.typeFormals.toString(), '[S]');
+      typeS = type.typeFormals[0].type;
+
+      type = type.instantiate([DynamicTypeImpl.instance]);
+      expect(type.toString(), '(dynamic) → void');
+      expect(type.typeParameters.toString(), '[S]');
+      expect(type.typeArguments, [DynamicTypeImpl.instance]);
+      expect(type.typeFormals, isEmpty);
+    }
+    // C - m - f
+    {
+      SimpleIdentifier identifier = _findIdentifier('f);');
+      FunctionTypeImpl type = identifier.staticType;
+      expect(type.toString(), '<U>(S, U) → void');
+      expect(type.typeParameters.toString(), '[S]');
+      expect(type.typeArguments.toString(), '[S]');
+      expect(type.typeFormals.toString(), '[U]');
+
+      type = type.instantiate([DynamicTypeImpl.instance]);
+      expect(type.toString(), '(S, dynamic) → void');
+      expect(type.typeParameters.toString(), '[S, U]');
+      expect(type.typeArguments, [typeS, DynamicTypeImpl.instance]);
+      expect(type.typeFormals, isEmpty);
+    }
+  }
 }
 
 @reflectiveTest
@@ -13388,11 +13466,8 @@
     MethodElementImpl e = f.staticElement;
     expect(e.typeParameters.toString(), '[T]');
     expect(e.type.typeFormals.toString(), '[T]');
-    // TODO(jmesserly): we could get rid of this {E/E} substitution, but it's
-    // probably harmless, as E won't be used in the function (error verifier
-    // checks this), and {E/E} is a no-op anyway.
-    expect(e.type.typeParameters.toString(), '[E]');
-    expect(e.type.typeArguments.toString(), '[E]');
+    expect(e.type.typeParameters.toString(), '[]');
+    expect(e.type.typeArguments.toString(), '[]');
     expect(e.type.toString(), '<T>(T) → T');
 
     FunctionType ft = e.type.instantiate([typeProvider.stringType]);
@@ -13779,6 +13854,18 @@
     expect(declaration.initializer.propagatedType, isNull);
   }
 
+  void test_genericMethod_nestedBound() {
+    String code = r'''
+class Foo<T extends num> {
+  void method/*<U extends T>*/(dynamic/*=U*/ u) {
+    u.abs();
+  }
+}
+''';
+    // Just validate that there is no warning on the call to `.abs()`.
+    _resolveTestUnit(code);
+  }
+
   void test_genericMethod_nestedCapture() {
     _resolveTestUnit(r'''
 class C<T> {
@@ -13855,6 +13942,11 @@
     // TODO(jmesserly): we can't use assertErrors because STRONG_MODE_* errors
     // from CodeChecker don't have working equality.
     List<AnalysisError> errors = analysisContext2.computeErrors(source);
+
+    // Sort errors by name.
+    errors.sort((AnalysisError e1, AnalysisError e2) =>
+        e1.errorCode.name.compareTo(e2.errorCode.name));
+
     expect(errors.map((e) => e.errorCode.name), [
       'INVALID_METHOD_OVERRIDE_RETURN_TYPE',
       'STRONG_MODE_INVALID_METHOD_OVERRIDE'
diff --git a/pkg/analyzer/test/generated/scanner_test.dart b/pkg/analyzer/test/generated/scanner_test.dart
index d0d8949..071231e 100644
--- a/pkg/analyzer/test/generated/scanner_test.dart
+++ b/pkg/analyzer/test/generated/scanner_test.dart
@@ -4,8 +4,11 @@
 
 library analyzer.test.generated.scanner_test;
 
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:unittest/unittest.dart';
 
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
index cfab206..5f5d0ef 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -6,7 +6,9 @@
 
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_core.dart' show formatList;
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:unittest/unittest.dart';
 
 import '../reflective_tests.dart';
 import '../utils.dart';
@@ -15,6 +17,7 @@
 main() {
   initializeTestEnvironment();
   runReflectiveTests(StaticTypeWarningCodeTest);
+  runReflectiveTests(StrongModeStaticTypeWarningCodeTest);
 }
 
 @reflectiveTest
@@ -2153,3 +2156,33 @@
     verify([source]);
   }
 }
+
+@reflectiveTest
+class StrongModeStaticTypeWarningCodeTest extends ResolverTestCase {
+  void setUp() {
+    super.setUp();
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.strongMode = true;
+    resetWithOptions(options);
+  }
+
+  void test_genericMethodWrongNumberOfTypeArguments() {
+    Source source = addSource('''
+f() {}
+main() {
+  f/*<int>*/();
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source, [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
+    for (AnalysisError error in analysisContext2.computeErrors(source)) {
+      if (error.errorCode ==
+          StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS) {
+        expect(error.message,
+            formatList(error.errorCode.message, ['() → dynamic', 0, 1]));
+      }
+    }
+    verify([source]);
+  }
+}
diff --git a/pkg/analyzer/test/generated/test_all.dart b/pkg/analyzer/test/generated/test_all.dart
index 8a0b3d2..4785daf 100644
--- a/pkg/analyzer/test/generated/test_all.dart
+++ b/pkg/analyzer/test/generated/test_all.dart
@@ -12,6 +12,7 @@
 import 'constant_test.dart' as constant_test;
 import 'declaration_resolver_test.dart' as declaration_resolver_test;
 import 'engine_test.dart' as engine_test;
+import 'error_suppression_test.dart' as error_suppression_test;
 import 'incremental_resolver_test.dart' as incremental_resolver_test;
 import 'incremental_scanner_test.dart' as incremental_scanner_test;
 import 'java_core_test.dart' as java_core_test;
@@ -35,6 +36,7 @@
     constant_test.main();
     declaration_resolver_test.main();
     engine_test.main();
+    error_suppression_test.main();
     incremental_resolver_test.main();
     incremental_scanner_test.main();
     java_core_test.main();
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index 5e6cfa4..51f5fcd 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -6,8 +6,7 @@
 
 import 'dart:collection';
 
-import 'package:analyzer/dart/ast/ast.dart'
-    show AstNode, SimpleIdentifier;
+import 'package:analyzer/dart/ast/ast.dart' show AstNode, SimpleIdentifier;
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
@@ -647,6 +646,8 @@
   TestSourceWithUri(String path, this.uri, [String content])
       : super(path, content);
 
+  String get encoding => uri.toString();
+
   UriKind get uriKind {
     if (uri == null) {
       return UriKind.FILE_URI;
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index 32b2487..f2a2a9e 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -7,11 +7,14 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/java_engine.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/generated/testing/ast_factory.dart';
 import 'package:analyzer/src/generated/testing/token_factory.dart';
@@ -278,6 +281,13 @@
     _assertCloneUnit('library l;  var a;');
   }
 
+  void test_visitCompilationUnit_directive_withComment() {
+    _assertCloneUnit(r'''
+/// aaa
+/// bbb
+library l;''');
+  }
+
   void test_visitCompilationUnit_empty() {
     _assertCloneUnit('');
   }
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart
index 326e6a2..cbcfacf 100644
--- a/pkg/analyzer/test/src/context/context_test.dart
+++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -16,11 +16,11 @@
 import 'package:analyzer/src/cancelable_future.dart';
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_collection.dart';
 import 'package:analyzer/src/task/dart.dart';
diff --git a/pkg/analyzer/test/src/context/mock_sdk.dart b/pkg/analyzer/test/src/context/mock_sdk.dart
index b67c4a5..9bf1b79 100644
--- a/pkg/analyzer/test/src/context/mock_sdk.dart
+++ b/pkg/analyzer/test/src/context/mock_sdk.dart
@@ -13,11 +13,10 @@
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 
-class MockSdk implements DartSdk {
-  static const _MockSdkLibrary LIB_CORE = const _MockSdkLibrary(
-      'dart:core',
-      '/lib/core/core.dart',
-      '''
+const _MockSdkLibrary _LIB_CORE = const _MockSdkLibrary(
+    'dart:core',
+    '/lib/core/core.dart',
+    '''
 library dart.core;
 
 import 'dart:async';
@@ -40,9 +39,11 @@
 abstract class String implements Comparable<String> {
   external factory String.fromCharCodes(Iterable<int> charCodes,
                                         [int start = 0, int end]);
+  String operator +(String other) => null;
   bool get isEmpty => false;
   bool get isNotEmpty => false;
   int get length => 0;
+  String substring(int len) => null;
   String toUpperCase();
   List<int> get codeUnits;
 }
@@ -115,10 +116,10 @@
 const Object override = const _Override();
 ''');
 
-  static const _MockSdkLibrary LIB_ASYNC = const _MockSdkLibrary(
-      'dart:async',
-      '/lib/async/async.dart',
-      '''
+const _MockSdkLibrary _LIB_ASYNC = const _MockSdkLibrary(
+    'dart:async',
+    '/lib/async/async.dart',
+    '''
 library dart.async;
 
 import 'dart:math';
@@ -126,37 +127,36 @@
 part 'stream.dart';
 
 class Future<T> {
+  factory Future(computation()) => null;
   factory Future.delayed(Duration duration, [T computation()]) => null;
-  factory Future.value([value]) => null;
+  factory Future.value([T value]) => null;
 
-  static Future<List</*<T>*/> wait/*<T>*/(
+  static Future<List/*<T>*/> wait/*<T>*/(
       Iterable<Future/*<T>*/> futures) => null;
   Future/*<R>*/ then/*<R>*/(/*=R*/ onValue(T value)) => null;
 }
 ''',
-      const <_MockSdkFile>[
-    const _MockSdkFile(
-        '/lib/async/stream.dart',
-        r'''
+    const <String, String>{
+      '/lib/async/stream.dart': r'''
 part of dart.async;
 class Stream<T> {}
 abstract class StreamTransformer<S, T> {}
-''')
-  ]);
+'''
+    });
 
-  static const _MockSdkLibrary LIB_COLLECTION = const _MockSdkLibrary(
-      'dart:collection',
-      '/lib/collection/collection.dart',
-      '''
+const _MockSdkLibrary _LIB_COLLECTION = const _MockSdkLibrary(
+    'dart:collection',
+    '/lib/collection/collection.dart',
+    '''
 library dart.collection;
 
 abstract class HashMap<K, V> implements Map<K, V> {}
 ''');
 
-  static const _MockSdkLibrary LIB_CONVERT = const _MockSdkLibrary(
-      'dart:convert',
-      '/lib/convert/convert.dart',
-      '''
+const _MockSdkLibrary _LIB_CONVERT = const _MockSdkLibrary(
+    'dart:convert',
+    '/lib/convert/convert.dart',
+    '''
 library dart.convert;
 
 import 'dart:async';
@@ -165,10 +165,21 @@
 class JsonDecoder extends Converter<String, Object> {}
 ''');
 
-  static const _MockSdkLibrary LIB_MATH = const _MockSdkLibrary(
-      'dart:math',
-      '/lib/math/math.dart',
-      '''
+const _MockSdkLibrary _LIB_FOREIGN_HELPER = const _MockSdkLibrary(
+    'dart:_foreign_helper',
+    '/lib/_foreign_helper/_foreign_helper.dart',
+    '''
+library dart._foreign_helper;
+
+JS(String typeDescription, String codeTemplate,
+  [arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11])
+{}
+''');
+
+const _MockSdkLibrary _LIB_MATH = const _MockSdkLibrary(
+    'dart:math',
+    '/lib/math/math.dart',
+    '''
 library dart.math;
 
 const double E = 2.718281828459045;
@@ -188,23 +199,25 @@
 }
 ''');
 
-  static const _MockSdkLibrary LIB_HTML = const _MockSdkLibrary(
-      'dart:html',
-      '/lib/html/dartium/html_dartium.dart',
-      '''
+const _MockSdkLibrary _LIB_HTML = const _MockSdkLibrary(
+    'dart:html',
+    '/lib/html/dartium/html_dartium.dart',
+    '''
 library dart.html;
 class HtmlElement {}
 ''');
 
-  static const List<SdkLibrary> LIBRARIES = const [
-    LIB_CORE,
-    LIB_ASYNC,
-    LIB_COLLECTION,
-    LIB_CONVERT,
-    LIB_MATH,
-    LIB_HTML,
-  ];
+const List<SdkLibrary> _LIBRARIES = const [
+  _LIB_CORE,
+  _LIB_ASYNC,
+  _LIB_COLLECTION,
+  _LIB_CONVERT,
+  _LIB_FOREIGN_HELPER,
+  _LIB_MATH,
+  _LIB_HTML,
+];
 
+class MockSdk implements DartSdk {
   final resource.MemoryResourceProvider provider =
       new resource.MemoryResourceProvider();
 
@@ -213,13 +226,14 @@
    */
   AnalysisContextImpl _analysisContext;
 
-  MockSdk() {
-    LIBRARIES.forEach((_MockSdkLibrary library) {
+  MockSdk({bool dartAsync: true})
+      : sdkLibraries = dartAsync ? _LIBRARIES : [_LIB_CORE] {
+    for (_MockSdkLibrary library in sdkLibraries) {
       provider.newFile(library.path, library.content);
-      library.parts.forEach((file) {
-        provider.newFile(file.path, file.content);
+      library.parts.forEach((String path, String content) {
+        provider.newFile(path, content);
       });
-    });
+    }
   }
 
   @override
@@ -233,21 +247,14 @@
   }
 
   @override
-  List<SdkLibrary> get sdkLibraries => LIBRARIES;
+  final List<SdkLibrary> sdkLibraries;
 
   @override
-  String get sdkVersion => throw unimplemented;
-
-  UnimplementedError get unimplemented => new UnimplementedError();
+  String get sdkVersion => throw new UnimplementedError();
 
   @override
-  List<String> get uris {
-    List<String> uris = <String>[];
-    for (SdkLibrary library in LIBRARIES) {
-      uris.add(library.shortName);
-    }
-    return uris;
-  }
+  List<String> get uris =>
+      sdkLibraries.map((SdkLibrary library) => library.shortName).toList();
 
   @override
   Source fromFileUri(Uri uri) {
@@ -256,7 +263,7 @@
     if (!filePath.startsWith("$libPath/")) {
       return null;
     }
-    for (SdkLibrary library in LIBRARIES) {
+    for (SdkLibrary library in sdkLibraries) {
       String libraryPath = library.path;
       if (filePath.replaceAll('\\', '/') == libraryPath) {
         try {
@@ -299,6 +306,7 @@
       "dart:async/stream.dart": "/lib/async/stream.dart",
       "dart:collection": "/lib/collection/collection.dart",
       "dart:convert": "/lib/convert/convert.dart",
+      "dart:_foreign_helper": "/lib/_foreign_helper/_foreign_helper.dart",
       "dart:math": "/lib/math/math.dart"
     };
 
@@ -315,44 +323,35 @@
   }
 }
 
-class _MockSdkFile {
-  final String path;
-  final String content;
-
-  const _MockSdkFile(this.path, this.content);
-}
-
 class _MockSdkLibrary implements SdkLibrary {
   final String shortName;
   final String path;
   final String content;
-  final List<_MockSdkFile> parts;
+  final Map<String, String> parts;
 
   const _MockSdkLibrary(this.shortName, this.path, this.content,
-      [this.parts = const <_MockSdkFile>[]]);
+      [this.parts = const <String, String>{}]);
 
   @override
-  String get category => throw unimplemented;
+  String get category => throw new UnimplementedError();
 
   @override
-  bool get isDart2JsLibrary => throw unimplemented;
+  bool get isDart2JsLibrary => throw new UnimplementedError();
 
   @override
-  bool get isDocumented => throw unimplemented;
+  bool get isDocumented => throw new UnimplementedError();
 
   @override
-  bool get isImplementation => throw unimplemented;
+  bool get isImplementation => throw new UnimplementedError();
 
   @override
-  bool get isInternal => throw unimplemented;
+  bool get isInternal => throw new UnimplementedError();
 
   @override
-  bool get isShared => throw unimplemented;
+  bool get isShared => throw new UnimplementedError();
 
   @override
-  bool get isVmLibrary => throw unimplemented;
-
-  UnimplementedError get unimplemented => new UnimplementedError();
+  bool get isVmLibrary => throw new UnimplementedError();
 }
 
 /**
diff --git a/pkg/analyzer/test/src/dart/ast/utilities_test.dart b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
index 8531637..f3a0e4c 100644
--- a/pkg/analyzer/test/src/dart/ast/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
@@ -5,11 +5,11 @@
 library analyzer.test.src.dart.ast.utilities_test;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/java_engine.dart' show Predicate;
 import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/testing/ast_factory.dart';
 import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:unittest/unittest.dart';
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index 3f0aa84..f907ae3 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -1857,6 +1857,14 @@
     expect(paramType.prunedTypedefs[0], same(f));
   }
 
+  void test_resolveToBound() {
+    FunctionElementImpl f = ElementFactory.functionElement('f');
+    FunctionTypeImpl type = f.type;
+
+    // Returns this.
+    expect(type.resolveToBound(null), same(type));
+  }
+
   void test_returnType_pruned_no_type_arguments() {
     FunctionTypeAliasElementImpl f =
         ElementFactory.functionTypeAliasElement('f');
@@ -3392,6 +3400,14 @@
     expect(typeA.lookUpSetter("s", library), isNull);
   }
 
+  void test_resolveToBound() {
+    InterfaceTypeImpl type =
+        ElementFactory.classElement2("A").type as InterfaceTypeImpl;
+
+    // Returns this.
+    expect(type.resolveToBound(null), same(type));
+  }
+
   void test_setTypeArguments() {
     InterfaceTypeImpl type =
         ElementFactory.classElement2("A").type as InterfaceTypeImpl;
@@ -3936,6 +3952,36 @@
     expect(typeParameterTypeT.isMoreSpecificThan(classS.type), isTrue);
   }
 
+  void test_resolveToBound_unbound() {
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(
+        new TypeParameterElementImpl.forNode(AstFactory.identifier3("E")));
+    // Returns whatever type is passed to resolveToBound().
+    expect(type.resolveToBound(VoidTypeImpl.instance),
+        same(VoidTypeImpl.instance));
+  }
+
+  void test_resolveToBound_bound() {
+    ClassElementImpl classS = ElementFactory.classElement2("A");
+    TypeParameterElementImpl element =
+    new TypeParameterElementImpl.forNode(AstFactory.identifier3("E"));
+    element.bound = classS.type;
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
+    expect(type.resolveToBound(null), same(classS.type));
+  }
+
+  void test_resolveToBound_nestedBound() {
+    ClassElementImpl classS = ElementFactory.classElement2("A");
+    TypeParameterElementImpl elementE =
+    new TypeParameterElementImpl.forNode(AstFactory.identifier3("E"));
+    elementE.bound = classS.type;
+    TypeParameterTypeImpl typeE = new TypeParameterTypeImpl(elementE);
+    TypeParameterElementImpl elementF =
+    new TypeParameterElementImpl.forNode(AstFactory.identifier3("F"));
+    elementF.bound = typeE;
+    TypeParameterTypeImpl typeF = new TypeParameterTypeImpl(elementE);
+    expect(typeF.resolveToBound(null), same(classS.type));
+  }
+
   void test_substitute_equal() {
     TypeParameterElementImpl element =
         new TypeParameterElementImpl.forNode(AstFactory.identifier3("E"));
@@ -3995,6 +4041,11 @@
   void test_isVoid() {
     expect(_voidType.isVoid, isTrue);
   }
+
+  void test_resolveToBound() {
+    // Returns this.
+    expect(_voidType.resolveToBound(null), same(_voidType));
+  }
 }
 
 class _FunctionTypeImplTest_isSubtypeOf_baseCase_classFunction
diff --git a/pkg/analyzer/test/src/mock_sdk.dart b/pkg/analyzer/test/src/mock_sdk.dart
deleted file mode 100644
index bfef108..0000000
--- a/pkg/analyzer/test/src/mock_sdk.dart
+++ /dev/null
@@ -1,327 +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 analyzer.test.src.mock_sdk;
-
-import 'package:analyzer/file_system/file_system.dart' as resource;
-import 'package:analyzer/file_system/memory_file_system.dart' as resource;
-import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-
-class MockSdk implements DartSdk {
-  static const _MockSdkLibrary LIB_CORE = const _MockSdkLibrary(
-      'dart:core',
-      '/lib/core/core.dart',
-      '''
-library dart.core;
-
-import 'dart:async';
-
-class Object {
-  bool operator ==(other) => identical(this, other);
-  String toString() => 'a string';
-  int get hashCode => 0;
-}
-
-class Function {}
-class StackTrace {}
-class Symbol {}
-class Type {}
-
-abstract class Comparable<T> {
-  int compareTo(T other);
-}
-
-abstract class String implements Comparable<String> {
-  external factory String.fromCharCodes(Iterable<int> charCodes,
-                                        [int start = 0, int end]);
-  bool get isEmpty => false;
-  bool get isNotEmpty => false;
-  int get length => 0;
-  String toUpperCase();
-  List<int> get codeUnits;
-}
-
-class bool extends Object {}
-abstract class num implements Comparable<num> {
-  bool operator <(num other);
-  bool operator <=(num other);
-  bool operator >(num other);
-  bool operator >=(num other);
-  num operator +(num other);
-  num operator -(num other);
-  num operator *(num other);
-  num operator /(num other);
-  int toInt();
-  num abs();
-  int round();
-}
-abstract class int extends num {
-  bool get isEven => false;
-  int operator -();
-  external static int parse(String source,
-                            { int radix,
-                              int onError(String source) });
-}
-class double extends num {}
-class DateTime extends Object {}
-class Null extends Object {}
-
-class Deprecated extends Object {
-  final String expires;
-  const Deprecated(this.expires);
-}
-const Object deprecated = const Deprecated("next release");
-
-class Iterator<E> {
-  bool moveNext();
-  E get current;
-}
-
-abstract class Iterable<E> {
-  Iterator<E> get iterator;
-  bool get isEmpty;
-}
-
-abstract class List<E> implements Iterable<E> {
-  void add(E value);
-  E operator [](int index);
-  void operator []=(int index, E value);
-  Iterator<E> get iterator => null;
-  void clear();
-}
-
-abstract class Map<K, V> extends Object {
-  Iterable<K> get keys;
-}
-
-external bool identical(Object a, Object b);
-
-void print(Object object) {}
-
-class _Override {
-  const _Override();
-}
-const Object override = const _Override();
-''');
-
-  static const _MockSdkLibrary LIB_ASYNC = const _MockSdkLibrary(
-      'dart:async',
-      '/lib/async/async.dart',
-      '''
-library dart.async;
-
-import 'dart:math';
-
-class Future<T> {
-  factory Future.delayed(Duration duration, [T computation()]) => null;
-  factory Future.value([value]) => null;
-  static Future wait(List<Future> futures) => null;
-}
-
-class Stream<T> {}
-abstract class StreamTransformer<S, T> {}
-''');
-
-  static const _MockSdkLibrary LIB_COLLECTION = const _MockSdkLibrary(
-      'dart:collection',
-      '/lib/collection/collection.dart',
-      '''
-library dart.collection;
-
-abstract class HashMap<K, V> implements Map<K, V> {}
-''');
-
-  static const _MockSdkLibrary LIB_CONVERT = const _MockSdkLibrary(
-      'dart:convert',
-      '/lib/convert/convert.dart',
-      '''
-library dart.convert;
-
-import 'dart:async';
-
-abstract class Converter<S, T> implements StreamTransformer {}
-class JsonDecoder extends Converter<String, Object> {}
-''');
-
-  static const _MockSdkLibrary LIB_MATH = const _MockSdkLibrary(
-      'dart:math',
-      '/lib/math/math.dart',
-      '''
-library dart.math;
-const double E = 2.718281828459045;
-const double PI = 3.1415926535897932;
-const double LN10 =  2.302585092994046;
-num min(num a, num b) => 0;
-num max(num a, num b) => 0;
-external double cos(num x);
-external double sin(num x);
-external double sqrt(num x);
-class Random {
-  bool nextBool() => true;
-  double nextDouble() => 2.0;
-  int nextInt() => 1;
-}
-''');
-
-  static const _MockSdkLibrary LIB_HTML = const _MockSdkLibrary(
-      'dart:html',
-      '/lib/html/dartium/html_dartium.dart',
-      '''
-library dart.html;
-class HtmlElement {}
-''');
-
-  static const List<SdkLibrary> LIBRARIES = const [
-    LIB_CORE,
-    LIB_ASYNC,
-    LIB_COLLECTION,
-    LIB_CONVERT,
-    LIB_MATH,
-    LIB_HTML,
-  ];
-
-  static const List<SdkLibrary> LIBRARIES_NO_ASYNC = const [
-    LIB_CORE,
-  ];
-
-  final resource.MemoryResourceProvider provider =
-      new resource.MemoryResourceProvider();
-
-  /**
-   * The [AnalysisContext] which is used for all of the sources.
-   */
-  InternalAnalysisContext _analysisContext;
-
-  MockSdk({bool dartAsync: true}) {
-    List<SdkLibrary> libraries = dartAsync ? LIBRARIES : LIBRARIES_NO_ASYNC;
-    libraries.forEach((_MockSdkLibrary library) {
-      provider.newFile(library.path, library.content);
-    });
-  }
-
-  @override
-  AnalysisContext get context {
-    if (_analysisContext == null) {
-      _analysisContext = new SdkAnalysisContext();
-      SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
-      _analysisContext.sourceFactory = factory;
-    }
-    return _analysisContext;
-  }
-
-  @override
-  List<SdkLibrary> get sdkLibraries => LIBRARIES;
-
-  @override
-  String get sdkVersion => throw unimplemented;
-
-  UnimplementedError get unimplemented => new UnimplementedError();
-
-  @override
-  List<String> get uris {
-    List<String> uris = <String>[];
-    for (SdkLibrary library in LIBRARIES) {
-      uris.add(library.shortName);
-    }
-    return uris;
-  }
-
-  @override
-  Source fromFileUri(Uri uri) {
-    String filePath = uri.path;
-    String libPath = '/lib';
-    if (!filePath.startsWith("$libPath/")) {
-      return null;
-    }
-    for (SdkLibrary library in LIBRARIES) {
-      String libraryPath = library.path;
-      if (filePath.replaceAll('\\', '/') == libraryPath) {
-        try {
-          resource.File file = provider.getResource(uri.path);
-          Uri dartUri = Uri.parse(library.shortName);
-          return file.createSource(dartUri);
-        } catch (exception) {
-          return null;
-        }
-      }
-      if (filePath.startsWith("$libraryPath/")) {
-        String pathInLibrary = filePath.substring(libraryPath.length + 1);
-        String path = '${library.shortName}/$pathInLibrary';
-        try {
-          resource.File file = provider.getResource(uri.path);
-          Uri dartUri = new Uri(scheme: 'dart', path: path);
-          return file.createSource(dartUri);
-        } catch (exception) {
-          return null;
-        }
-      }
-    }
-    return null;
-  }
-
-  @override
-  SdkLibrary getSdkLibrary(String dartUri) {
-    // getSdkLibrary() is only used to determine whether a library is internal
-    // to the SDK.  The mock SDK doesn't have any internals, so it's safe to
-    // return null.
-    return null;
-  }
-
-  @override
-  Source mapDartUri(String dartUri) {
-    const Map<String, String> uriToPath = const {
-      "dart:core": "/lib/core/core.dart",
-      "dart:html": "/lib/html/dartium/html_dartium.dart",
-      "dart:async": "/lib/async/async.dart",
-      "dart:collection": "/lib/collection/collection.dart",
-      "dart:convert": "/lib/convert/convert.dart",
-      "dart:math": "/lib/math/math.dart"
-    };
-
-    String path = uriToPath[dartUri];
-    if (path != null) {
-      resource.File file = provider.getResource(path);
-      Uri uri = new Uri(scheme: 'dart', path: dartUri.substring(5));
-      return file.createSource(uri);
-    }
-
-    // If we reach here then we tried to use a dartUri that's not in the
-    // table above.
-    return null;
-  }
-}
-
-class _MockSdkLibrary implements SdkLibrary {
-  final String shortName;
-  final String path;
-  final String content;
-
-  const _MockSdkLibrary(this.shortName, this.path, this.content);
-
-  @override
-  String get category => throw unimplemented;
-
-  @override
-  bool get isDart2JsLibrary => throw unimplemented;
-
-  @override
-  bool get isDocumented => throw unimplemented;
-
-  @override
-  bool get isImplementation => throw unimplemented;
-
-  @override
-  bool get isInternal => throw unimplemented;
-
-  @override
-  bool get isShared => throw unimplemented;
-
-  @override
-  bool get isVmLibrary => throw unimplemented;
-
-  UnimplementedError get unimplemented => new UnimplementedError();
-}
diff --git a/pkg/analyzer/test/src/summary/flat_buffers_test.dart b/pkg/analyzer/test/src/summary/flat_buffers_test.dart
index 7ceed57..361973b 100644
--- a/pkg/analyzer/test/src/summary/flat_buffers_test.dart
+++ b/pkg/analyzer/test/src/summary/flat_buffers_test.dart
@@ -4,6 +4,8 @@
 
 library test.src.summary.flat_buffers_test;
 
+import 'dart:typed_data';
+
 import 'package:analyzer/src/summary/flat_buffers.dart';
 import 'package:unittest/unittest.dart';
 
@@ -86,6 +88,39 @@
     expect(const Int32Reader().vTableGet(object, 1, 15), 20);
   }
 
+  void test_table_format() {
+    Uint8List byteList;
+    {
+      Builder builder = new Builder(initialSize: 0);
+      builder.startTable();
+      builder.addInt32(0, 10);
+      builder.addInt32(1, 20);
+      builder.addInt32(2, 30);
+      byteList = builder.finish(builder.endTable());
+    }
+    // Convert byteList to a ByteData so that we can read data from it.
+    ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes);
+    // First 4 bytes are an offset to the table data.
+    int tableDataLoc = byteData.getUint32(0, Endianness.LITTLE_ENDIAN);
+    // First 4 bytes of the table data are a backwards offset to the vtable.
+    int vTableLoc = tableDataLoc -
+        byteData.getInt32(tableDataLoc, Endianness.LITTLE_ENDIAN);
+    // First 2 bytes of the vtable are the size of the vtable in bytes, which
+    // should be 10.
+    expect(byteData.getUint16(vTableLoc, Endianness.LITTLE_ENDIAN), 10);
+    // Next 2 bytes are the size of the object in bytes (including the vtable
+    // pointer), which should be 16.
+    expect(byteData.getUint16(vTableLoc + 2, Endianness.LITTLE_ENDIAN), 16);
+    // Remaining 6 bytes are the offsets within the object where the ints are
+    // located.
+    for (int i = 0; i < 3; i++) {
+      int offset =
+          byteData.getUint16(vTableLoc + 4 + 2 * i, Endianness.LITTLE_ENDIAN);
+      expect(byteData.getInt32(tableDataLoc + offset, Endianness.LITTLE_ENDIAN),
+          10 + 10 * i);
+    }
+  }
+
   void test_table_types() {
     List<int> byteList;
     {
@@ -98,6 +133,7 @@
       builder.addOffset(3, stringOffset);
       builder.addInt32(4, 40);
       builder.addUint32(5, 0x9ABCDEF0);
+      builder.addUint8(6, 0x9A);
       Offset offset = builder.endTable();
       byteList = builder.finish(offset);
     }
@@ -109,6 +145,23 @@
     expect(const StringReader().vTableGet(object, 3), '12345');
     expect(const Int32Reader().vTableGet(object, 4), 40);
     expect(const Uint32Reader().vTableGet(object, 5), 0x9ABCDEF0);
+    expect(const Uint8Reader().vTableGet(object, 6), 0x9A);
+  }
+
+  void test_writeList_of_Uint32() {
+    List<int> values = <int>[10, 100, 12345, 0x9abcdef0];
+    // write
+    List<int> byteList;
+    {
+      Builder builder = new Builder(initialSize: 0);
+      Offset offset = builder.writeListUint32(values);
+      byteList = builder.finish(offset);
+    }
+    // read and verify
+    BufferPointer root = new BufferPointer.fromBytes(byteList);
+    List<int> items = const Uint32ListReader().read(root);
+    expect(items, hasLength(4));
+    expect(items, orderedEquals(values));
   }
 
   void test_writeList_ofFloat64() {
@@ -227,6 +280,20 @@
     expect(items, hasLength(3));
     expect(items, orderedEquals(<int>[1, 2, 0x9ABCDEF0]));
   }
+
+  void test_writeList_ofUint8() {
+    List<int> byteList;
+    {
+      Builder builder = new Builder(initialSize: 0);
+      Offset offset = builder.writeListUint8(<int>[1, 2, 0x9A]);
+      byteList = builder.finish(offset);
+    }
+    // read and verify
+    BufferPointer root = new BufferPointer.fromBytes(byteList);
+    List<int> items = const ListReader<int>(const Uint8Reader()).read(root);
+    expect(items, hasLength(3));
+    expect(items, orderedEquals(<int>[1, 2, 0x9A]));
+  }
 }
 
 class StringListWrapperImpl {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_test.dart b/pkg/analyzer/test/src/summary/resynthesize_test.dart
index a19d1fa..3f6d653 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_test.dart
@@ -131,6 +131,49 @@
     }
   }
 
+  void checkPossibleLocalElements(Element resynthesized, Element original) {
+    if (original is! LocalElement && resynthesized is! LocalElement) {
+      return;
+    }
+    // TODO(scheglov) add support for parameters
+    if (original is ParameterElement && resynthesized is ParameterElement) {
+      return;
+    }
+    if (original is LocalElement && resynthesized is LocalElement) {
+      expect(resynthesized.visibleRange, original.visibleRange);
+    } else {
+      fail('Incompatible local elements '
+          '${resynthesized.runtimeType} vs. ${original.runtimeType}');
+    }
+  }
+
+  void checkPossibleMember(
+      Element resynthesized, Element original, String desc) {
+    Element resynthesizedNonHandle = resynthesized is ElementHandle
+        ? resynthesized.actualElement
+        : resynthesized;
+    if (original is Member) {
+      expect(resynthesizedNonHandle, new isInstanceOf<Member>(), reason: desc);
+      if (resynthesizedNonHandle is Member) {
+        List<DartType> resynthesizedTypeArguments =
+            resynthesizedNonHandle.definingType.typeArguments;
+        List<DartType> originalTypeArguments =
+            original.definingType.typeArguments;
+        expect(
+            resynthesizedTypeArguments, hasLength(originalTypeArguments.length),
+            reason: desc);
+        for (int i = 0; i < originalTypeArguments.length; i++) {
+          compareTypeImpls(resynthesizedTypeArguments[i],
+              originalTypeArguments[i], '$desc type argument $i');
+        }
+      }
+    } else {
+      expect(
+          resynthesizedNonHandle, isNot(new isInstanceOf<ConstructorMember>()),
+          reason: desc);
+    }
+  }
+
   void compareClassElements(
       ClassElementImpl resynthesized, ClassElementImpl original, String desc) {
     compareElements(resynthesized, original, desc);
@@ -330,7 +373,14 @@
       } else if (o is IntegerLiteral && r is IntegerLiteral) {
         expect(r.value, o.value, reason: desc);
       } else if (o is DoubleLiteral && r is DoubleLiteral) {
-        expect(r.value, o.value, reason: desc);
+        if (r.value != null &&
+            r.value.isNaN &&
+            o.value != null &&
+            o.value.isNaN) {
+          // NaN is not comparable.
+        } else {
+          expect(r.value, o.value, reason: desc);
+        }
       } else if (o is StringInterpolation && r is StringInterpolation) {
         compareConstAstLists(r.elements, o.elements, desc);
       } else if (o is StringLiteral && r is StringLiteral) {
@@ -372,7 +422,7 @@
         ConstructorName rConstructor = r.constructorName;
         expect(oConstructor, isNotNull, reason: desc);
         expect(rConstructor, isNotNull, reason: desc);
-        compareElements(
+        compareConstructorElements(
             rConstructor.staticElement, oConstructor.staticElement, desc);
         TypeName oType = oConstructor.type;
         TypeName rType = rConstructor.type;
@@ -425,12 +475,26 @@
     }
   }
 
-  void compareConstructorElements(ConstructorElementImpl resynthesized,
-      ConstructorElementImpl original, String desc) {
+  void compareConstructorElements(ConstructorElement resynthesized,
+      ConstructorElement original, String desc) {
+    if (original == null && resynthesized == null) {
+      return;
+    }
     compareExecutableElements(resynthesized, original, desc);
-    compareConstAstLists(resynthesized.constantInitializers,
-        original.constantInitializers, desc);
-    // TODO(paulberry): test redirectedConstructor
+    if (original.isConst) {
+      ConstructorElementImpl resynthesizedImpl =
+          getActualElement(resynthesized, desc);
+      ConstructorElementImpl originalImpl = getActualElement(original, desc);
+      compareConstAstLists(resynthesizedImpl.constantInitializers,
+          originalImpl.constantInitializers, desc);
+    }
+    if (original.redirectedConstructor == null) {
+      expect(resynthesized.redirectedConstructor, isNull, reason: desc);
+    } else {
+      compareConstructorElements(resynthesized.redirectedConstructor,
+          original.redirectedConstructor, '$desc redirectedConstructor');
+    }
+    checkPossibleMember(resynthesized, original, desc);
   }
 
   void compareElementAnnotations(ElementAnnotationImpl resynthesized,
@@ -448,7 +512,18 @@
   }
 
   void compareElements(Element resynthesized, Element original, String desc) {
+    ElementImpl rImpl = getActualElement(resynthesized, desc);
+    ElementImpl oImpl = getActualElement(original, desc);
+    if (oImpl == null && rImpl == null) {
+      return;
+    }
+    if (oImpl is PrefixElement) {
+      // TODO(scheglov) prefixes cannot be resynthesized
+      return;
+    }
+    expect(original, isNotNull);
     expect(resynthesized, isNotNull);
+    expect(rImpl.runtimeType, oImpl.runtimeType);
     expect(resynthesized.kind, original.kind);
     expect(resynthesized.location, original.location, reason: desc);
     expect(resynthesized.name, original.name);
@@ -459,20 +534,17 @@
     compareMetadata(resynthesized.metadata, original.metadata, desc);
     // Modifiers are a pain to test via handles.  So just test them via the
     // actual element.
-    ElementImpl actualResynthesized = getActualElement(resynthesized, desc);
-    ElementImpl actualOriginal = getActualElement(original, desc);
     for (Modifier modifier in Modifier.values) {
-      bool got = actualResynthesized.hasModifier(modifier);
-      bool want = actualOriginal.hasModifier(modifier);
+      bool got = rImpl.hasModifier(modifier);
+      bool want = oImpl.hasModifier(modifier);
       expect(got, want,
           reason: 'Mismatch in $desc.$modifier: got $got, want $want');
     }
     // Validate members.
-    if (actualOriginal is Member) {
-      expect(actualResynthesized, new isInstanceOf<Member>(), reason: desc);
+    if (oImpl is Member) {
+      expect(rImpl, new isInstanceOf<Member>(), reason: desc);
     } else {
-      expect(actualResynthesized, isNot(new isInstanceOf<Member>()),
-          reason: desc);
+      expect(rImpl, isNot(new isInstanceOf<Member>()), reason: desc);
     }
   }
 
@@ -496,6 +568,24 @@
           original.typeParameters[i],
           '$desc type parameter ${original.typeParameters[i].name}');
     }
+    if (original is! Member) {
+      List<FunctionElement> rFunctions = resynthesized.functions;
+      List<FunctionElement> oFunctions = original.functions;
+      expect(rFunctions, hasLength(oFunctions.length));
+      for (int i = 0; i < oFunctions.length; i++) {
+        compareFunctionElements(rFunctions[i], oFunctions[i],
+            '$desc local function ${oFunctions[i].name}');
+      }
+    }
+    if (original is! Member) {
+      List<LocalVariableElement> rVariables = resynthesized.localVariables;
+      List<LocalVariableElement> oVariables = original.localVariables;
+      expect(rVariables, hasLength(oVariables.length));
+      for (int i = 0; i < oVariables.length; i++) {
+        compareVariableElements(rVariables[i], oVariables[i],
+            '$desc local variable ${oVariables[i].name}');
+      }
+    }
   }
 
   void compareExportElements(ExportElementImpl resynthesized,
@@ -513,12 +603,12 @@
   void compareFieldElements(
       FieldElementImpl resynthesized, FieldElementImpl original, String desc) {
     comparePropertyInducingElements(resynthesized, original, desc);
-    // TODO(paulberry): test evaluationResult
   }
 
   void compareFunctionElements(
       FunctionElement resynthesized, FunctionElement original, String desc) {
     compareExecutableElements(resynthesized, original, desc);
+    checkPossibleLocalElements(resynthesized, original);
   }
 
   void compareFunctionTypeAliasElements(
@@ -609,8 +699,8 @@
     }
   }
 
-  void compareParameterElements(ParameterElementImpl resynthesized,
-      ParameterElementImpl original, String desc) {
+  void compareParameterElements(
+      ParameterElement resynthesized, ParameterElement original, String desc) {
     compareVariableElements(resynthesized, original, desc);
     expect(resynthesized.parameters.length, original.parameters.length);
     for (int i = 0; i < resynthesized.parameters.length; i++) {
@@ -639,7 +729,6 @@
   void comparePrefixElements(PrefixElementImpl resynthesized,
       PrefixElementImpl original, String desc) {
     compareElements(resynthesized, original, desc);
-    // TODO(paulberry): test _importedLibraries.
   }
 
   void comparePropertyAccessorElements(
@@ -678,7 +767,6 @@
       TopLevelVariableElementImpl original,
       String desc) {
     comparePropertyInducingElements(resynthesized, original, desc);
-    // TODO(paulberry): test evaluationResult
   }
 
   void compareTypeImpls(
@@ -752,9 +840,14 @@
       }
     } else if (resynthesized is VoidTypeImpl && original is VoidTypeImpl) {
       expect(resynthesized, same(original));
+    } else if (resynthesized is DynamicTypeImpl &&
+        original is UndefinedTypeImpl) {
+      // TODO(scheglov) In the strong mode constant variable like
+      //  `var V = new Unresolved()` gets `UndefinedTypeImpl`, and it gets
+      // `DynamicTypeImpl` in the spec mode.
     } else if (resynthesized.runtimeType != original.runtimeType) {
-      fail(
-          'Type mismatch: expected ${original.runtimeType}, got ${resynthesized.runtimeType}');
+      fail('Type mismatch: expected ${original.runtimeType},'
+          ' got ${resynthesized.runtimeType} ($desc)');
     } else {
       fail('Unimplemented comparison for ${original.runtimeType}');
     }
@@ -768,18 +861,24 @@
     expect(resynthesized.uriEnd, original.uriEnd, reason: desc);
   }
 
-  void compareVariableElements(VariableElementImpl resynthesized,
-      VariableElementImpl original, String desc) {
+  void compareVariableElements(
+      VariableElement resynthesized, VariableElement original, String desc) {
     compareElements(resynthesized, original, desc);
     compareTypes(resynthesized.type, original.type, desc);
-    if (original is ConstVariableElement) {
-      Expression initializer = resynthesized.constantInitializer;
+    VariableElementImpl originalActual = getActualElement(original, desc);
+    if (originalActual is ConstVariableElement) {
+      VariableElementImpl resynthesizedActual =
+          getActualElement(resynthesized, desc);
+      Expression initializer = resynthesizedActual.constantInitializer;
       if (constantInitializersAreInvalid) {
         _assertUnresolvedIdentifier(initializer, desc);
       } else {
-        compareConstAsts(initializer, original.constantInitializer, desc);
+        compareConstAsts(initializer, originalActual.constantInitializer,
+            '$desc initializer');
       }
     }
+    checkPossibleMember(resynthesized, original, desc);
+    checkPossibleLocalElements(resynthesized, original);
   }
 
   /**
@@ -848,10 +947,16 @@
   }
 
   ElementImpl getActualElement(Element element, String desc) {
-    if (element is ElementImpl) {
+    if (element == null) {
+      return null;
+    } else if (element is ElementImpl) {
       return element;
     } else if (element is ElementHandle) {
-      return getActualElement(element.actualElement, desc);
+      Element actualElement = element.actualElement;
+      // A handle should never point to a member, because if it did, then
+      // "is Member" checks on the handle would produce the wrong result.
+      expect(actualElement, isNot(new isInstanceOf<Member>()), reason: desc);
+      return getActualElement(actualElement, desc);
     } else if (element is Member) {
       return getActualElement(element.baseElement, desc);
     } else {
@@ -1034,6 +1139,22 @@
     checkLibrary('class C { var x; C(this.x); }');
   }
 
+  test_class_constructor_fieldFormal_named_noDefault() {
+    checkLibrary('class C { int x; C({this.x}); }');
+  }
+
+  test_class_constructor_fieldFormal_named_withDefault() {
+    checkLibrary('class C { int x; C({this.x: 42}); }');
+  }
+
+  test_class_constructor_fieldFormal_optional_noDefault() {
+    checkLibrary('class C { int x; C([this.x]); }');
+  }
+
+  test_class_constructor_fieldFormal_optional_withDefault() {
+    checkLibrary('class C { int x; C([this.x = 42]); }');
+  }
+
   test_class_constructor_implicit() {
     checkLibrary('class C {}');
   }
@@ -1348,6 +1469,56 @@
 ''');
   }
 
+  test_const_invokeConstructor_named_unresolved() {
+    checkLibrary(
+        r'''
+class C {}
+const V = const C.named();
+''',
+        allowErrors: true);
+  }
+
+  test_const_invokeConstructor_named_unresolved2() {
+    checkLibrary(
+        r'''
+const V = const C.named();
+''',
+        allowErrors: true);
+  }
+
+  test_const_invokeConstructor_named_unresolved3() {
+    addLibrarySource(
+        '/a.dart',
+        r'''
+class C {
+}
+''');
+    checkLibrary(
+        r'''
+import 'a.dart' as p;
+const V = const p.C.named();
+''',
+        allowErrors: true);
+  }
+
+  test_const_invokeConstructor_named_unresolved4() {
+    addLibrarySource('/a.dart', '');
+    checkLibrary(
+        r'''
+import 'a.dart' as p;
+const V = const p.C.named();
+''',
+        allowErrors: true);
+  }
+
+  test_const_invokeConstructor_named_unresolved5() {
+    checkLibrary(
+        r'''
+const V = const p.C.named();
+''',
+        allowErrors: true);
+  }
+
   test_const_invokeConstructor_unnamed() {
     checkLibrary(r'''
 class C {
@@ -1385,6 +1556,32 @@
 ''');
   }
 
+  test_const_invokeConstructor_unnamed_unresolved() {
+    checkLibrary(
+        r'''
+const V = const C();
+''',
+        allowErrors: true);
+  }
+
+  test_const_invokeConstructor_unnamed_unresolved2() {
+    addLibrarySource('/a.dart', '');
+    checkLibrary(
+        r'''
+import 'a.dart' as p;
+const V = const p.C();
+''',
+        allowErrors: true);
+  }
+
+  test_const_invokeConstructor_unnamed_unresolved3() {
+    checkLibrary(
+        r'''
+const V = const p.C();
+''',
+        allowErrors: true);
+  }
+
   test_const_length_ofClassConstField() {
     checkLibrary(r'''
 class C {
@@ -1502,7 +1699,9 @@
   const C.positional([p = 1 + 2]);
   const C.named({p: 1 + 2});
   void methodPositional([p = 1 + 2]) {}
+  void methodPositionalWithoutDefault([p]) {}
   void methodNamed({p: 1 + 2}) {}
+  void methodNamedWithoutDefault({p}) {}
 }
 ''');
   }
@@ -1691,6 +1890,37 @@
 ''');
   }
 
+  test_const_reference_unresolved_prefix0() {
+    checkLibrary(
+        r'''
+const V = foo;
+''',
+        allowErrors: true);
+  }
+
+  test_const_reference_unresolved_prefix1() {
+    checkLibrary(
+        r'''
+class C {}
+const v = C.foo;
+''',
+        allowErrors: true);
+  }
+
+  test_const_reference_unresolved_prefix2() {
+    addLibrarySource(
+        '/foo.dart',
+        '''
+class C {}
+''');
+    checkLibrary(
+        r'''
+import 'foo.dart' as p;
+const v = p.C.foo;
+''',
+        allowErrors: true);
+  }
+
   test_const_topLevel_binary() {
     checkLibrary(r'''
 const vEqual = 1 == 2;
@@ -1897,6 +2127,234 @@
 ''');
   }
 
+  test_constructor_redirected_factory_named() {
+    checkLibrary('''
+class C {
+  factory C() = D.named;
+  C._();
+}
+class D extends C {
+  D.named() : super._();
+}
+''');
+  }
+
+  test_constructor_redirected_factory_named_generic() {
+    checkLibrary('''
+class C<T, U> {
+  factory C() = D<U, T>.named;
+  C._();
+}
+class D<T, U> extends C<U, T> {
+  D.named() : super._();
+}
+''');
+  }
+
+  test_constructor_redirected_factory_named_imported() {
+    addLibrarySource(
+        '/foo.dart',
+        '''
+import 'test.dart';
+class D extends C {
+  D.named() : super._();
+}
+''');
+    checkLibrary('''
+import 'foo.dart';
+class C {
+  factory C() = D.named;
+  C._();
+}
+''');
+  }
+
+  test_constructor_redirected_factory_named_imported_generic() {
+    addLibrarySource(
+        '/foo.dart',
+        '''
+import 'test.dart';
+class D<T, U> extends C<U, T> {
+  D.named() : super._();
+}
+''');
+    checkLibrary('''
+import 'foo.dart';
+class C<T, U> {
+  factory C() = D<U, T>.named;
+  C._();
+}
+''');
+  }
+
+  test_constructor_redirected_factory_named_prefixed() {
+    addLibrarySource(
+        '/foo.dart',
+        '''
+import 'test.dart';
+class D extends C {
+  D.named() : super._();
+}
+''');
+    checkLibrary('''
+import 'foo.dart' as foo;
+class C {
+  factory C() = foo.D.named;
+  C._();
+}
+''');
+  }
+
+  test_constructor_redirected_factory_named_prefixed_generic() {
+    addLibrarySource(
+        '/foo.dart',
+        '''
+import 'test.dart';
+class D<T, U> extends C<U, T> {
+  D.named() : super._();
+}
+''');
+    checkLibrary('''
+import 'foo.dart' as foo;
+class C<T, U> {
+  factory C() = foo.D<U, T>.named;
+  C._();
+}
+''');
+  }
+
+  test_constructor_redirected_factory_unnamed() {
+    checkLibrary('''
+class C {
+  factory C() = D;
+  C._();
+}
+class D extends C {
+  D() : super._();
+}
+''');
+  }
+
+  test_constructor_redirected_factory_unnamed_generic() {
+    checkLibrary('''
+class C<T, U> {
+  factory C() = D<U, T>;
+  C._();
+}
+class D<T, U> extends C<U, T> {
+  D() : super._();
+}
+''');
+  }
+
+  test_constructor_redirected_factory_unnamed_imported() {
+    addLibrarySource(
+        '/foo.dart',
+        '''
+import 'test.dart';
+class D extends C {
+  D() : super._();
+}
+''');
+    checkLibrary('''
+import 'foo.dart';
+class C {
+  factory C() = D;
+  C._();
+}
+''');
+  }
+
+  test_constructor_redirected_factory_unnamed_imported_generic() {
+    addLibrarySource(
+        '/foo.dart',
+        '''
+import 'test.dart';
+class D<T, U> extends C<U, T> {
+  D() : super._();
+}
+''');
+    checkLibrary('''
+import 'foo.dart';
+class C<T, U> {
+  factory C() = D<U, T>;
+  C._();
+}
+''');
+  }
+
+  test_constructor_redirected_factory_unnamed_prefixed() {
+    addLibrarySource(
+        '/foo.dart',
+        '''
+import 'test.dart';
+class D extends C {
+  D() : super._();
+}
+''');
+    checkLibrary('''
+import 'foo.dart' as foo;
+class C {
+  factory C() = foo.D;
+  C._();
+}
+''');
+  }
+
+  test_constructor_redirected_factory_unnamed_prefixed_generic() {
+    addLibrarySource(
+        '/foo.dart',
+        '''
+import 'test.dart';
+class D<T, U> extends C<U, T> {
+  D() : super._();
+}
+''');
+    checkLibrary('''
+import 'foo.dart' as foo;
+class C<T, U> {
+  factory C() = foo.D<U, T>;
+  C._();
+}
+''');
+  }
+
+  test_constructor_redirected_thisInvocation_named() {
+    checkLibrary('''
+class C {
+  C.named();
+  C() : this.named();
+}
+''');
+  }
+
+  test_constructor_redirected_thisInvocation_named_generic() {
+    checkLibrary('''
+class C<T> {
+  C.named();
+  C() : this.named();
+}
+''');
+  }
+
+  test_constructor_redirected_thisInvocation_unnamed() {
+    checkLibrary('''
+class C {
+  C();
+  C.named() : this();
+}
+''');
+  }
+
+  test_constructor_redirected_thisInvocation_unnamed_generic() {
+    checkLibrary('''
+class C<T> {
+  C();
+  C.named() : this();
+}
+''');
+  }
+
   test_core() {
     String uri = 'dart:core';
     LibraryElementImpl original =
@@ -2015,15 +2473,15 @@
         ' abstract class D { int get v; }');
   }
 
-  test_field_inferred_type_nonstatic_explicit_initialized() {
+  test_field_inferred_type_nonStatic_explicit_initialized() {
     checkLibrary('class C { num v = 0; }');
   }
 
-  test_field_inferred_type_nonstatic_implicit_initialized() {
+  test_field_inferred_type_nonStatic_implicit_initialized() {
     checkLibrary('class C { var v = 0; }');
   }
 
-  test_field_inferred_type_nonstatic_implicit_uninitialized() {
+  test_field_inferred_type_nonStatic_implicit_uninitialized() {
     checkLibrary(
         'class C extends D { var v; } abstract class D { int get v; }');
   }
@@ -2105,12 +2563,10 @@
   }
 
   test_function_parameter_kind_named() {
-    // TODO(paulberry): also test default value.
     checkLibrary('f({x}) {}');
   }
 
   test_function_parameter_kind_positional() {
-    // TODO(paulberry): also test default value.
     checkLibrary('f([x]) {}');
   }
 
@@ -2164,6 +2620,18 @@
     checkLibrary('f() {} g() {}');
   }
 
+  test_generic_gClass_gMethodStatic() {
+    resetWithOptions(new AnalysisOptionsImpl()..enableGenericMethods = true);
+    checkLibrary('''
+class C<T, U> {
+  static void m<V, W>(V v, W w) {
+    void f<X, Y>(V v, W w, X x, Y y) {
+    }
+  }
+}
+''');
+  }
+
   test_getElement_constructor_named() {
     ConstructorElement original = resolve2(addSource('class C { C.named(); }'))
         .getType('C')
@@ -2227,6 +2695,14 @@
     comparePropertyAccessorElements(resynthesized, original, 'C.setter f');
   }
 
+  test_getElement_unit() {
+    Source source = addSource('class C { f() {} }');
+    CompilationUnitElement original = resolve2(source).definingCompilationUnit;
+    expect(original, isNotNull);
+    CompilationUnitElement resynthesized = validateGetElement(original);
+    compareCompilationUnitElements(resynthesized, original);
+  }
+
   test_getter_documented() {
     checkLibrary('''
 // Extra comment so doc comment offset != 0
@@ -2240,7 +2716,7 @@
     checkLibrary('external int get x;');
   }
 
-  test_getter_inferred_type_nonstatic_implicit_return() {
+  test_getter_inferred_type_nonStatic_implicit_return() {
     checkLibrary(
         'class C extends D { get f => null; } abstract class D { int get f; }');
   }
@@ -2343,6 +2819,102 @@
     checkLibrary('library foo.bar;');
   }
 
+  test_localFunctions() {
+    checkLibrary(r'''
+f() {
+  f1() {}
+  {
+    f2() {}
+  }
+}
+''');
+  }
+
+  test_localFunctions_inConstructor() {
+    checkLibrary(r'''
+class C {
+  C() {
+    f() {}
+  }
+}
+''');
+  }
+
+  test_localFunctions_inMethod() {
+    checkLibrary(r'''
+class C {
+  m() {
+    f() {}
+  }
+}
+''');
+  }
+
+  test_localFunctions_inTopLevelGetter() {
+    checkLibrary(r'''
+get g {
+  f() {}
+}
+''');
+  }
+
+  test_localVariables_inConstructor() {
+    checkLibrary(r'''
+class C {
+  C() {
+    int v;
+    f() {}
+  }
+}
+''');
+  }
+
+  test_localVariables_inLocalFunction() {
+    checkLibrary(r'''
+f() {
+  f1() {
+    int v1 = 1;
+  } // 2
+  f2() {
+    int v1 = 1;
+    f3() {
+      int v2 = 1;
+    }
+  }
+}
+''');
+  }
+
+  test_localVariables_inMethod() {
+    checkLibrary(r'''
+class C {
+  m() {
+    int v;
+  }
+}
+''');
+  }
+
+  test_localVariables_inTopLevelFunction() {
+    checkLibrary(r'''
+main() {
+  int v1 = 1;
+  {
+    const String v2 = 'bbb';
+  }
+  Map<int, List<double>> v3;
+}
+''');
+  }
+
+  test_localVariables_inTopLevelGetter() {
+    checkLibrary(r'''
+get g {
+  int v;
+}
+''');
+  }
+
   test_main_class() {
     checkLibrary('class main {}');
   }
@@ -2542,12 +3114,12 @@
 }''');
   }
 
-  test_method_inferred_type_nonstatic_implicit_param() {
+  test_method_inferred_type_nonStatic_implicit_param() {
     checkLibrary('class C extends D { void f(value) {} }'
         ' abstract class D { void f(int value); }');
   }
 
-  test_method_inferred_type_nonstatic_implicit_return() {
+  test_method_inferred_type_nonStatic_implicit_return() {
     checkLibrary(
         'class C extends D { f() => null; } abstract class D { int f(); }');
   }
@@ -2583,6 +3155,62 @@
     checkLibrary('class C { void f<T, U>(T x(U u)) {} }');
   }
 
+  test_nested_generic_functions_in_generic_class_with_function_typed_params() {
+    checkLibrary('''
+class C<T, U> {
+  void g<V, W>() {
+    void h<X, Y>(void p(T t, U u, V v, W w, X x, Y y)) {
+    }
+  }
+}
+''');
+  }
+
+  test_nested_generic_functions_in_generic_class_with_local_variables() {
+    checkLibrary('''
+class C<T, U> {
+  void g<V, W>() {
+    void h<X, Y>() {
+      T t;
+      U u;
+      V v;
+      W w;
+      X x;
+      Y y;
+    }
+  }
+}
+''');
+  }
+
+  test_nested_generic_functions_with_function_typed_param() {
+    checkLibrary('''
+void f<T, U>() {
+  void g<V, W>() {
+    void h<X, Y>(void p(T t, U u, V v, W w, X x, Y y)) {
+    }
+  }
+}
+''');
+  }
+
+  test_nested_generic_functions_with_local_variables() {
+    checkLibrary('''
+void f<T, U>() {
+  void g<V, W>() {
+    void h<X, Y>() {
+      T t;
+      U u;
+      V v;
+      W w;
+      X x;
+      Y y;
+    }
+  }
+}
+''');
+  }
+
   test_operator() {
     checkLibrary('class C { C operator+(C other) => null; }');
   }
@@ -2611,6 +3239,50 @@
     checkLibrary('class C { bool operator<=(C other) => false; }');
   }
 
+  test_parameterTypeNotInferred_constructor() {
+    // Strong mode doesn't do type inference on constructor parameters, so it's
+    // ok that we don't store inferred type info for them in summaries.
+    checkLibrary('''
+class C {
+  C.positional([x = 1]);
+  C.named({x: 1});
+}
+''');
+  }
+
+  test_parameterTypeNotInferred_initializingFormal() {
+    // Strong mode doesn't do type inference on initializing formals, so it's
+    // ok that we don't store inferred type info for them in summaries.
+    checkLibrary('''
+class C {
+  var x;
+  C.positional([this.x = 1]);
+  C.named({this.x: 1});
+}
+''');
+  }
+
+  test_parameterTypeNotInferred_staticMethod() {
+    // Strong mode doesn't do type inference on parameters of static methods,
+    // so it's ok that we don't store inferred type info for them in summaries.
+    checkLibrary('''
+class C {
+  static void positional([x = 1]) {}
+  static void named({x: 1}) {}
+}
+''');
+  }
+
+  test_parameterTypeNotInferred_topLevelFunction() {
+    // Strong mode doesn't do type inference on parameters of top level
+    // functions, so it's ok that we don't store inferred type info for them in
+    // summaries.
+    checkLibrary('''
+void positional([x = 1]) {}
+void named({x: 1}) {}
+''');
+  }
+
   test_parts() {
     addNamedSource('/a.dart', 'part of my.lib;');
     addNamedSource('/b.dart', 'part of my.lib;');
@@ -2630,7 +3302,7 @@
     checkLibrary('external void set x(int value);');
   }
 
-  test_setter_inferred_type_nonstatic_implicit_param() {
+  test_setter_inferred_type_nonStatic_implicit_param() {
     checkLibrary('class C extends D { void set f(value) {} }'
         ' abstract class D { void set f(int value); }');
   }
diff --git a/pkg/analyzer/test/src/summary/summarize_ast_test.dart b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
index af0ad99..4e4cc1e 100644
--- a/pkg/analyzer/test/src/summary/summarize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
@@ -6,9 +6,11 @@
 
 import 'package:analyzer/analyzer.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/prelink.dart';
 import 'package:analyzer/src/summary/summarize_ast.dart';
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index 63009b8..5e2f084 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -7,11 +7,12 @@
 import 'package:analyzer/analyzer.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/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/generated/source_io.dart';
 import 'package:analyzer/src/summary/base.dart';
@@ -327,7 +328,7 @@
       int numTypeParameters: 0}) {
     if (strongMode) {
       checkLinkedTypeSlot(slotId, absoluteUri, relativeUri, expectedName,
-          allowTypeParameters: allowTypeParameters,
+          allowTypeArguments: allowTypeParameters,
           expectedKind: expectedKind,
           expectedTargetUnit: expectedTargetUnit,
           linkedSourceUnit: linkedSourceUnit,
@@ -363,8 +364,8 @@
   /**
    * Verify that the given [typeRef] represents a reference to a type declared
    * in a file reachable via [absoluteUri] and [relativeUri], having name
-   * [expectedName].  If [allowTypeParameters] is true, allow the type
-   * reference to supply type parameters.  [expectedKind] is the kind of object
+   * [expectedName].  If [allowTypeArguments] is true, allow the type
+   * reference to supply type arguments.  [expectedKind] is the kind of object
    * referenced.  [linkedSourceUnit] and [unlinkedSourceUnit] refer to the
    * compilation unit within which the [typeRef] appears; if not specified they
    * are assumed to refer to the defining compilation unit.
@@ -375,7 +376,7 @@
    */
   void checkLinkedTypeRef(EntityRef typeRef, String absoluteUri,
       String relativeUri, String expectedName,
-      {bool allowTypeParameters: false,
+      {bool allowTypeArguments: false,
       ReferenceKind expectedKind: ReferenceKind.classOrEnum,
       int expectedTargetUnit: 0,
       LinkedUnit linkedSourceUnit,
@@ -386,7 +387,7 @@
         reason: 'No entry in linkedSourceUnit.types matching slotId');
     expect(typeRef.paramReference, 0);
     int index = typeRef.reference;
-    if (!allowTypeParameters) {
+    if (!allowTypeArguments) {
       expect(typeRef.typeArguments, isEmpty);
     }
     checkReferenceIndex(index, absoluteUri, relativeUri, expectedName,
@@ -400,8 +401,8 @@
   /**
    * Verify that the given [slotId] represents a reference to a type declared
    * in a file reachable via [absoluteUri] and [relativeUri], having name
-   * [expectedName].  If [allowTypeParameters] is true, allow the type
-   * reference to supply type parameters.  [expectedKind] is the kind of object
+   * [expectedName].  If [allowTypeArguments] is true, allow the type
+   * reference to supply type arguments.  [expectedKind] is the kind of object
    * referenced.  [linkedSourceUnit] and [unlinkedSourceUnit] refer to the
    * compilation unit within which the [typeRef] appears; if not specified they
    * are assumed to refer to the defining compilation unit.
@@ -412,7 +413,7 @@
    */
   void checkLinkedTypeSlot(
       int slotId, String absoluteUri, String relativeUri, String expectedName,
-      {bool allowTypeParameters: false,
+      {bool allowTypeArguments: false,
       ReferenceKind expectedKind: ReferenceKind.classOrEnum,
       int expectedTargetUnit: 0,
       LinkedUnit linkedSourceUnit,
@@ -429,7 +430,7 @@
         absoluteUri,
         relativeUri,
         expectedName,
-        allowTypeParameters: allowTypeParameters,
+        allowTypeArguments: allowTypeArguments,
         expectedKind: expectedKind,
         expectedTargetUnit: expectedTargetUnit,
         linkedSourceUnit: linkedSourceUnit,
@@ -467,6 +468,9 @@
    * reference, return the [UnlinkedReference] that is used to make the
    * explicit reference.  If the type reference in question is an implicit
    * reference, return `null`.
+   *
+   * TODO(scheglov) remove [checkAstDerivedDataOverride] once elements-based
+   * serializer can record unresolved information.
    */
   UnlinkedReference checkReferenceIndex(int referenceIndex, String absoluteUri,
       String relativeUri, String expectedName,
@@ -474,7 +478,8 @@
       int expectedTargetUnit: 0,
       LinkedUnit linkedSourceUnit,
       UnlinkedUnit unlinkedSourceUnit,
-      int numTypeParameters: 0}) {
+      int numTypeParameters: 0,
+      bool checkAstDerivedDataOverride: false}) {
     linkedSourceUnit ??= definingUnit;
     unlinkedSourceUnit ??= unlinkedUnits[0];
     LinkedReference referenceResolution =
@@ -504,7 +509,9 @@
     } else {
       checkDependency(referenceResolution.dependency, absoluteUri, relativeUri);
     }
-    if (expectedKind == ReferenceKind.unresolved && !checkAstDerivedData) {
+    if (expectedKind == ReferenceKind.unresolved &&
+        !checkAstDerivedData &&
+        !checkAstDerivedDataOverride) {
       // summarize_elements.dart isn't yet able to record the name of
       // unresolved references.  TODO(paulberry): fix this.
       expect(name, '*unresolved*');
@@ -534,6 +541,9 @@
    * target of the [typeRef] is expected to appear; if not specified it is
    * assumed to be the defining compilation unit.  [numTypeParameters] is the
    * number of type parameters of the thing being referred to.
+   *
+   * TODO(scheglov) remove [checkAstDerivedDataOverride] once elements-based
+   * serializer can record unresolved information.
    */
   void checkTypeRef(EntityRef typeRef, String absoluteUri, String relativeUri,
       String expectedName,
@@ -544,7 +554,8 @@
       int expectedTargetUnit: 0,
       LinkedUnit linkedSourceUnit,
       UnlinkedUnit unlinkedSourceUnit,
-      int numTypeParameters: 0}) {
+      int numTypeParameters: 0,
+      bool checkAstDerivedDataOverride: false}) {
     linkedSourceUnit ??= definingUnit;
     expect(typeRef, new isInstanceOf<EntityRef>());
     expect(typeRef.paramReference, 0);
@@ -558,10 +569,13 @@
         expectedTargetUnit: expectedTargetUnit,
         linkedSourceUnit: linkedSourceUnit,
         unlinkedSourceUnit: unlinkedSourceUnit,
-        numTypeParameters: numTypeParameters);
+        numTypeParameters: numTypeParameters,
+        checkAstDerivedDataOverride: checkAstDerivedDataOverride);
     expect(reference, isNotNull,
         reason: 'Unlinked type refs must refer to an explicit reference');
-    if (expectedKind == ReferenceKind.unresolved && !checkAstDerivedData) {
+    if (expectedKind == ReferenceKind.unresolved &&
+        !checkAstDerivedData &&
+        !checkAstDerivedDataOverride) {
       // summarize_elements.dart isn't yet able to record the prefix of
       // unresolved references.  TODO(paulberry): fix this.
       expect(reference.prefixReference, 0);
@@ -580,6 +594,7 @@
                 : expectation.relativeUri ?? relativeUri,
             expectation.name,
             expectedKind: expectation.kind,
+            checkAstDerivedDataOverride: checkAstDerivedDataOverride,
             expectedTargetUnit: expectedTargetUnit,
             linkedSourceUnit: linkedSourceUnit,
             unlinkedSourceUnit: unlinkedSourceUnit,
@@ -614,20 +629,6 @@
     checkTypeRef(typeRef, null, null, 'void');
   }
 
-  fail_enum_value_documented() {
-    // TODO(paulberry): currently broken because of dartbug.com/25385
-    String text = '''
-enum E {
-  /**
-   * Docs
-   */
-  v
-}''';
-    UnlinkedEnumValue value = serializeEnumText(text).values[0];
-    expect(value.documentationComment, isNotNull);
-    checkDocumentationComment(value.documentationComment, text);
-  }
-
   /**
    * Find the class with the given [className] in the summary, and return its
    * [UnlinkedClass] data structure.  If [unit] is not given, the class is
@@ -1099,17 +1100,17 @@
     // executables
     Map<String, UnlinkedPublicName> executablesMap =
         <String, UnlinkedPublicName>{};
-    className.constMembers.forEach((e) => executablesMap[e.name] = e);
+    className.members.forEach((e) => executablesMap[e.name] = e);
     expect(executablesMap, hasLength(2));
     {
       UnlinkedPublicName executable = executablesMap['fieldStaticConst'];
       expect(executable.kind, ReferenceKind.propertyAccessor);
-      expect(executable.constMembers, isEmpty);
+      expect(executable.members, isEmpty);
     }
     {
       UnlinkedPublicName executable = executablesMap['methodStaticPublic'];
       expect(executable.kind, ReferenceKind.method);
-      expect(executable.constMembers, isEmpty);
+      expect(executable.members, isEmpty);
     }
   }
 
@@ -1131,18 +1132,18 @@
     // executables
     Map<String, UnlinkedPublicName> executablesMap =
         <String, UnlinkedPublicName>{};
-    className.constMembers.forEach((e) => executablesMap[e.name] = e);
+    className.members.forEach((e) => executablesMap[e.name] = e);
     expect(executablesMap, hasLength(2));
     {
-      UnlinkedPublicName executable = executablesMap[''];
-      expect(executable.kind, ReferenceKind.constructor);
-      expect(executable.constMembers, isEmpty);
-    }
-    {
       UnlinkedPublicName executable =
           executablesMap['constructorNamedPublicConst'];
       expect(executable.kind, ReferenceKind.constructor);
-      expect(executable.constMembers, isEmpty);
+      expect(executable.members, isEmpty);
+    }
+    {
+      UnlinkedPublicName executable = executablesMap['constructorNamedPublic'];
+      expect(executable.kind, ReferenceKind.constructor);
+      expect(executable.members, isEmpty);
     }
   }
 
@@ -1969,6 +1970,123 @@
     ]);
   }
 
+  test_constExpr_invokeConstructor_unresolved_named() {
+    UnlinkedVariable variable = serializeVariableText(
+        '''
+class C {}
+const v = const C.foo();
+''',
+        allowErrors: true);
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.invokeConstructor,
+    ], ints: [
+      0,
+      0
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'foo',
+              expectedKind: ReferenceKind.unresolved,
+              checkAstDerivedDataOverride: true,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
+              ])
+    ]);
+  }
+
+  test_constExpr_invokeConstructor_unresolved_named2() {
+    UnlinkedVariable variable = serializeVariableText(
+        '''
+const v = const C.foo();
+''',
+        allowErrors: true);
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.invokeConstructor,
+    ], ints: [
+      0,
+      0
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'foo',
+              expectedKind: ReferenceKind.unresolved,
+              checkAstDerivedDataOverride: true,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.unresolved, 'C')
+              ])
+    ]);
+  }
+
+  test_constExpr_invokeConstructor_unresolved_named_prefixed() {
+    addNamedSource(
+        '/a.dart',
+        '''
+class C {
+}
+''');
+    UnlinkedVariable variable = serializeVariableText(
+        '''
+import 'a.dart' as p;
+const v = const p.C.foo();
+''',
+        allowErrors: true);
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.invokeConstructor,
+    ], ints: [
+      0,
+      0
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'foo',
+              expectedKind: ReferenceKind.unresolved,
+              checkAstDerivedDataOverride: true,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
+                    absoluteUri: absUri('/a.dart'), relativeUri: 'a.dart'),
+                new _PrefixExpectation(ReferenceKind.prefix, 'p',
+                    inLibraryDefiningUnit: true)
+              ])
+    ]);
+  }
+
+  test_constExpr_invokeConstructor_unresolved_named_prefixed2() {
+    addNamedSource('/a.dart', '');
+    UnlinkedVariable variable = serializeVariableText(
+        '''
+import 'a.dart' as p;
+const v = const p.C.foo();
+''',
+        allowErrors: true);
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.invokeConstructor,
+    ], ints: [
+      0,
+      0
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'foo',
+              expectedKind: ReferenceKind.unresolved,
+              checkAstDerivedDataOverride: true,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.unresolved, 'C'),
+                new _PrefixExpectation(ReferenceKind.prefix, 'p',
+                    inLibraryDefiningUnit: true)
+              ])
+    ]);
+  }
+
+  test_constExpr_invokeConstructor_unresolved_unnamed() {
+    UnlinkedVariable variable = serializeVariableText(
+        '''
+const v = const Foo();
+''',
+        allowErrors: true);
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.invokeConstructor,
+    ], ints: [
+      0,
+      0
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'Foo',
+          expectedKind: ReferenceKind.unresolved,
+          checkAstDerivedDataOverride: true)
+    ]);
+  }
+
   test_constExpr_length_classConstField() {
     UnlinkedVariable variable = serializeVariableText('''
 class C {
@@ -2679,6 +2797,67 @@
     _assertUnlinkedConst(variable.constExpr, isInvalid: true);
   }
 
+  test_constExpr_pushReference_unresolved_prefix0() {
+    UnlinkedVariable variable = serializeVariableText(
+        '''
+const v = foo;
+''',
+        allowErrors: true);
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'foo',
+          expectedKind: ReferenceKind.unresolved,
+          checkAstDerivedDataOverride: true)
+    ]);
+  }
+
+  test_constExpr_pushReference_unresolved_prefix1() {
+    UnlinkedVariable variable = serializeVariableText(
+        '''
+class C {}
+const v = C.foo;
+''',
+        allowErrors: true);
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'foo',
+              expectedKind: ReferenceKind.unresolved,
+              checkAstDerivedDataOverride: true,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
+              ])
+    ]);
+  }
+
+  test_constExpr_pushReference_unresolved_prefix2() {
+    addNamedSource(
+        '/a.dart',
+        '''
+class C {}
+''');
+    UnlinkedVariable variable = serializeVariableText(
+        '''
+import 'a.dart' as p;
+const v = p.C.foo;
+''',
+        allowErrors: true);
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'foo',
+              expectedKind: ReferenceKind.unresolved,
+              checkAstDerivedDataOverride: true,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
+                    absoluteUri: absUri('/a.dart'), relativeUri: 'a.dart'),
+                new _PrefixExpectation(ReferenceKind.prefix, 'p',
+                    inLibraryDefiningUnit: true),
+              ])
+    ]);
+  }
+
   test_constExpr_pushString_adjacent() {
     UnlinkedVariable variable =
         serializeVariableText('const v = "aaa" "b" "ccc";');
@@ -2746,6 +2925,11 @@
     expect(executable.returnType, isNull);
     expect(executable.isExternal, isFalse);
     expect(executable.nameOffset, text.indexOf('C();'));
+    expect(executable.isRedirectedConstructor, isFalse);
+    expect(executable.redirectedConstructor, isNull);
+    expect(executable.redirectedConstructorName, isEmpty);
+    expect(executable.visibleOffset, 0);
+    expect(executable.visibleLength, 0);
   }
 
   test_constructor_anonymous() {
@@ -3162,6 +3346,358 @@
     expect(ctor.parameters[0].inferredTypeSlot, 0);
   }
 
+  test_constructor_redirected_factory_named() {
+    String text = '''
+class C {
+  factory C() = D.named;
+  C._();
+}
+class D extends C {
+  D.named() : super._();
+}
+''';
+    UnlinkedExecutable executable =
+        serializeClassText(text, className: 'C').executables[0];
+    expect(executable.isRedirectedConstructor, isTrue);
+    expect(executable.isFactory, isTrue);
+    expect(executable.redirectedConstructorName, isEmpty);
+    checkTypeRef(executable.redirectedConstructor, null, null, 'named',
+        expectedKind: ReferenceKind.constructor,
+        prefixExpectations: [
+          new _PrefixExpectation(ReferenceKind.classOrEnum, 'D')
+        ]);
+  }
+
+  test_constructor_redirected_factory_named_generic() {
+    String text = '''
+class C<T, U> {
+  factory C() = D<U, T>.named;
+  C._();
+}
+class D<T, U> extends C<U, T> {
+  D.named() : super._();
+}
+''';
+    UnlinkedExecutable executable =
+        serializeClassText(text, className: 'C').executables[0];
+    expect(executable.isRedirectedConstructor, isTrue);
+    expect(executable.isFactory, isTrue);
+    expect(executable.redirectedConstructorName, isEmpty);
+    checkTypeRef(executable.redirectedConstructor, null, null, 'named',
+        expectedKind: ReferenceKind.constructor,
+        prefixExpectations: [
+          new _PrefixExpectation(ReferenceKind.classOrEnum, 'D',
+              numTypeParameters: 2)
+        ],
+        allowTypeParameters: true);
+    checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
+    checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
+  }
+
+  test_constructor_redirected_factory_named_imported() {
+    addNamedSource(
+        '/foo.dart',
+        '''
+import 'test.dart';
+class D extends C {
+  D.named() : super._();
+}
+''');
+    String text = '''
+import 'foo.dart';
+class C {
+  factory C() = D.named;
+  C._();
+}
+''';
+    UnlinkedExecutable executable =
+        serializeClassText(text, className: 'C').executables[0];
+    expect(executable.isRedirectedConstructor, isTrue);
+    expect(executable.isFactory, isTrue);
+    expect(executable.redirectedConstructorName, isEmpty);
+    checkTypeRef(executable.redirectedConstructor, null, null, 'named',
+        expectedKind: ReferenceKind.constructor,
+        prefixExpectations: [
+          new _PrefixExpectation(ReferenceKind.classOrEnum, 'D',
+              absoluteUri: absUri('/foo.dart'), relativeUri: 'foo.dart')
+        ]);
+  }
+
+  test_constructor_redirected_factory_named_imported_generic() {
+    addNamedSource(
+        '/foo.dart',
+        '''
+import 'test.dart';
+class D<T, U> extends C<U, T> {
+  D.named() : super._();
+}
+''');
+    String text = '''
+import 'foo.dart';
+class C<T, U> {
+  factory C() = D<U, T>.named;
+  C._();
+}
+''';
+    UnlinkedExecutable executable =
+        serializeClassText(text, className: 'C').executables[0];
+    expect(executable.isRedirectedConstructor, isTrue);
+    expect(executable.isFactory, isTrue);
+    expect(executable.redirectedConstructorName, isEmpty);
+    checkTypeRef(executable.redirectedConstructor, null, null, 'named',
+        expectedKind: ReferenceKind.constructor,
+        prefixExpectations: [
+          new _PrefixExpectation(ReferenceKind.classOrEnum, 'D',
+              numTypeParameters: 2,
+              absoluteUri: absUri('/foo.dart'),
+              relativeUri: 'foo.dart')
+        ],
+        allowTypeParameters: true);
+    checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
+    checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
+  }
+
+  test_constructor_redirected_factory_named_prefixed() {
+    addNamedSource(
+        '/foo.dart',
+        '''
+import 'test.dart';
+class D extends C {
+  D.named() : super._();
+}
+''');
+    String text = '''
+import 'foo.dart' as foo;
+class C {
+  factory C() = foo.D.named;
+  C._();
+}
+''';
+    UnlinkedExecutable executable =
+        serializeClassText(text, className: 'C').executables[0];
+    expect(executable.isRedirectedConstructor, isTrue);
+    expect(executable.isFactory, isTrue);
+    expect(executable.redirectedConstructorName, isEmpty);
+    checkTypeRef(executable.redirectedConstructor, null, null, 'named',
+        expectedKind: ReferenceKind.constructor,
+        prefixExpectations: [
+          new _PrefixExpectation(ReferenceKind.classOrEnum, 'D',
+              absoluteUri: absUri('/foo.dart'), relativeUri: 'foo.dart'),
+          new _PrefixExpectation(ReferenceKind.prefix, 'foo')
+        ]);
+  }
+
+  test_constructor_redirected_factory_named_prefixed_generic() {
+    addNamedSource(
+        '/foo.dart',
+        '''
+import 'test.dart';
+class D<T, U> extends C<U, T> {
+  D.named() : super._();
+}
+''');
+    String text = '''
+import 'foo.dart' as foo;
+class C<T, U> {
+  factory C() = foo.D<U, T>.named;
+  C._();
+}
+''';
+    UnlinkedExecutable executable =
+        serializeClassText(text, className: 'C').executables[0];
+    expect(executable.isRedirectedConstructor, isTrue);
+    expect(executable.isFactory, isTrue);
+    expect(executable.redirectedConstructorName, isEmpty);
+    checkTypeRef(executable.redirectedConstructor, null, null, 'named',
+        expectedKind: ReferenceKind.constructor,
+        prefixExpectations: [
+          new _PrefixExpectation(ReferenceKind.classOrEnum, 'D',
+              numTypeParameters: 2,
+              absoluteUri: absUri('/foo.dart'),
+              relativeUri: 'foo.dart'),
+          new _PrefixExpectation(ReferenceKind.prefix, 'foo')
+        ],
+        allowTypeParameters: true);
+    checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
+    checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
+  }
+
+  test_constructor_redirected_factory_unnamed() {
+    String text = '''
+class C {
+  factory C() = D;
+  C._();
+}
+class D extends C {
+  D() : super._();
+}
+''';
+    UnlinkedExecutable executable =
+        serializeClassText(text, className: 'C').executables[0];
+    expect(executable.isRedirectedConstructor, isTrue);
+    expect(executable.isFactory, isTrue);
+    expect(executable.redirectedConstructorName, isEmpty);
+    checkTypeRef(executable.redirectedConstructor, null, null, 'D');
+  }
+
+  test_constructor_redirected_factory_unnamed_generic() {
+    String text = '''
+class C<T, U> {
+  factory C() = D<U, T>;
+  C._();
+}
+class D<T, U> extends C<U, T> {
+  D() : super._();
+}
+''';
+    UnlinkedExecutable executable =
+        serializeClassText(text, className: 'C').executables[0];
+    expect(executable.isRedirectedConstructor, isTrue);
+    expect(executable.isFactory, isTrue);
+    expect(executable.redirectedConstructorName, isEmpty);
+    checkTypeRef(executable.redirectedConstructor, null, null, 'D',
+        allowTypeParameters: true, numTypeParameters: 2);
+    checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
+    checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
+  }
+
+  test_constructor_redirected_factory_unnamed_imported() {
+    addNamedSource(
+        '/foo.dart',
+        '''
+import 'test.dart';
+class D extends C {
+  D() : super._();
+}
+''');
+    String text = '''
+import 'foo.dart';
+class C {
+  factory C() = D;
+  C._();
+}
+''';
+    UnlinkedExecutable executable =
+        serializeClassText(text, className: 'C').executables[0];
+    expect(executable.isRedirectedConstructor, isTrue);
+    expect(executable.isFactory, isTrue);
+    expect(executable.redirectedConstructorName, isEmpty);
+    checkTypeRef(
+        executable.redirectedConstructor, absUri('/foo.dart'), 'foo.dart', 'D');
+  }
+
+  test_constructor_redirected_factory_unnamed_imported_generic() {
+    addNamedSource(
+        '/foo.dart',
+        '''
+import 'test.dart';
+class D<T, U> extends C<U, T> {
+  D() : super._();
+}
+''');
+    String text = '''
+import 'foo.dart';
+class C<T, U> {
+  factory C() = D<U, T>;
+  C._();
+}
+''';
+    UnlinkedExecutable executable =
+        serializeClassText(text, className: 'C').executables[0];
+    expect(executable.isRedirectedConstructor, isTrue);
+    expect(executable.isFactory, isTrue);
+    expect(executable.redirectedConstructorName, isEmpty);
+    checkTypeRef(
+        executable.redirectedConstructor, absUri('/foo.dart'), 'foo.dart', 'D',
+        allowTypeParameters: true, numTypeParameters: 2);
+    checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
+    checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
+  }
+
+  test_constructor_redirected_factory_unnamed_prefixed() {
+    addNamedSource(
+        '/foo.dart',
+        '''
+import 'test.dart';
+class D extends C {
+  D() : super._();
+}
+''');
+    String text = '''
+import 'foo.dart' as foo;
+class C {
+  factory C() = foo.D;
+  C._();
+}
+''';
+    UnlinkedExecutable executable =
+        serializeClassText(text, className: 'C').executables[0];
+    expect(executable.isRedirectedConstructor, isTrue);
+    expect(executable.isFactory, isTrue);
+    expect(executable.redirectedConstructorName, isEmpty);
+    checkTypeRef(
+        executable.redirectedConstructor, absUri('/foo.dart'), 'foo.dart', 'D',
+        expectedPrefix: 'foo');
+  }
+
+  test_constructor_redirected_factory_unnamed_prefixed_generic() {
+    addNamedSource(
+        '/foo.dart',
+        '''
+import 'test.dart';
+class D<T, U> extends C<U, T> {
+  D() : super._();
+}
+''');
+    String text = '''
+import 'foo.dart' as foo;
+class C<T, U> {
+  factory C() = foo.D<U, T>;
+  C._();
+}
+''';
+    UnlinkedExecutable executable =
+        serializeClassText(text, className: 'C').executables[0];
+    expect(executable.isRedirectedConstructor, isTrue);
+    expect(executable.isFactory, isTrue);
+    expect(executable.redirectedConstructorName, isEmpty);
+    checkTypeRef(
+        executable.redirectedConstructor, absUri('/foo.dart'), 'foo.dart', 'D',
+        allowTypeParameters: true, numTypeParameters: 2, expectedPrefix: 'foo');
+    checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
+    checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
+  }
+
+  test_constructor_redirected_thisInvocation_named() {
+    String text = '''
+class C {
+  C() : this.named();
+  C.named();
+}
+''';
+    UnlinkedExecutable executable =
+        serializeClassText(text, className: 'C').executables[0];
+    expect(executable.isRedirectedConstructor, isTrue);
+    expect(executable.isFactory, isFalse);
+    expect(executable.redirectedConstructorName, 'named');
+    expect(executable.redirectedConstructor, isNull);
+  }
+
+  test_constructor_redirected_thisInvocation_unnamed() {
+    String text = '''
+class C {
+  C.named() : this();
+  C();
+}
+''';
+    UnlinkedExecutable executable =
+        serializeClassText(text, className: 'C').executables[0];
+    expect(executable.isRedirectedConstructor, isTrue);
+    expect(executable.isFactory, isFalse);
+    expect(executable.redirectedConstructorName, isEmpty);
+    expect(executable.redirectedConstructor, isNull);
+  }
+
   test_constructor_return_type() {
     UnlinkedExecutable executable = findExecutable('',
         executables: serializeClassText('class C { C(); }').executables);
@@ -3372,6 +3908,19 @@
     expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
   }
 
+  test_enum_value_documented() {
+    String text = '''
+enum E {
+  /**
+   * Docs
+   */
+  v
+}''';
+    UnlinkedEnumValue value = serializeEnumText(text).values[0];
+    expect(value.documentationComment, isNotNull);
+    checkDocumentationComment(value.documentationComment, text);
+  }
+
   test_executable_abstract() {
     UnlinkedExecutable executable =
         serializeClassText('abstract class C { f(); }').executables[0];
@@ -3391,6 +3940,8 @@
     expect(executable.returnType, isNull);
     expect(executable.isExternal, isFalse);
     expect(executable.nameOffset, text.indexOf('f'));
+    expect(executable.visibleOffset, 0);
+    expect(executable.visibleLength, 0);
     expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
     expect(unlinkedUnits[0].publicNamespace.names[0].kind,
         ReferenceKind.topLevelFunction);
@@ -3452,12 +4003,194 @@
     expect(executable.parameters, isEmpty);
   }
 
+  test_executable_localFunctions() {
+    String code = r'''
+f() { // 1
+  f1() {}
+  { // 2
+    f2() {}
+  } // 3
+} // 4
+''';
+    UnlinkedExecutable executable = serializeExecutableText(code);
+    List<UnlinkedExecutable> functions = executable.localFunctions;
+    expect(functions, hasLength(2));
+    {
+      UnlinkedExecutable f1 = functions.singleWhere((v) => v.name == 'f1');
+      _assertExecutableVisible(code, f1, '{ // 1', '} // 4');
+    }
+    {
+      UnlinkedExecutable f2 = functions.singleWhere((v) => v.name == 'f2');
+      _assertExecutableVisible(code, f2, '{ // 2', '} // 3');
+    }
+  }
+
+  test_executable_localVariables_empty() {
+    UnlinkedExecutable executable = serializeExecutableText(r'''
+f() {
+}
+''');
+    expect(executable.localVariables, isEmpty);
+  }
+
+  test_executable_localVariables_inConstructor() {
+    String code = r'''
+class C {
+  C() { // 1
+    int v;
+  } // 2
+}
+''';
+    UnlinkedExecutable executable =
+        findExecutable('', executables: serializeClassText(code).executables);
+    List<UnlinkedVariable> variables = executable.localVariables;
+    expect(variables, hasLength(1));
+    {
+      UnlinkedVariable v = variables.singleWhere((v) => v.name == 'v');
+      _assertVariableVisible(code, v, '{ // 1', '} // 2');
+      checkTypeRef(v.type, 'dart:core', 'dart:core', 'int');
+    }
+  }
+
+  test_executable_localVariables_inLocalFunctions() {
+    String code = r'''
+f() {
+  f1() { // 1
+    int v1 = 1;
+  } // 2
+  f2() { // 3
+    int v1 = 1;
+    f3() { // 4
+      int v2 = 1;
+    } // 5
+  } // 6
+} // 7
+''';
+    UnlinkedExecutable executable = serializeExecutableText(code);
+    List<UnlinkedExecutable> functions = executable.localFunctions;
+    expect(functions, hasLength(2));
+    // f - f1
+    {
+      UnlinkedExecutable f1 = functions.singleWhere((v) => v.name == 'f1');
+      List<UnlinkedVariable> variables = f1.localVariables;
+      expect(variables, hasLength(1));
+      // f1 - v1
+      UnlinkedVariable v1 = variables.singleWhere((v) => v.name == 'v1');
+      _assertVariableVisible(code, v1, '{ // 1', '} // 2');
+      checkTypeRef(v1.type, 'dart:core', 'dart:core', 'int');
+    }
+    // f - f2
+    {
+      UnlinkedExecutable f2 = functions.singleWhere((v) => v.name == 'f2');
+      List<UnlinkedVariable> variables2 = f2.localVariables;
+      List<UnlinkedExecutable> functions2 = f2.localFunctions;
+      expect(variables2, hasLength(1));
+      expect(functions2, hasLength(1));
+      // f - f2 - v1
+      UnlinkedVariable v1 = variables2.singleWhere((v) => v.name == 'v1');
+      _assertVariableVisible(code, v1, '{ // 3', '} // 6');
+      checkTypeRef(v1.type, 'dart:core', 'dart:core', 'int');
+      // f - f2 - f3
+      UnlinkedExecutable f3 = functions2.singleWhere((v) => v.name == 'f3');
+      _assertExecutableVisible(code, f3, '{ // 3', '} // 6');
+      List<UnlinkedVariable> variables3 = f3.localVariables;
+      List<UnlinkedExecutable> functions3 = f3.localFunctions;
+      expect(variables3, hasLength(1));
+      expect(functions3, hasLength(0));
+      // f - f3 - v2
+      UnlinkedVariable v2 = variables3.singleWhere((v) => v.name == 'v2');
+      _assertVariableVisible(code, v2, '{ // 4', '} // 5');
+      checkTypeRef(v2.type, 'dart:core', 'dart:core', 'int');
+    }
+  }
+
+  test_executable_localVariables_inMethod() {
+    String code = r'''
+class C {
+  m() { // 1
+    int v;
+    f() {}
+  } // 2
+}
+''';
+    UnlinkedExecutable executable =
+        findExecutable('m', executables: serializeClassText(code).executables);
+    {
+      List<UnlinkedExecutable> functions = executable.localFunctions;
+      expect(functions, hasLength(1));
+      UnlinkedExecutable f = functions.singleWhere((v) => v.name == 'f');
+      _assertExecutableVisible(code, f, '{ // 1', '} // 2');
+    }
+    {
+      List<UnlinkedVariable> variables = executable.localVariables;
+      expect(variables, hasLength(1));
+      UnlinkedVariable v = variables.singleWhere((v) => v.name == 'v');
+      _assertVariableVisible(code, v, '{ // 1', '} // 2');
+      checkTypeRef(v.type, 'dart:core', 'dart:core', 'int');
+    }
+  }
+
+  test_executable_localVariables_inTopLevelFunction() {
+    String code = r'''
+f() { // 1
+  int v1 = 1;
+  { // 2
+    int v2 = 2;
+  } // 3
+  var v3 = 3;
+} // 4
+''';
+    UnlinkedExecutable executable = serializeExecutableText(code);
+    List<UnlinkedVariable> variables = executable.localVariables;
+    expect(variables, hasLength(3));
+    {
+      UnlinkedVariable v1 = variables.singleWhere((v) => v.name == 'v1');
+      _assertVariableVisible(code, v1, '{ // 1', '} // 4');
+      checkTypeRef(v1.type, 'dart:core', 'dart:core', 'int');
+    }
+    {
+      UnlinkedVariable v2 = variables.singleWhere((v) => v.name == 'v2');
+      _assertVariableVisible(code, v2, '{ // 2', '} // 3');
+      checkTypeRef(v2.type, 'dart:core', 'dart:core', 'int');
+    }
+    {
+      UnlinkedVariable v3 = variables.singleWhere((v) => v.name == 'v3');
+      _assertVariableVisible(code, v3, '{ // 1', '} // 4');
+      expect(v3.type, isNull);
+    }
+  }
+
+  test_executable_localVariables_inTopLevelGetter() {
+    String code = r'''
+get g { // 1
+  int v;
+  f() {}
+} // 2
+''';
+    UnlinkedExecutable executable = serializeExecutableText(code, 'g');
+    {
+      List<UnlinkedExecutable> functions = executable.localFunctions;
+      expect(functions, hasLength(1));
+      UnlinkedExecutable f = functions.singleWhere((v) => v.name == 'f');
+      _assertExecutableVisible(code, f, '{ // 1', '} // 2');
+    }
+    {
+      List<UnlinkedVariable> variables = executable.localVariables;
+      expect(variables, hasLength(1));
+      UnlinkedVariable v = variables.singleWhere((v) => v.name == 'v');
+      _assertVariableVisible(code, v, '{ // 1', '} // 2');
+      checkTypeRef(v.type, 'dart:core', 'dart:core', 'int');
+    }
+  }
+
   test_executable_member_function() {
     UnlinkedExecutable executable = findExecutable('f',
         executables: serializeClassText('class C { f() {} }').executables);
     expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
     expect(executable.returnType, isNull);
     expect(executable.isExternal, isFalse);
+    expect(executable.visibleOffset, 0);
+    expect(executable.visibleLength, 0);
   }
 
   test_executable_member_function_explicit_return() {
@@ -4227,6 +4960,15 @@
     UnlinkedVariable variable =
         serializeClassText('class C { static int i; }').fields[0];
     expect(variable.isStatic, isTrue);
+    expect(variable.constExpr, isNull);
+  }
+
+  test_field_static_final() {
+    UnlinkedVariable variable =
+        serializeClassText('class C { static final int i = 0; }').fields[0];
+    expect(variable.isStatic, isTrue);
+    expect(variable.isFinal, isTrue);
+    expect(variable.constExpr, isNull);
   }
 
   test_fully_linked_references_follow_other_references() {
@@ -4269,6 +5011,25 @@
     expect(f.inferredReturnTypeSlot, 0);
   }
 
+  test_generic_gClass_gMethodStatic() {
+    UnlinkedClass cls = serializeClassText('''
+class C<T, U> {
+  static void m<V, W>(V v, W w) {
+    void f<X, Y>(V v, W w, X x, Y y) {
+    }
+  }
+}
+''');
+    UnlinkedExecutable m = cls.executables[0];
+    UnlinkedExecutable f = m.localFunctions[0];
+    checkParamTypeRef(m.parameters[0].type, 2);
+    checkParamTypeRef(m.parameters[1].type, 1);
+    checkParamTypeRef(f.parameters[0].type, 4);
+    checkParamTypeRef(f.parameters[1].type, 3);
+    checkParamTypeRef(f.parameters[2].type, 2);
+    checkParamTypeRef(f.parameters[3].type, 1);
+  }
+
   test_generic_method_in_generic_class() {
     UnlinkedClass cls = serializeClassText(
         'class C<T, U> { void m<V, W>(T t, U u, V v, W w) {} }');
@@ -4579,7 +5340,7 @@
     EntityRef type = getTypeRefForSlot(cls.fields[0].inferredTypeSlot);
     // Check that v has inferred type Map<T, int>.
     checkLinkedTypeRef(type, 'dart:core', 'dart:core', 'Map',
-        allowTypeParameters: true, numTypeParameters: 2);
+        allowTypeArguments: true, numTypeParameters: 2);
     checkParamTypeRef(type.typeArguments[0], 1);
     checkLinkedTypeRef(type.typeArguments[1], 'dart:core', 'dart:core', 'int');
   }
@@ -5188,6 +5949,113 @@
     expect(f.inferredReturnTypeSlot, 0);
   }
 
+  test_nested_generic_functions() {
+    UnlinkedExecutable executable = serializeExecutableText('''
+void f<T, U>() {
+  void g<V, W>() {
+    void h<X, Y>() {
+      T t;
+      U u;
+      V v;
+      W w;
+      X x;
+      Y y;
+    }
+  }
+}
+''');
+    expect(executable.typeParameters, hasLength(2));
+    expect(executable.localFunctions[0].typeParameters, hasLength(2));
+    expect(executable.localFunctions[0].localFunctions[0].typeParameters,
+        hasLength(2));
+    List<UnlinkedVariable> localVariables =
+        executable.localFunctions[0].localFunctions[0].localVariables;
+    checkParamTypeRef(findVariable('t', variables: localVariables).type, 6);
+    checkParamTypeRef(findVariable('u', variables: localVariables).type, 5);
+    checkParamTypeRef(findVariable('v', variables: localVariables).type, 4);
+    checkParamTypeRef(findVariable('w', variables: localVariables).type, 3);
+    checkParamTypeRef(findVariable('x', variables: localVariables).type, 2);
+    checkParamTypeRef(findVariable('y', variables: localVariables).type, 1);
+  }
+
+  test_nested_generic_functions_in_generic_class() {
+    UnlinkedClass cls = serializeClassText('''
+class C<T, U> {
+  void g<V, W>() {
+    void h<X, Y>() {
+      T t;
+      U u;
+      V v;
+      W w;
+      X x;
+      Y y;
+    }
+  }
+}
+''');
+    expect(cls.typeParameters, hasLength(2));
+    expect(cls.executables[0].typeParameters, hasLength(2));
+    expect(cls.executables[0].localFunctions[0].typeParameters, hasLength(2));
+    List<UnlinkedVariable> localVariables =
+        cls.executables[0].localFunctions[0].localVariables;
+    checkParamTypeRef(findVariable('t', variables: localVariables).type, 6);
+    checkParamTypeRef(findVariable('u', variables: localVariables).type, 5);
+    checkParamTypeRef(findVariable('v', variables: localVariables).type, 4);
+    checkParamTypeRef(findVariable('w', variables: localVariables).type, 3);
+    checkParamTypeRef(findVariable('x', variables: localVariables).type, 2);
+    checkParamTypeRef(findVariable('y', variables: localVariables).type, 1);
+  }
+
+  test_parameter_visibleRange_abstractMethod() {
+    UnlinkedExecutable m = findExecutable('m',
+        executables:
+            serializeClassText('abstract class C { m(p); }').executables,
+        failIfAbsent: true);
+    _assertParameterZeroVisibleRange(m.parameters[0]);
+  }
+
+  test_parameter_visibleRange_function_blockBody() {
+    String text = r'''
+f(x) { // 1
+  f2(y) { // 2
+  } // 3
+} // 4
+''';
+    UnlinkedExecutable f = serializeExecutableText(text);
+    UnlinkedExecutable f2 = f.localFunctions[0];
+    _assertParameterVisible(text, f.parameters[0], '{ // 1', '} // 4');
+    _assertParameterVisible(text, f2.parameters[0], '{ // 2', '} // 3');
+  }
+
+  test_parameter_visibleRange_function_emptyBody() {
+    UnlinkedExecutable f = serializeExecutableText('external f(x);');
+    _assertParameterZeroVisibleRange(f.parameters[0]);
+  }
+
+  test_parameter_visibleRange_function_expressionBody() {
+    String text = r'''
+f(x) => 42;
+''';
+    UnlinkedExecutable f = serializeExecutableText(text);
+    _assertParameterVisible(text, f.parameters[0], '=>', ';');
+  }
+
+  test_parameter_visibleRange_inFunctionTypedParameter() {
+    String text = 'f(g(p)) {}';
+    UnlinkedExecutable f = serializeExecutableText(text);
+    UnlinkedParam g = f.parameters[0];
+    UnlinkedParam p = g.parameters[0];
+    expect(g.name, 'g');
+    expect(p.name, 'p');
+    _assertParameterVisible(text, g, '{', '}');
+    _assertParameterZeroVisibleRange(p);
+  }
+
+  test_parameter_visibleRange_typedef() {
+    UnlinkedTypedef type = serializeTypedefText('typedef F(x);');
+    _assertParameterZeroVisibleRange(type.parameters[0]);
+  }
+
   test_part_declaration() {
     addNamedSource('/a.dart', 'part of my.lib;');
     String text = 'library my.lib; part "a.dart"; // <-part';
@@ -5900,7 +6768,7 @@
     UnlinkedVariable v = serializeVariableText('final v = <int, dynamic>{};');
     EntityRef type = getTypeRefForSlot(v.propagatedTypeSlot);
     checkLinkedTypeRef(type, 'dart:core', 'dart:core', 'Map',
-        allowTypeParameters: true, numTypeParameters: 2);
+        allowTypeArguments: true, numTypeParameters: 2);
     expect(type.typeArguments, hasLength(1));
     checkLinkedTypeRef(type.typeArguments[0], 'dart:core', 'dart:core', 'int');
   }
@@ -5974,6 +6842,29 @@
     }
   }
 
+  void _assertExecutableVisible(String code, UnlinkedExecutable f,
+      String visibleBegin, String visibleEnd) {
+    int expectedVisibleOffset = code.indexOf(visibleBegin);
+    int expectedVisibleLength =
+        code.indexOf(visibleEnd) - expectedVisibleOffset + 1;
+    expect(f.visibleOffset, expectedVisibleOffset);
+    expect(f.visibleLength, expectedVisibleLength);
+  }
+
+  void _assertParameterVisible(
+      String code, UnlinkedParam p, String visibleBegin, String visibleEnd) {
+    int expectedVisibleOffset = code.indexOf(visibleBegin);
+    int expectedVisibleLength =
+        code.indexOf(visibleEnd) - expectedVisibleOffset + 1;
+    expect(p.visibleOffset, expectedVisibleOffset);
+    expect(p.visibleLength, expectedVisibleLength);
+  }
+
+  void _assertParameterZeroVisibleRange(UnlinkedParam p) {
+    expect(p.visibleOffset, isZero);
+    expect(p.visibleLength, isZero);
+  }
+
   void _assertUnlinkedConst(UnlinkedConst constExpr,
       {bool isInvalid: false,
       List<UnlinkedConstOperation> operators: const <UnlinkedConstOperation>[],
@@ -5993,6 +6884,15 @@
       referenceValidators[i](constExpr.references[i]);
     }
   }
+
+  void _assertVariableVisible(
+      String code, UnlinkedVariable v, String visibleBegin, String visibleEnd) {
+    int expectedVisibleOffset = code.indexOf(visibleBegin);
+    int expectedVisibleLength =
+        code.indexOf(visibleEnd) - expectedVisibleOffset + 1;
+    expect(v.visibleOffset, expectedVisibleOffset);
+    expect(v.visibleLength, expectedVisibleLength);
+  }
 }
 
 /**
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index a259e62..21c2fd3 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -5,6 +5,7 @@
 library analyzer.test.src.task.dart_test;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -15,7 +16,6 @@
     show AnalysisOptions, AnalysisOptionsImpl, CacheState;
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/services/lint.dart';
@@ -32,7 +32,7 @@
 import '../../reflective_tests.dart';
 import '../../utils.dart';
 import '../context/abstract_context.dart';
-import '../mock_sdk.dart';
+import '../context/mock_sdk.dart';
 
 main() {
   initializeTestEnvironment();
@@ -2240,6 +2240,8 @@
 
 @reflectiveTest
 class GatherUsedLocalElementsTaskTest extends _AbstractDartTaskTest {
+  List<Element> definedElements;
+  Set<String> definedElementNames;
   UsedLocalElements usedElements;
   Set<String> usedElementNames;
 
@@ -2304,6 +2306,7 @@
 }''');
     _computeUsedElements(source);
     // validate
+    expect(definedElementNames, unorderedEquals(['main', 'v1', 'v2']));
     expect(usedElementNames, unorderedEquals(['v2']));
   }
 
@@ -2323,14 +2326,30 @@
 ''');
     _computeUsedElements(source);
     // validate
+    expect(definedElementNames,
+        unorderedEquals(['A', '_m1', '_m2', 'main', 'a', 'p']));
     expect(usedElementNames, unorderedEquals(['A', 'a', 'p', '_m2']));
     expect(usedElements.members, unorderedEquals(['_m2', '_m3']));
   }
 
+  test_perform_unresolvedImportWithPrefix() {
+    Source source = newSource(
+        '/test.dart',
+        r'''
+import 'x' as p;
+''');
+    _computeUsedElements(source);
+    // validate
+    expect(definedElementNames, isEmpty);
+    expect(usedElementNames, isEmpty);
+  }
+
   void _computeUsedElements(Source source) {
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
     computeResult(target, USED_LOCAL_ELEMENTS,
         matcher: isGatherUsedLocalElementsTask);
+    definedElements = outputs[DEFINED_ELEMENTS];
+    definedElementNames = definedElements.map((e) => e.name).toSet();
     usedElements = outputs[USED_LOCAL_ELEMENTS];
     usedElementNames = usedElements.elements.map((e) => e.name).toSet();
   }
@@ -4048,10 +4067,12 @@
    * Verify that the mutated states of the given [variable] correspond to the
    * [mutatedInClosure] and [mutatedInScope] matchers.
    */
-  void expectMutated(VariableElement variable, Matcher mutatedInClosure,
-      Matcher mutatedInScope) {
+  void expectMutated(FunctionBody body, VariableElement variable,
+      bool mutatedInClosure, bool mutatedInScope) {
     expect(variable.isPotentiallyMutatedInClosure, mutatedInClosure);
     expect(variable.isPotentiallyMutatedInScope, mutatedInScope);
+    expect(body.isPotentiallyMutatedInClosure(variable), mutatedInClosure);
+    expect(body.isPotentiallyMutatedInScope(variable), mutatedInScope);
   }
 
   test_created_resolved_unit() {
@@ -4101,11 +4122,13 @@
         matcher: isResolveVariableReferencesTask);
     // validate
     CompilationUnit unit = outputs[RESOLVED_UNIT4];
-    FunctionElement main = unit.element.functions[0];
-    expectMutated(main.localVariables[0], isFalse, isFalse);
-    expectMutated(main.localVariables[1], isFalse, isTrue);
-    expectMutated(main.localVariables[2], isTrue, isTrue);
-    expectMutated(main.localVariables[3], isTrue, isTrue);
+    FunctionDeclaration mainDeclaration = unit.declarations[0];
+    FunctionBody body = mainDeclaration.functionExpression.body;
+    FunctionElement main = mainDeclaration.element;
+    expectMutated(body, main.localVariables[0], false, false);
+    expectMutated(body, main.localVariables[1], false, true);
+    expectMutated(body, main.localVariables[2], true, true);
+    expectMutated(body, main.localVariables[3], true, true);
   }
 
   test_perform_parameter() {
@@ -4126,11 +4149,13 @@
         matcher: isResolveVariableReferencesTask);
     // validate
     CompilationUnit unit = outputs[RESOLVED_UNIT4];
-    FunctionElement main = unit.element.functions[0];
-    expectMutated(main.parameters[0], isFalse, isFalse);
-    expectMutated(main.parameters[1], isFalse, isTrue);
-    expectMutated(main.parameters[2], isTrue, isTrue);
-    expectMutated(main.parameters[3], isTrue, isTrue);
+    FunctionDeclaration mainDeclaration = unit.declarations[0];
+    FunctionBody body = mainDeclaration.functionExpression.body;
+    FunctionElement main = mainDeclaration.element;
+    expectMutated(body, main.parameters[0], false, false);
+    expectMutated(body, main.parameters[1], false, true);
+    expectMutated(body, main.parameters[2], true, true);
+    expectMutated(body, main.parameters[3], true, true);
   }
 }
 
diff --git a/pkg/analyzer/test/src/task/dart_work_manager_test.dart b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
index 315e061..c6d3f1d 100644
--- a/pkg/analyzer/test/src/task/dart_work_manager_test.dart
+++ b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
@@ -6,6 +6,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart' show ScannerErrorCode;
 import 'package:analyzer/src/generated/engine.dart'
     show
         AnalysisErrorInfo,
@@ -15,7 +16,6 @@
         InternalAnalysisContext;
 import 'package:analyzer/src/generated/error.dart' show AnalysisError;
 import 'package:analyzer/src/generated/java_engine.dart' show CaughtException;
-import 'package:analyzer/src/generated/scanner.dart' show ScannerErrorCode;
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/testing/ast_factory.dart';
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 0a00961..cc7047e 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -1161,12 +1161,47 @@
 
     test('uninferred closure', () {
       checkFile('''
-      typedef num Num2Num(num x);
-      void main() {
-        Num2Num g = /*info:INFERRED_TYPE_CLOSURE,severe:STATIC_TYPE_ERROR*/(int x) { return x; };
-        print(g(42));
-      }
-    ''');
+        typedef num Num2Num(num x);
+        void main() {
+          Num2Num g = /*info:INFERRED_TYPE_CLOSURE,severe:STATIC_TYPE_ERROR*/(int x) { return x; };
+          print(g(42));
+        }
+      ''');
+    });
+
+    test('subtype of universal type', () {
+      checkFile('''
+        void main() {
+          nonGenericFn(x) => null;
+          {
+            /*=R*/ f/*<P, R>*/(/*=P*/ p) => null;
+            /*=T*/ g/*<S, T>*/(/*=S*/ s) => null;
+
+            var local = f;
+            local = g; // valid
+
+            // Non-generic function cannot subtype a generic one.
+            local = /*severe:STATIC_TYPE_ERROR*/(x) => null;
+            local = /*severe:STATIC_TYPE_ERROR*/nonGenericFn;
+          }
+          {
+            Iterable/*<R>*/ f/*<P, R>*/(List/*<P>*/ p) => null;
+            List/*<T>*/ g/*<S, T>*/(Iterable/*<S>*/ s) => null;
+
+            var local = f;
+            local = g; // valid
+
+            var local2 = g;
+            local = local2;
+            local2 = /*severe:STATIC_TYPE_ERROR*/f;
+            local2 = /*warning:DOWN_CAST_COMPOSITE*/local;
+
+            // Non-generic function cannot subtype a generic one.
+            local = /*severe:STATIC_TYPE_ERROR*/(x) => null;
+            local = /*severe:STATIC_TYPE_ERROR*/nonGenericFn;
+          }
+        }
+      ''');
     });
   });
 
@@ -2597,8 +2632,8 @@
               // different.
               // TODO(sigmund): should we merge these as well?
               class T1 extends Object
-                  with /*severe:INVALID_METHOD_OVERRIDE*/M1
-                  with /*severe:INVALID_METHOD_OVERRIDE*/M2
+                  with /*severe:INVALID_METHOD_OVERRIDE*/M1,
+                  /*severe:INVALID_METHOD_OVERRIDE*/M2
                   implements I1 {
               }
            ''');
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index 663ee78..2e7981e 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -1491,6 +1491,75 @@
       ''');
   });
 
+  test('downwards inference on generic function expressions', () {
+    checkFile('''
+      void main () {
+        {
+          String f/*<S>*/(int x) => null;
+          var v = f;
+          v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(int x) => null;
+          v = /*<T>*/(int x) => "hello";
+          v = /*severe:STATIC_TYPE_ERROR*//*<T>*/(String x) => "hello";
+          v = /*severe:STATIC_TYPE_ERROR*//*<T>*/(int x) => 3;
+          v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(int x) {return /*severe:STATIC_TYPE_ERROR*/3;};
+        }
+        {
+          String f/*<S>*/(int x) => null;
+          var v = f;
+          v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => null;
+          v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => "hello";
+          v = /*info:INFERRED_TYPE_CLOSURE, severe:STATIC_TYPE_ERROR*//*<T>*/(x) => 3;
+          v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) {return /*severe:STATIC_TYPE_ERROR*/3;};
+          v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) {return /*severe:STATIC_TYPE_ERROR*/x;};
+        }
+        {
+          List<String> f/*<S>*/(int x) => null;
+          var v = f;
+          v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(int x) => null;
+          v = /*<T>*/(int x) => /*info:INFERRED_TYPE_LITERAL*/["hello"];
+          v = /*severe:STATIC_TYPE_ERROR*//*<T>*/(String x) => /*info:INFERRED_TYPE_LITERAL*/["hello"];
+          v = /*<T>*/(int x) => /*info:INFERRED_TYPE_LITERAL*/[/*severe:STATIC_TYPE_ERROR*/3];
+          v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(int x) {return /*info:INFERRED_TYPE_LITERAL*/[/*severe:STATIC_TYPE_ERROR*/3];};
+        }
+        {
+          int int2int/*<S>*/(int x) => null;
+          String int2String/*<T>*/(int x) => null;
+          String string2String/*<T>*/(String x) => null;
+          var x = int2int;
+          x = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => x;
+          x = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => x+1;
+          var y = int2String;
+          y = /*info:INFERRED_TYPE_CLOSURE, severe:STATIC_TYPE_ERROR*//*<T>*/(x) => x;
+          y = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/x.substring(3);
+          var z = string2String;
+          z = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => x.substring(3);
+        }
+      }
+      ''');
+  });
+
+  test('downwards inference on function<T> using the T', () {
+    checkFile('''
+      void main () {
+        {
+          /*=T*/ f/*<T>*/(/*=T*/ x) => null;
+          var v1 = f;
+          v1 = /*info:INFERRED_TYPE_CLOSURE*//*<S>*/(x) => x;
+        }
+        {
+          /*=List<T>*/ f/*<T>*/(/*=T*/ x) => null;
+          var v2 = f;
+          v2 = /*info:INFERRED_TYPE_CLOSURE*//*<S>*/(x) => /*info:INFERRED_TYPE_LITERAL*/[x];
+          Iterable<int> r = v2(42);
+          Iterable<String> s = v2('hello');
+          Iterable<List<int>> t = v2(<int>[]);
+          Iterable<num> u = v2(42);
+          Iterable<num> v = v2/*<num>*/(42);
+        }
+      }
+    ''');
+  });
+
   test('downwards inference initializing formal, default formal', () {
     checkFile('''
       typedef T Function2<S, T>([S x]);
@@ -1500,7 +1569,7 @@
         Foo.named([List<int> x = /*info:INFERRED_TYPE_LITERAL*/const [1]]);
       }
       void f([List<int> l = /*info:INFERRED_TYPE_LITERAL*/const [1]]) {}
-// We do this inference in an early task but don't preserve the infos.
+      // We do this inference in an early task but don't preserve the infos.
       Function2<List<int>, String> g = /*pass should be info:INFERRED_TYPE_CLOSURE*/([llll = /*info:INFERRED_TYPE_LITERAL*/const [1]]) => "hello";
 ''');
   });
@@ -1696,14 +1765,23 @@
   takeIIO(new C().m);
   takeDDO(new C().m);
 
-  takeOOI(/*severe:STATIC_TYPE_ERROR*/new C().m);
-  takeIDI(/*severe:STATIC_TYPE_ERROR*/new C().m);
-  takeDID(/*severe:STATIC_TYPE_ERROR*/new C().m);
-
   // Note: this is a warning because a downcast of a method tear-off could work
-  // (derived method can be a subtype).
+  // (derived method can be a subtype):
+  //
+  //     class D extends C {
+  //       S m<S extends num>(Object x, Object y);
+  //     }
+  //
+  // That's legal because we're loosening parameter types.
+  //
   takeOON(/*warning:DOWN_CAST_COMPOSITE*/new C().m);
   takeOOO(/*warning:DOWN_CAST_COMPOSITE*/new C().m);
+
+  // Note: this is a warning because a downcast of a method tear-off could work
+  // in "normal" Dart, due to bivariance.
+  takeOOI(/*warning:DOWN_CAST_COMPOSITE*/new C().m);
+  takeIDI(/*warning:DOWN_CAST_COMPOSITE*/new C().m);
+  takeDID(/*warning:DOWN_CAST_COMPOSITE*/new C().m);
 }
 
 void takeIII(int fn(int a, int b)) {}
@@ -1722,6 +1800,55 @@
 void takeDDO(Object fn(double a, double b)) {}
   ''');
     });
+
+    // Regression test for https://github.com/dart-lang/sdk/issues/25668
+    test('infer generic method type', () {
+      checkFile('''
+class C {
+  /*=T*/ m/*<T>*/(/*=T*/ x) => x;
+}
+class D extends C {
+  m/*<S>*/(x) => x;
+}
+main() {
+  int y = new D().m/*<int>*/(42);
+  print(y);
+}
+    ''');
+    });
+
+    test('do not infer invalid override of generic method', () {
+      checkFile('''
+class C {
+  /*=T*/ m/*<T>*/(/*=T*/ x) => x;
+}
+class D extends C {
+  /*severe:INVALID_METHOD_OVERRIDE*/m(x) => x;
+}
+main() {
+  int y = /*info:DYNAMIC_CAST*/new D().m/*<int>*/(42);
+  print(y);
+}
+    ''');
+    });
+
+    test('correctly recognize generic upper bound', () {
+      // Regression test for https://github.com/dart-lang/sdk/issues/25740.
+      checkFile('''
+class Foo<T extends Pattern> {
+  void method/*<U extends T>*/(dynamic/*=U*/ u) {}
+}
+main() {
+  new Foo().method/*<String>*/("str");
+  new Foo();
+
+  new Foo<String>().method("str");
+  new Foo().method("str");
+
+  new Foo<String>().method(/*severe:STATIC_TYPE_ERROR*/42);
+}
+      ''');
+    });
   });
 
   // Regression test for https://github.com/dart-lang/dev_compiler/issues/47
@@ -1747,34 +1874,4 @@
   ''');
   });
 
-  // Regression test for https://github.com/dart-lang/sdk/issues/25668
-  test('infer generic method type', () {
-    checkFile('''
-class C {
-  /*=T*/ m/*<T>*/(/*=T*/ x) => x;
-}
-class D extends C {
-  m/*<S>*/(x) => x;
-}
-main() {
-  int y = new D().m/*<int>*/(42);
-  print(y);
-}
-    ''');
-  });
-
-  test('do not infer invalid override of generic method', () {
-    checkFile('''
-class C {
-  /*=T*/ m/*<T>*/(/*=T*/ x) => x;
-}
-class D extends C {
-  /*severe:INVALID_METHOD_OVERRIDE*/m(x) => x;
-}
-main() {
-  int y = /*info:DYNAMIC_CAST*/new D().m/*<int>*/(42);
-  print(y);
-}
-    ''');
-  });
 }
diff --git a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
index 83c0477..e858a37 100644
--- a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
+++ b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
@@ -7,14 +7,13 @@
 library analyzer.test.src.task.strong.strong_test_helper;
 
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/src/context/context.dart' show SdkAnalysisContext;
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/task/strong/checker.dart';
@@ -22,30 +21,11 @@
 import 'package:source_span/source_span.dart';
 import 'package:unittest/unittest.dart';
 
+import '../../context/mock_sdk.dart';
 
 MemoryResourceProvider files;
 bool _checkCalled;
 
-initStrongModeTests() {
-  setUp(() {
-    AnalysisEngine.instance.processRequiredPlugins();
-    files = new MemoryResourceProvider();
-    _checkCalled = false;
-  });
-
-  tearDown(() {
-    // This is a sanity check, in case only addFile is called.
-    expect(_checkCalled, true, reason: 'must call check() method in test case');
-    files = null;
-  });
-}
-
-/// Adds a file using [addFile] and calls [check].
-void checkFile(String content) {
-  addFile(content);
-  check();
-}
-
 /// Adds a file to check. The file should contain:
 ///
 ///   * all expected failures are listed in the source code using comments
@@ -80,20 +60,17 @@
   expect(files.getFile('/main.dart').exists, true,
       reason: '`/main.dart` is missing');
 
-  var uriResolver = new TestUriResolver(files);
+  var uriResolver = new _TestUriResolver(files);
   // Enable task model strong mode
   var context = AnalysisEngine.instance.createAnalysisContext();
   context.analysisOptions.strongMode = true;
   context.analysisOptions.strongModeHints = true;
-  context.sourceFactory = new SourceFactory([
-    new MockDartSdk(_mockSdkSources, reportMissing: true).resolver,
-    uriResolver
-  ]);
+  context.sourceFactory =
+      new SourceFactory([new DartUriResolver(new MockSdk()), uriResolver]);
 
   // Run the checker on /main.dart.
   Source mainSource = uriResolver.resolveAbsolute(new Uri.file('/main.dart'));
-  var initialLibrary =
-      context.resolveCompilationUnit2(mainSource, mainSource);
+  var initialLibrary = context.resolveCompilationUnit2(mainSource, mainSource);
 
   var collector = new _ErrorCollector();
   var checker = new CodeChecker(
@@ -113,120 +90,26 @@
 
       var librarySource = context.getLibrariesContaining(source).single;
       var resolved = context.resolveCompilationUnit2(source, librarySource);
-      var analyzerErrors = context
-          .getErrors(source)
-          .errors
-          .where((error) =>
-              error.errorCode.name.startsWith('STRONG_MODE_INFERRED_TYPE'))
-          .toList();
-      errors.addAll(analyzerErrors);
+      errors.addAll(context.getErrors(source).errors.where((error) =>
+          error.errorCode.name.startsWith('STRONG_MODE_INFERRED_TYPE')));
       checker.visitCompilationUnit(resolved);
 
-      new _ExpectedErrorVisitor(errors).validate(resolved);
+      _expectErrors(resolved, errors);
     }
   }
 }
 
-/// Sample mock SDK sources.
-final Map<String, String> _mockSdkSources = {
-  // The list of types below is derived from:
-  //   * types we use via our smoke queries, including HtmlElement and
-  //     types from `_typeHandlers` (deserialize.dart)
-  //   * types that are used internally by the resolver (see
-  //   _initializeFrom in resolver.dart).
-  'dart:core': '''
-        library dart.core;
-
-        void print(Object o) {}
-
-        class Object {
-          int get hashCode {}
-          Type get runtimeType {}
-          String toString(){}
-          bool ==(other){}
-        }
-        class Function {}
-        class StackTrace {}
-        class Symbol {}
-        class Type {}
-
-        class String {
-          String operator +(String other) {}
-          String substring(int len) {}
-        }
-        class bool {}
-        class num {
-          num operator +(num other) {}
-        }
-        class int extends num {
-          bool operator<(num other) {}
-          int operator-() {}
-        }
-        class double extends num {}
-        class DateTime {}
-        class Null {}
-
-        class Deprecated {
-          final String expires;
-          const Deprecated(this.expires);
-        }
-        const Object deprecated = const Deprecated("next release");
-        class _Override { const _Override(); }
-        const Object override = const _Override();
-        class _Proxy { const _Proxy(); }
-        const Object proxy = const _Proxy();
-
-        class Iterable<E> {
-          Iterable/*<R>*/ map/*<R>*/(/*=R*/ f(E e));
-
-          /*=R*/ fold/*<R>*/(/*=R*/ initialValue,
-              /*=R*/ combine(/*=R*/ previousValue, E element));
-        }
-        class List<E> implements Iterable<E> {
-          List([int length]);
-          List.filled(int length, E fill);
-        }
-        class Map<K, V> {
-          Iterable<K> get keys {}
-        }
-        ''',
-  'dart:async': '''
-        library dart.async;
-        class Future<T> {
-          Future(computation()) {}
-          Future.value(T t) {}
-          static Future<List/*<T>*/> wait/*<T>*/(
-              Iterable<Future/*<T>*/> futures) => null;
-          Future/*<R>*/ then/*<R>*/(/*=R*/ onValue(T value)) => null;
-        }
-        class Stream<T> {}
-  ''',
-  'dart:html': '''
-        library dart.html;
-        class HtmlElement {}
-        ''',
-  'dart:math': '''
-        library dart.math;
-        class Random {
-          bool nextBool() {}
-        }
-        num/*=T*/ min/*<T extends num>*/(num/*=T*/ a, num/*=T*/ b) => null;
-        num/*=T*/ max/*<T extends num>*/(num/*=T*/ a, num/*=T*/ b) => null;
-        ''',
-
-  'dart:_foreign_helper': '''
-  library dart._foreign_helper;
-
-  JS(String typeDescription, String codeTemplate,
-    [arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11])
-  {}
-  '''
-};
+/// Adds a file using [addFile] and calls [check].
+void checkFile(String content) {
+  addFile(content);
+  check();
+}
 
 SourceSpanWithContext createSpanHelper(
-    LineInfo lineInfo, int start, int end, Source source, String content) {
+    LineInfo lineInfo, int start, Source source, String content,
+    {int end}) {
   var startLoc = locationForOffset(lineInfo, source.uri, start);
-  var endLoc = locationForOffset(lineInfo, source.uri, end);
+  var endLoc = locationForOffset(lineInfo, source.uri, end ?? start);
 
   var lineStart = startLoc.offset - startLoc.column;
   // Find the end of the line. This is not exposed directly on LineInfo, but
@@ -238,6 +121,11 @@
   while (lineEnd < content.length &&
       lineInfo.getLocation(++lineEnd).lineNumber == lineNum);
 
+  if (end == null) {
+    end = lineEnd;
+    endLoc = locationForOffset(lineInfo, source.uri, lineEnd);
+  }
+
   var text = content.substring(start, end);
   var lineText = content.substring(lineStart, lineEnd);
   return new SourceSpanWithContext(startLoc, endLoc, text, lineText);
@@ -255,6 +143,20 @@
   }
 }
 
+initStrongModeTests() {
+  setUp(() {
+    AnalysisEngine.instance.processRequiredPlugins();
+    files = new MemoryResourceProvider();
+    _checkCalled = false;
+  });
+
+  tearDown(() {
+    // This is a sanity check, in case only addFile is called.
+    expect(_checkCalled, true, reason: 'must call check() method in test case');
+    files = null;
+  });
+}
+
 // TODO(jmesserly): can we reuse the same mock SDK as Analyzer tests?
 SourceLocation locationForOffset(LineInfo lineInfo, Uri uri, int offset) {
   var loc = lineInfo.getLocation(offset);
@@ -277,77 +179,121 @@
   return results;
 }
 
-/// Dart SDK which contains a mock implementation of the SDK libraries. May be
-/// used to speed up execution when most of the core libraries is not needed.
-class MockDartSdk implements DartSdk {
-  final Map<Uri, _MockSdkSource> _sources = {};
-  final bool reportMissing;
-  final Map<String, SdkLibrary> _libs = {};
-  final String sdkVersion = '0';
-  final AnalysisContext context = new SdkAnalysisContext();
-  DartUriResolver _resolver;
-  MockDartSdk(Map<String, String> sources, {this.reportMissing}) {
-    sources.forEach((uriString, contents) {
-      var uri = Uri.parse(uriString);
-      _sources[uri] = new _MockSdkSource(uri, contents);
-      _libs[uriString] = new SdkLibraryImpl(uri.path)
-        ..setDart2JsLibrary()
-        ..setVmLibrary();
-    });
-    _resolver = new DartUriResolver(this);
-    context.sourceFactory = new SourceFactory([_resolver]);
-  }
-  DartUriResolver get resolver => _resolver;
+Level _actualErrorLevel(AnalysisError actual) {
+  return const <ErrorSeverity, Level>{
+    ErrorSeverity.ERROR: Level.SEVERE,
+    ErrorSeverity.WARNING: Level.WARNING,
+    ErrorSeverity.INFO: Level.INFO
+  }[actual.errorCode.errorSeverity];
+}
 
-  List<SdkLibrary> get sdkLibraries => _libs.values.toList();
+void _expectErrors(CompilationUnit unit, List<AnalysisError> actualErrors) {
+  var expectedErrors = _findExpectedErrors(unit.beginToken);
 
-  List<String> get uris => _sources.keys.map((uri) => '$uri').toList();
-  Source fromEncoding(UriKind kind, Uri uri) {
-    if (kind != UriKind.DART_URI) {
-      throw new UnsupportedError('expected dart: uri kind, got $kind.');
+  // Categorize the differences, if any.
+  var unreported = <_ErrorExpectation>[];
+  var different = <_ErrorExpectation, AnalysisError>{};
+
+  for (var expected in expectedErrors) {
+    AnalysisError actual = expected._removeMatchingActual(actualErrors);
+    if (actual != null) {
+      if (_actualErrorLevel(actual) != expected.level ||
+          errorCodeName(actual.errorCode) != expected.typeName) {
+        different[expected] = actual;
+      }
+    } else {
+      unreported.add(expected);
     }
-    return _getSource(uri);
   }
 
-  @override
-  Source fromFileUri(Uri uri) {
-    throw new UnsupportedError('MockDartSdk.fromFileUri');
-  }
+  // Whatever is left was an unexpected error.
+  List<AnalysisError> unexpected = actualErrors;
 
-  SdkLibrary getSdkLibrary(String dartUri) => _libs[dartUri];
-
-  Source mapDartUri(String dartUri) => _getSource(Uri.parse(dartUri));
-
-  Source _getSource(Uri uri) {
-    var src = _sources[uri];
-    if (src == null) {
-      if (reportMissing) print('warning: missing mock for $uri.');
-      _sources[uri] =
-          src = new _MockSdkSource(uri, 'library dart.${uri.path};');
-    }
-    return src;
+  if (unreported.isNotEmpty || unexpected.isNotEmpty || different.isNotEmpty) {
+    _reportFailure(unit, unreported, unexpected, different);
   }
 }
 
-class TestUriResolver extends ResourceUriResolver {
-  final MemoryResourceProvider provider;
-  TestUriResolver(provider)
-      : provider = provider,
-        super(provider);
+List<_ErrorExpectation> _findExpectedErrors(Token beginToken) {
+  var expectedErrors = <_ErrorExpectation>[];
 
-  @override
-  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
-    if (uri.scheme == 'package') {
-      return (provider.getResource('/packages/' + uri.path) as File)
-          .createSource(uri);
+  // Collect expectations like "severe:STATIC_TYPE_ERROR" from comment tokens.
+  for (Token t = beginToken; t.type != TokenType.EOF; t = t.next) {
+    for (CommentToken c = t.precedingComments; c != null; c = c.next) {
+      if (c.type == TokenType.MULTI_LINE_COMMENT) {
+        String value = c.lexeme.substring(2, c.lexeme.length - 2);
+        if (value.contains(':')) {
+          var offset = c.end;
+          if (c.next?.type == TokenType.GENERIC_METHOD_TYPE_LIST) {
+            offset += 2;
+          }
+          for (var expectCode in value.split(',')) {
+            var expected = _ErrorExpectation.parse(offset, expectCode);
+            if (expected != null) {
+              expectedErrors.add(expected);
+            }
+          }
+        }
+      }
     }
-    return super.resolveAbsolute(uri, actualUri);
   }
+  return expectedErrors;
+}
+
+void _reportFailure(
+    CompilationUnit unit,
+    List<_ErrorExpectation> unreported,
+    List<AnalysisError> unexpected,
+    Map<_ErrorExpectation, AnalysisError> different) {
+  // Get the source code. This reads the data again, but it's safe because
+  // all tests use memory file system.
+  var sourceCode = unit.element.source.contents.data;
+
+  String formatActualError(AnalysisError error) {
+    int offset = error.offset;
+    int length = error.length;
+    var span = createSpanHelper(
+        unit.lineInfo, offset, unit.element.source, sourceCode,
+        end: offset + length);
+    var levelName = _actualErrorLevel(error).name.toLowerCase();
+    return '@$offset $levelName: [${errorCodeName(error.errorCode)}]\n' +
+        span.message(error.message);
+  }
+
+  String formatExpectedError(_ErrorExpectation error) {
+    int offset = error.offset;
+    var span = createSpanHelper(
+        unit.lineInfo, offset, unit.element.source, sourceCode);
+    var levelName = error.level.toString().toLowerCase();
+    return '@$offset $levelName: [${error.typeName}]\n' + span.message('');
+  }
+
+  var message = new StringBuffer();
+  if (unreported.isNotEmpty) {
+    message.writeln('Expected errors that were not reported:');
+    unreported.map(formatExpectedError).forEach(message.writeln);
+    message.writeln();
+  }
+  if (unexpected.isNotEmpty) {
+    message.writeln('Errors that were not expected:');
+    unexpected.map(formatActualError).forEach(message.writeln);
+    message.writeln();
+  }
+  if (different.isNotEmpty) {
+    message.writeln('Errors that were reported, but different than expected:');
+    different.forEach((expected, actual) {
+      message.writeln('Expected: ' + formatExpectedError(expected));
+      message.writeln('Actual: ' + formatActualError(actual));
+    });
+    message.writeln();
+  }
+  fail('Checker errors do not match expected errors:\n\n$message');
 }
 
 class _ErrorCollector implements AnalysisErrorListener {
   List<AnalysisError> errors;
   final bool hints;
+
   _ErrorCollector({this.hints: true});
 
   void onError(AnalysisError error) {
@@ -361,26 +307,39 @@
 
 /// Describes an expected message that should be produced by the checker.
 class _ErrorExpectation {
+  final int offset;
   final Level level;
   final String typeName;
-  _ErrorExpectation(this.level, this.typeName);
 
-  String toString() => '$level $typeName';
+  _ErrorExpectation(this.offset, this.level, this.typeName);
 
-  static _ErrorExpectation parse(String descriptor) {
+  String toString() =>
+      '@$offset ${level.toString().toLowerCase()}: [$typeName]';
+
+  AnalysisError _removeMatchingActual(List<AnalysisError> actualErrors) {
+    for (var actual in actualErrors) {
+      if (actual.offset == offset) {
+        actualErrors.remove(actual);
+        return actual;
+      }
+    }
+    return null;
+  }
+
+  static _ErrorExpectation parse(int offset, String descriptor) {
     descriptor = descriptor.trim();
     var tokens = descriptor.split(' ');
-    if (tokens.length == 1) return _parse(tokens[0]);
+    if (tokens.length == 1) return _parse(offset, tokens[0]);
     expect(tokens.length, 4, reason: 'invalid error descriptor');
     expect(tokens[1], "should", reason: 'invalid error descriptor');
     expect(tokens[2], "be", reason: 'invalid error descriptor');
     if (tokens[0] == "pass") return null;
     // TODO(leafp) For now, we just use whatever the current expectation is,
     // eventually we could do more automated reporting here.
-    return _parse(tokens[0]);
+    return _parse(offset, tokens[0]);
   }
 
-  static _ErrorExpectation _parse(String descriptor) {
+  static _ErrorExpectation _parse(offset, String descriptor) {
     var tokens = descriptor.split(':');
     expect(tokens.length, 2, reason: 'invalid error descriptor');
     var name = tokens[0].toUpperCase();
@@ -392,155 +351,22 @@
         reason: 'invalid level in error descriptor: `${tokens[0]}`');
     expect(typeName, isNotNull,
         reason: 'invalid type in error descriptor: ${tokens[1]}');
-    return new _ErrorExpectation(level, typeName);
+    return new _ErrorExpectation(offset, level, typeName);
   }
 }
 
-class _ExpectedErrorVisitor extends UnifyingAstVisitor {
-  final Set<AnalysisError> _actualErrors;
-  CompilationUnit _unit;
-  String _unitSourceCode;
+class _TestUriResolver extends ResourceUriResolver {
+  final MemoryResourceProvider provider;
+  _TestUriResolver(provider)
+      : provider = provider,
+        super(provider);
 
-  _ExpectedErrorVisitor(List<AnalysisError> actualErrors)
-      : _actualErrors = new Set.from(actualErrors);
-
-  validate(CompilationUnit unit) {
-    _unit = unit;
-    // This reads the file. Only safe because tests use MemoryFileSystem.
-    _unitSourceCode = unit.element.source.contents.data;
-
-    // Visit the compilation unit.
-    unit.accept(this);
-
-    if (_actualErrors.isNotEmpty) {
-      var actualMsgs = _actualErrors.map(_formatActualError).join('\n');
-      fail('Unexpected errors reported by checker:\n\n$actualMsgs');
+  @override
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
+    if (uri.scheme == 'package') {
+      return (provider.getResource('/packages/' + uri.path) as File)
+          .createSource(uri);
     }
+    return super.resolveAbsolute(uri, actualUri);
   }
-
-  visitNode(AstNode node) {
-    var token = node.beginToken;
-    var comment = token.precedingComments;
-    // Use error marker found in an immediately preceding comment,
-    // and attach it to the outermost expression that starts at that token.
-    if (comment != null) {
-      while (comment.next != null) {
-        comment = comment.next;
-      }
-      if (comment.end == token.offset && node.parent.beginToken != token) {
-        var commentText = '$comment';
-        var start = commentText.lastIndexOf('/*');
-        var end = commentText.lastIndexOf('*/');
-        if (start != -1 &&
-            end != -1 &&
-            !commentText.startsWith('/*<', start) &&
-            !commentText.startsWith('/*=', start)) {
-          expect(start, lessThan(end));
-          var errors = commentText.substring(start + 2, end).split(',');
-          var expectations =
-              errors.map(_ErrorExpectation.parse).where((x) => x != null);
-
-          for (var e in expectations) {
-            _expectError(node, e);
-          }
-        }
-      }
-    }
-    return super.visitNode(node);
-  }
-
-  Level _actualErrorLevel(AnalysisError actual) {
-    return const <ErrorSeverity, Level>{
-      ErrorSeverity.ERROR: Level.SEVERE,
-      ErrorSeverity.WARNING: Level.WARNING,
-      ErrorSeverity.INFO: Level.INFO
-    }[actual.errorCode.errorSeverity];
-  }
-
-  SourceSpan _createSpan(int offset, int len) {
-    return createSpanHelper(_unit.lineInfo, offset, offset + len,
-        _unit.element.source, _unitSourceCode);
-  }
-
-  void _expectError(AstNode node, _ErrorExpectation expected) {
-    // See if we can find the expected error in our actual errors
-    for (var actual in _actualErrors) {
-      if (actual.offset == node.offset && actual.length == node.length) {
-        var actualMsg = _formatActualError(actual);
-        expect(_actualErrorLevel(actual), expected.level,
-            reason: 'expected different error code at:\n\n$actualMsg');
-        expect(errorCodeName(actual.errorCode), expected.typeName,
-            reason: 'expected different error type at:\n\n$actualMsg');
-
-        // We found it. Stop the search.
-        _actualErrors.remove(actual);
-        return;
-      }
-    }
-
-    var span = _createSpan(node.offset, node.length);
-    var levelName = expected.level.name.toLowerCase();
-    var msg = span.message(expected.typeName, color: _colorOf(levelName));
-    fail('expected error was not reported at:\n\n$levelName: $msg');
-  }
-
-  String _formatActualError(AnalysisError actual) {
-    var span = _createSpan(actual.offset, actual.length);
-    var levelName = _actualErrorLevel(actual).name.toLowerCase();
-    var msg = span.message(actual.message, color: _colorOf(levelName));
-    return '$levelName: [${errorCodeName(actual.errorCode)}] $msg';
-  }
-
-  /// Returns an ANSII color escape sequence corresponding to [levelName].
-  ///
-  /// Colors are defined for: severe, error, warning, or info.
-  /// Returns null if the level name is not recognized.
-  String _colorOf(String levelName) {
-    const String CYAN_COLOR = '\u001b[36m';
-    const String MAGENTA_COLOR = '\u001b[35m';
-    const String RED_COLOR = '\u001b[31m';
-
-    levelName = levelName.toLowerCase();
-    if (levelName == 'shout' || levelName == 'severe' || levelName == 'error') {
-      return RED_COLOR;
-    }
-    if (levelName == 'warning') return MAGENTA_COLOR;
-    if (levelName == 'info') return CYAN_COLOR;
-    return null;
-  }
-}
-
-class _MockSdkSource implements Source {
-  /// Absolute URI which this source can be imported from.
-  final Uri uri;
-  final String _contents;
-
-  final int modificationStamp = 1;
-
-  _MockSdkSource(this.uri, this._contents);
-
-  TimestampedData<String> get contents =>
-      new TimestampedData(modificationStamp, _contents);
-
-  String get encoding => "${uriKind.encoding}$uri";
-
-  String get fullName => shortName;
-
-  int get hashCode => uri.hashCode;
-
-  bool get isInSystemLibrary => true;
-
-  String get shortName => uri.path;
-
-  Source get source => this;
-
-  UriKind get uriKind => UriKind.DART_URI;
-
-  bool exists() => true;
-
-  Source resolveRelative(Uri relativeUri) =>
-      throw new UnsupportedError('not expecting relative urls in dart: mocks');
-
-  Uri resolveRelativeUri(Uri relativeUri) =>
-      throw new UnsupportedError('not expecting relative urls in dart: mocks');
 }
diff --git a/pkg/analyzer/tool/summary/build_sdk_summaries.dart b/pkg/analyzer/tool/summary/build_sdk_summaries.dart
index 2e680da..8e6c5fc 100644
--- a/pkg/analyzer/tool/summary/build_sdk_summaries.dart
+++ b/pkg/analyzer/tool/summary/build_sdk_summaries.dart
@@ -44,8 +44,8 @@
   //
   // Build spec and strong summaries.
   //
-  _buildSummary(sdkPath, outputDirectoryPath, false);
-  _buildSummary(sdkPath, outputDirectoryPath, true);
+  new _Builder(sdkPath, outputDirectoryPath, false).build();
+  new _Builder(sdkPath, outputDirectoryPath, true).build();
 }
 
 /**
@@ -54,58 +54,92 @@
 const BINARY_NAME = "build_sdk_summaries";
 
 /**
- * Build a strong or spec mode summary for the Dart SDK at [sdkPath].
- */
-void _buildSummary(
-    String sdkPath, String outputDirectoryPath, bool strongMode) {
-  print('Generating ${strongMode ? 'strong' : 'spec'} mode summary.');
-  Stopwatch sw = new Stopwatch()..start();
-  //
-  // Prepare SDK.
-  //
-  DirectoryBasedDartSdk sdk = new DirectoryBasedDartSdk(new JavaFile(sdkPath));
-  AnalysisContext context = sdk.context;
-  context.analysisOptions = new AnalysisOptionsImpl()..strongMode = strongMode;
-  //
-  // Serialize each SDK library.
-  //
-  List<String> linkedLibraryUris = <String>[];
-  List<LinkedLibraryBuilder> linkedLibraries = <LinkedLibraryBuilder>[];
-  List<String> unlinkedUnitUris = <String>[];
-  List<UnlinkedUnitBuilder> unlinkedUnits = <UnlinkedUnitBuilder>[];
-  for (SdkLibrary lib in sdk.sdkLibraries) {
-    Source librarySource = sdk.mapDartUri(lib.shortName);
-    LibraryElement libraryElement =
-        context.computeLibraryElement(librarySource);
-    LibrarySerializationResult libraryResult =
-        serializeLibrary(libraryElement, context.typeProvider, strongMode);
-    linkedLibraryUris.add(lib.shortName);
-    linkedLibraries.add(libraryResult.linked);
-    unlinkedUnitUris.addAll(libraryResult.unitUris);
-    unlinkedUnits.addAll(libraryResult.unlinkedUnits);
-  }
-  //
-  // Write the whole SDK bundle.
-  //
-  SdkBundleBuilder sdkBundle = new SdkBundleBuilder(
-      linkedLibraryUris: linkedLibraryUris,
-      linkedLibraries: linkedLibraries,
-      unlinkedUnitUris: unlinkedUnitUris,
-      unlinkedUnits: unlinkedUnits);
-  String outputFilePath =
-      join(outputDirectoryPath, strongMode ? 'strong.sum' : 'spec.sum');
-  File file = new File(outputFilePath);
-  file.writeAsBytesSync(sdkBundle.toBuffer(), mode: FileMode.WRITE_ONLY);
-  //
-  // Done.
-  //
-  print('\tDone in ${sw.elapsedMilliseconds} ms.');
-}
-
-/**
  * Print information about how to use the SDK summaries builder.
  */
 void _printUsage() {
   print('Usage: $BINARY_NAME output_directory_path [sdk_path]');
   print('Build files spec.sum and strong.sum in the output directory.');
 }
+
+class _Builder {
+  final String sdkPath;
+  final String outputDirectoryPath;
+  final bool strongMode;
+
+  AnalysisContext context;
+  final Set<Source> processedSources = new Set<Source>();
+
+  final List<String> linkedLibraryUris = <String>[];
+  final List<LinkedLibraryBuilder> linkedLibraries = <LinkedLibraryBuilder>[];
+  final List<String> unlinkedUnitUris = <String>[];
+  final List<UnlinkedUnitBuilder> unlinkedUnits = <UnlinkedUnitBuilder>[];
+
+  _Builder(this.sdkPath, this.outputDirectoryPath, this.strongMode);
+
+  /**
+   * Build a strong or spec mode summary for the Dart SDK at [sdkPath].
+   */
+  void build() {
+    print('Generating ${strongMode ? 'strong' : 'spec'} mode summary.');
+    Stopwatch sw = new Stopwatch()..start();
+    //
+    // Prepare SDK.
+    //
+    DirectoryBasedDartSdk sdk =
+        new DirectoryBasedDartSdk(new JavaFile(sdkPath));
+    sdk.useSummary = false;
+    context = sdk.context;
+    context.analysisOptions = new AnalysisOptionsImpl()
+      ..strongMode = strongMode;
+    //
+    // Serialize each SDK library.
+    //
+    for (SdkLibrary lib in sdk.sdkLibraries) {
+      Source libSource = sdk.mapDartUri(lib.shortName);
+      _serializeLibrary(libSource);
+    }
+    //
+    // Write the whole SDK bundle.
+    //
+    SdkBundleBuilder sdkBundle = new SdkBundleBuilder(
+        linkedLibraryUris: linkedLibraryUris,
+        linkedLibraries: linkedLibraries,
+        unlinkedUnitUris: unlinkedUnitUris,
+        unlinkedUnits: unlinkedUnits);
+    String outputFilePath =
+        join(outputDirectoryPath, strongMode ? 'strong.sum' : 'spec.sum');
+    File file = new File(outputFilePath);
+    file.writeAsBytesSync(sdkBundle.toBuffer(), mode: FileMode.WRITE_ONLY);
+    //
+    // Done.
+    //
+    print('\tDone in ${sw.elapsedMilliseconds} ms.');
+  }
+
+  /**
+   * Serialize the library with the given [source] and all its direct or
+   * indirect imports and exports.
+   */
+  void _serializeLibrary(Source source) {
+    if (!processedSources.add(source)) {
+      return;
+    }
+    LibraryElement element = context.computeLibraryElement(source);
+    _serializeSingleLibrary(element);
+    element.importedLibraries.forEach((e) => _serializeLibrary(e.source));
+    element.exportedLibraries.forEach((e) => _serializeLibrary(e.source));
+  }
+
+  /**
+   * Serialize the library with the given [element].
+   */
+  void _serializeSingleLibrary(LibraryElement element) {
+    String uri = element.source.uri.toString();
+    LibrarySerializationResult libraryResult =
+        serializeLibrary(element, context.typeProvider, strongMode);
+    linkedLibraryUris.add(uri);
+    linkedLibraries.add(libraryResult.linked);
+    unlinkedUnitUris.addAll(libraryResult.unitUris);
+    unlinkedUnits.addAll(libraryResult.unlinkedUnits);
+  }
+}
diff --git a/pkg/analyzer/tool/summary/generate.dart b/pkg/analyzer/tool/summary/generate.dart
index 5c2d2bf..ba4a49e 100644
--- a/pkg/analyzer/tool/summary/generate.dart
+++ b/pkg/analyzer/tool/summary/generate.dart
@@ -23,11 +23,13 @@
 import 'dart:io' hide File;
 
 import 'package:analyzer/analyzer.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:path/path.dart';
 
@@ -82,6 +84,7 @@
    */
   void checkIdl() {
     _idl.classes.forEach((String name, idlModel.ClassDeclaration cls) {
+      Map<int, String> idsUsed = <int, String>{};
       for (idlModel.FieldDeclaration field in cls.fields) {
         String fieldName = field.name;
         idlModel.FieldType type = field.type;
@@ -101,6 +104,16 @@
                 '$name.$fieldName: illegal type (list of ${type.typeName})');
           }
         }
+        if (idsUsed.containsKey(field.id)) {
+          throw new Exception('$name.$fieldName: id ${field.id} already used by'
+              ' ${idsUsed[field.id]}');
+        }
+        idsUsed[field.id] = fieldName;
+      }
+      for (int i = 0; i < idsUsed.length; i++) {
+        if (!idsUsed.containsKey(i)) {
+          throw new Exception('$name: no field uses id $i');
+        }
       }
     });
   }
@@ -193,9 +206,10 @@
         }
         for (ClassMember classMember in decl.members) {
           if (classMember is MethodDeclaration && classMember.isGetter) {
+            String desc = '${cls.name}.${classMember.name.name}';
             TypeName type = classMember.returnType;
             if (type == null) {
-              throw new Exception('Class member needs a type: $classMember');
+              throw new Exception('Class member needs a type: $desc');
             }
             bool isList = false;
             if (type.name.name == 'List' &&
@@ -207,11 +221,34 @@
             if (type.typeArguments != null) {
               throw new Exception('Cannot handle type arguments in `$type`');
             }
+            int id;
+            for (Annotation annotation in classMember.metadata) {
+              if (annotation.name.name == 'Id') {
+                if (id != null) {
+                  throw new Exception(
+                      'Duplicate @id annotation ($classMember)');
+                }
+                if (annotation.arguments.arguments.length != 1) {
+                  throw new Exception(
+                      '@Id must be passed exactly one argument ($desc)');
+                }
+                Expression expression = annotation.arguments.arguments[0];
+                if (expression is IntegerLiteral) {
+                  id = expression.value;
+                } else {
+                  throw new Exception(
+                      '@Id parameter must be an integer literal ($desc)');
+                }
+              }
+            }
+            if (id == null) {
+              throw new Exception('Missing @id annotation ($desc)');
+            }
             String doc = _getNodeDoc(lineInfo, classMember);
             idlModel.FieldType fieldType =
                 new idlModel.FieldType(type.name.name, isList);
             cls.fields.add(new idlModel.FieldDeclaration(
-                doc, classMember.name.name, fieldType));
+                doc, classMember.name.name, fieldType, id));
           } else if (classMember is ConstructorDeclaration &&
               classMember.name.name == 'fromBuffer') {
             // Ignore `fromBuffer` declarations; they simply forward to the
@@ -404,7 +441,7 @@
         out('assert(!_finished);');
         out('_finished = true;');
         // Write objects and remember Offset(s).
-        cls.fields.asMap().forEach((index, idlModel.FieldDeclaration field) {
+        for (idlModel.FieldDeclaration field in cls.fields) {
           idlModel.FieldType fieldType = field.type;
           String offsetName = 'offset_' + field.name;
           if (fieldType.isList ||
@@ -412,8 +449,8 @@
               _idl.classes.containsKey(fieldType.typeName)) {
             out('fb.Offset $offsetName;');
           }
-        });
-        cls.fields.asMap().forEach((index, idlModel.FieldDeclaration field) {
+        }
+        for (idlModel.FieldDeclaration field in cls.fields) {
           idlModel.FieldType fieldType = field.type;
           String valueName = '_' + field.name;
           String offsetName = 'offset_' + field.name;
@@ -428,7 +465,7 @@
             } else if (_idl.enums.containsKey(fieldType.typeName)) {
               String itemCode = 'b.index';
               String listCode = '$valueName.map((b) => $itemCode).toList()';
-              writeCode = '$offsetName = fbBuilder.writeListUint32($listCode);';
+              writeCode = '$offsetName = fbBuilder.writeListUint8($listCode);';
             } else if (fieldType.typeName == 'int') {
               writeCode =
                   '$offsetName = fbBuilder.writeListUint32($valueName);';
@@ -457,10 +494,11 @@
             });
             out('}');
           }
-        });
+        }
         // Write the table.
         out('fbBuilder.startTable();');
-        cls.fields.asMap().forEach((index, idlModel.FieldDeclaration field) {
+        for (idlModel.FieldDeclaration field in cls.fields) {
+          int index = field.id;
           idlModel.FieldType fieldType = field.type;
           String valueName = '_' + field.name;
           String condition = '$valueName != null';
@@ -479,7 +517,7 @@
             writeCode = 'fbBuilder.addUint32($index, $valueName);';
           } else if (_idl.enums.containsKey(fieldType.typeName)) {
             condition += ' && $valueName != ${defaultValue(fieldType, true)}';
-            writeCode = 'fbBuilder.addUint32($index, $valueName.index);';
+            writeCode = 'fbBuilder.addUint8($index, $valueName.index);';
           }
           if (writeCode == null) {
             throw new UnimplementedError('Writing type ${fieldType.typeName}');
@@ -489,7 +527,7 @@
             out(writeCode);
           });
           out('}');
-        });
+        }
         out('return fbBuilder.endTable();');
       });
       out('}');
@@ -505,12 +543,12 @@
       out('const $readerName() : super();');
       out();
       out('@override');
-      out('int get size => 4;');
+      out('int get size => 1;');
       out();
       out('@override');
       out('${idlPrefix(name)} read(fb.BufferPointer bp) {');
       indent(() {
-        out('int index = const fb.Uint32Reader().read(bp);');
+        out('int index = const fb.Uint8Reader().read(bp);');
         out('return ${idlPrefix(name)}.values[index];');
       });
       out('}');
@@ -536,7 +574,8 @@
         out('$returnType _$fieldName;');
       }
       // Write getters.
-      cls.fields.asMap().forEach((index, field) {
+      for (idlModel.FieldDeclaration field in cls.fields) {
+        int index = field.id;
         String fieldName = field.name;
         idlModel.FieldType type = field.type;
         String typeName = type.typeName;
@@ -545,8 +584,7 @@
         String def = defaultValue(type, false);
         if (type.isList) {
           if (typeName == 'int') {
-            String itemCode = 'const fb.Uint32Reader()';
-            readCode = 'const fb.ListReader<int>($itemCode)';
+            readCode = 'const fb.Uint32ListReader()';
           } else if (typeName == 'double') {
             readCode = 'const fb.Float64ListReader()';
           } else if (typeName == 'String') {
@@ -583,7 +621,7 @@
           out('return _$fieldName;');
         });
         out('}');
-      });
+      }
     });
     out('}');
   }
diff --git a/pkg/analyzer/tool/summary/idl_model.dart b/pkg/analyzer/tool/summary/idl_model.dart
index 9317215..fca1054 100644
--- a/pkg/analyzer/tool/summary/idl_model.dart
+++ b/pkg/analyzer/tool/summary/idl_model.dart
@@ -74,7 +74,12 @@
    */
   final FieldType type;
 
-  FieldDeclaration(String documentation, String name, this.type)
+  /**
+   * The id of the field.
+   */
+  final int id;
+
+  FieldDeclaration(String documentation, String name, this.type, this.id)
       : super(documentation, name);
 }
 
diff --git a/pkg/analyzer/tool/summary/stats.dart b/pkg/analyzer/tool/summary/stats.dart
new file mode 100644
index 0000000..da524a0
--- /dev/null
+++ b/pkg/analyzer/tool/summary/stats.dart
@@ -0,0 +1,103 @@
+// 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.
+
+/**
+ * This file contains code for collecting statistics about the use of fields in
+ * a summary file.
+ */
+library analyzer.tool.summary.stats;
+
+import 'dart:io';
+import 'dart:mirrors';
+
+import 'package:analyzer/src/summary/base.dart';
+import 'package:analyzer/src/summary/idl.dart';
+
+main(List<String> args) {
+  if (args.length != 1) {
+    _printUsage();
+    exitCode = 1;
+    return;
+  }
+
+  String inputFilePath = args[0];
+
+  // Read the input.
+  SdkBundle bundle =
+      new SdkBundle.fromBuffer(new File(inputFilePath).readAsBytesSync());
+
+  // Compute and output stats.
+  Stats stats = new Stats();
+  stats.record(bundle);
+  stats.dump();
+}
+
+/**
+ * The name of the stats tool.
+ */
+const String BINARY_NAME = "stats";
+
+/**
+ * Print information about how to use the stats tool.
+ */
+void _printUsage() {
+  print('Usage: $BINARY_NAME input_file_path');
+}
+
+/**
+ * An instance of [Stats] keeps track of statistics about the use of fields in
+ * summary objects.
+ */
+class Stats {
+  /**
+   * Map from type to field name to a count of how often the field is used.
+   */
+  Map<Type, Map<String, int>> counts = <Type, Map<String, int>>{};
+
+  /**
+   * Print out statistics gathered so far.
+   */
+  void dump() {
+    counts.forEach((Type type, Map<String, int> typeCounts) {
+      print(type);
+      List<String> keys = typeCounts.keys.toList();
+      keys.sort((String a, String b) => typeCounts[b].compareTo(typeCounts[a]));
+      for (String key in keys) {
+        print('  $key: ${typeCounts[key]}');
+      }
+      print('');
+    });
+  }
+
+  /**
+   * Record statistics for [obj] and all objects it refers to.
+   */
+  void record(SummaryClass obj) {
+    Map<String, int> typeCounts =
+        counts.putIfAbsent(obj.runtimeType, () => <String, int>{});
+    obj.toMap().forEach((String key, Object value) {
+      if (value == null ||
+          value == 0 ||
+          value == false ||
+          value == '' ||
+          value is List && value.isEmpty ||
+          reflect(value).type.isEnum && (value as dynamic).index == 0) {
+        return;
+      }
+      if (!typeCounts.containsKey(key)) {
+        typeCounts[key] = 0;
+      }
+      typeCounts[key]++;
+      if (value is SummaryClass) {
+        record(value);
+      } else if (value is List) {
+        value.forEach((Object element) {
+          if (element is SummaryClass) {
+            record(element);
+          }
+        });
+      }
+    });
+  }
+}
diff --git a/pkg/analyzer/tool/task_dependency_graph/tasks.dot b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
index 3953adc..1f14eda 100644
--- a/pkg/analyzer/tool/task_dependency_graph/tasks.dot
+++ b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
@@ -76,6 +76,8 @@
   DART_ERRORS [shape=box]
   DART_SCRIPTS -> ScanDartTask
   DART_SCRIPTS [shape=box]
+  DEFINED_ELEMENTS -> GenerateHintsTask
+  DEFINED_ELEMENTS [shape=box]
   DartErrorsTask -> DART_ERRORS
   EXPLICITLY_IMPORTED_LIBRARIES [shape=box]
   EXPORTED_LIBRARIES -> BuildDirectiveElementsTask
@@ -88,6 +90,7 @@
   EvaluateUnitConstantsTask -> CREATED_RESOLVED_UNIT11
   EvaluateUnitConstantsTask -> RESOLVED_UNIT11
   GatherUsedImportedElementsTask -> USED_IMPORTED_ELEMENTS
+  GatherUsedLocalElementsTask -> DEFINED_ELEMENTS
   GatherUsedLocalElementsTask -> USED_LOCAL_ELEMENTS
   GenerateHintsTask -> HINTS
   GenerateLintsTask -> LINTS
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 58e4359..3de4b4d 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -290,7 +290,9 @@
       packagesRequiringFullParse = null;
     }
     return (Source source) {
-      if (source.uri.scheme == 'dart') {
+      if (options.sourceFiles.contains(source.fullName)) {
+        return true;
+      } else if (source.uri.scheme == 'dart') {
         return options.showSdkWarnings;
       } else if (source.uri.scheme == 'package') {
         if (packagesRequiringFullParse == null) {
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 4b37788..e6b4f4c 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -1795,6 +1795,18 @@
       uri = currentElement.compilationUnit.script.resourceUri;
       assert(invariant(currentElement, () {
 
+        bool sameToken(Token token, Token sought) {
+          if (token == sought) return true;
+          if (token.stringValue == '>>' ||
+              token.stringValue == '>>>') {
+            // `>>` and `>>>` are converted to `>` in the parser when needed.
+            return sought.stringValue == '>' &&
+                token.charOffset <= sought.charOffset &&
+                sought.charOffset < token.charEnd;
+          }
+          return false;
+        }
+
         /// Check that [begin] and [end] can be found between [from] and [to].
         validateToken(Token from, Token to) {
           if (from == null || to == null) return true;
@@ -1802,10 +1814,10 @@
           bool foundEnd = false;
           Token token = from;
           while (true) {
-            if (token == begin) {
+            if (sameToken(token, begin)) {
               foundBegin = true;
             }
-            if (token == end) {
+            if (sameToken(token, end)) {
               foundEnd = true;
             }
             if (foundBegin && foundEnd) {
@@ -1859,7 +1871,7 @@
   }
 
   SourceSpan spanFromNode(Node node) {
-    return spanFromTokens(node.getBeginToken(), node.getEndToken());
+    return spanFromTokens(node.getBeginToken(), node.getPrefixEndToken());
   }
 
   SourceSpan spanFromElement(Element element) {
diff --git a/pkg/compiler/lib/src/cps_ir/builtin_operator.dart b/pkg/compiler/lib/src/cps_ir/builtin_operator.dart
index 2db4ac5..7992821 100644
--- a/pkg/compiler/lib/src/cps_ir/builtin_operator.dart
+++ b/pkg/compiler/lib/src/cps_ir/builtin_operator.dart
@@ -18,7 +18,7 @@
 /// In all cases, the word "null" refers to the Dart null object, corresponding
 /// to both JS null and JS undefined.
 ///
-/// Some operators, notably [IsFloor] and [IsNumberAndFloor], take "repeated"
+/// Some operators, notably [IsFloor] and [IsInteger], take "repeated"
 /// arguments to reflect the number of times the given value is referenced
 /// by the generated code. The tree IR needs to know the number of references
 /// to safely propagate assignments.
@@ -133,7 +133,28 @@
   /// The argument must be repeated 3 times.
   ///
   /// Compiles to `typeof x === 'number' && Math.floor(x) === x`
-  IsNumberAndFloor,
+  IsInteger,
+
+  /// Returns true if the argument is not an integer.
+  ///
+  /// The argument must be repeated 3 times.
+  ///
+  /// Compiles to `typeof x !== 'number' || Math.floor(x) !== x`
+  IsNotInteger,
+
+  /// Returns true if `x` is an unsigned 32-bit integer.
+  ///
+  /// The argument must be repeated 2 times.
+  ///
+  /// Compiles to `x >>> 0 === x`
+  IsUnsigned32BitInteger,
+
+  /// Returns false if `x` is an unsigned 32-bit integer.
+  ///
+  /// The argument must be repeated 2 times.
+  ///
+  /// Compiles to `x >>> 0 !== x`
+  IsNotUnsigned32BitInteger,
 
   /// Returns true if the argument is a fixed length Array.
   ///
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 470a96d..8ec5743 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
@@ -20,8 +20,11 @@
 import '../io/source_information.dart';
 import '../js/js.dart' as js show
     js,
+    objectLiteral,
+    Expression,
     LiteralStatement,
     Template,
+    InterpolatedExpression,
     isIdentityTemplate;
 import '../native/native.dart' show
     NativeBehavior;
@@ -691,6 +694,9 @@
     assert(!element.isLocal);
     assert(!element.isInstanceMember);
     assert(isOpen);
+    if (program.isJsInterop(element)) {
+      return buildInvokeJsInteropMember(element, arguments);
+    }
     return addPrimitive(
         new ir.InvokeStatic(element, selector, arguments, sourceInformation));
   }
@@ -1401,8 +1407,8 @@
       Selector selector = new Selector.setter(
           new Name(variableElement.name, variableElement.library));
       List<ir.Primitive> value = <ir.Primitive>[currentValue];
-      // Note the order of the comparisons below.  It can be the case that an
-      // element isError and isMalformed.
+      // Note the comparison below.  It can be the case that an element isError
+      // and isMalformed.
       if (Elements.isError(variableElement)) {
         bodyBuilder.buildStaticNoSuchMethod(selector, value);
       } else {
@@ -2066,6 +2072,86 @@
     buildReturn(value: value, sourceInformation: source);
   }
 
+  static _isNotNull(ir.Primitive value) =>
+      !(value is ir.Constant && value.value.isNull);
+
+  /// Builds a call to a resolved js-interop element.
+  ir.Primitive buildInvokeJsInteropMember(FunctionElement element,
+      List<ir.Primitive> arguments) {
+    program.addNativeMethod(element);
+    String target = program.getJsInteropTargetPath(element);
+    // Strip off trailing arguments that were not specified.
+    // TODO(jacobr,sigmund): assert that the trailing arguments are all null.
+    // TODO(jacobr): rewrite named arguments to an object literal matching
+    // the factory constructor case.
+    var inputs = arguments.where(_isNotNull).toList();
+
+    var behavior = new NativeBehavior()..sideEffects.setAllSideEffects();
+    DartType type = element.isConstructor ?
+        element.enclosingClass.thisType : element.type.returnType;
+    // Native behavior effects here are similar to native/behavior.dart.
+    // The return type is dynamic if we don't trust js-interop type
+    // declarations.
+    behavior.typesReturned.add(
+        program.trustJSInteropTypeAnnotations ? type : const DynamicType());
+
+    // The allocation effects include the declared type if it is native (which
+    // includes js interop types).
+    if (type.element != null && program.isNative(type.element)) {
+      behavior.typesInstantiated.add(type);
+    }
+
+    // It also includes any other JS interop type if we don't trust the
+    // annotation or if is declared too broad.
+    if (!program.trustJSInteropTypeAnnotations || type.isObject ||
+        type.isDynamic) {
+      behavior.typesInstantiated.add(program.jsJavascriptObjectType);
+    }
+
+    String code;
+    if (element.isGetter) {
+      code = target;
+    } else if (element.isSetter) {
+      code = "$target = #";
+    } else {
+      var args = new List.filled(inputs.length, '#').join(',');
+      code = element.isConstructor ? "new $target($args)" : "$target($args)";
+    }
+    return buildForeignCode(js.js.parseForeignJS(code), inputs, behavior);
+    // TODO(sigmund): should we record the source-information here?
+  }
+
+  /// Builds an object literal that results from invoking a factory constructor
+  /// of a js-interop anonymous type.
+  ir.Primitive buildJsInteropObjectLiteral(ConstructorElement constructor,
+      List<ir.Primitive> arguments, {SourceInformation source}) {
+    assert(program.isJsInteropAnonymous(constructor));
+    program.addNativeMethod(constructor);
+    FunctionSignature params = constructor.functionSignature;
+    int i = 0;
+    var filteredArguments = <ir.Primitive>[];
+    var entries = new Map<String, js.Expression>();
+    params.orderedForEachParameter((ParameterElement parameter) {
+      // TODO(jacobr): throw if parameter names do not match names of property
+      // names in the class.
+      assert (parameter.isNamed);
+      ir.Primitive argument = arguments[i++];
+      if (_isNotNull(argument)) {
+        filteredArguments.add(argument);
+        entries[parameter.name] =
+            new js.InterpolatedExpression(filteredArguments.length - 1);
+      }
+    });
+    var code = new js.Template(null, js.objectLiteral(entries));
+    var behavior = new NativeBehavior();
+    if (program.trustJSInteropTypeAnnotations) {
+      behavior.typesReturned.add(constructor.enclosingClass.thisType);
+    }
+
+    // TODO(sigmund): should we record the source-information here?
+    return buildForeignCode(code, filteredArguments, behavior);
+  }
+
   /// Create a blocks of [statements] by applying [build] to all reachable
   /// statements. The first statement is assumed to be reachable.
   // TODO(johnniwinther): Type [statements] as `Iterable` when `NodeList` uses
@@ -2551,6 +2637,13 @@
     Selector selector =
         new Selector(SelectorKind.CALL, element.memberName, callStructure);
     ClassElement cls = element.enclosingClass;
+    if (program.isJsInterop(element)) {
+      if (program.isJsInteropAnonymous(element)) {
+        return buildJsInteropObjectLiteral(element, arguments,
+            source: sourceInformation);
+      }
+      return buildInvokeJsInteropMember(element, arguments);
+    }
     if (program.requiresRuntimeTypesFor(cls)) {
       InterfaceType interface = type;
       Iterable<ir.Primitive> typeArguments =
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 3ae2c1b..629bfac 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
@@ -796,7 +796,10 @@
 
   /// Creates a primitive for the default value of [parameter].
   ir.Primitive translateDefaultValue(ParameterElement parameter) {
-    if (parameter.initializer == null) {
+    if (parameter.initializer == null ||
+        // TODO(sigmund): JS doesn't support default values, so this should be
+        // reported as an error earlier (Issue #25759).
+        backend.isJsInterop(parameter.functionDeclaration)) {
       return irBuilder.buildNullConstant();
     } else {
       return inlineConstant(parameter.executableContext, parameter.initializer);
@@ -1111,8 +1114,105 @@
   }
 
   visitAsyncForIn(ast.AsyncForIn node) {
-    // await for is not yet implemented.
-    return giveup(node, 'await for');
+    // Translate await for into a loop over a StreamIterator.  The source
+    // statement:
+    //
+    // await for (<decl> in <stream>) <body>
+    //
+    // is translated as if it were:
+    //
+    // var iterator = new StreamIterator(<stream>);
+    // try {
+    //   while (await iterator.hasNext()) {
+    //     <decl> = await iterator.current;
+    //     <body>
+    //   }
+    // } finally {
+    //   await iterator.cancel();
+    // }
+    ir.Primitive stream = visit(node.expression);
+    ir.Primitive dummyTypeArgument = irBuilder.buildNullConstant();
+    ConstructorElement constructor = helpers.streamIteratorConstructor;
+    ir.Primitive iterator = irBuilder.addPrimitive(new ir.InvokeConstructor(
+        constructor.enclosingClass.thisType,
+        constructor,
+        new Selector.callConstructor(constructor.memberName, 1),
+        <ir.Primitive>[stream, dummyTypeArgument],
+        sourceInformationBuilder.buildGeneric(node)));
+
+    ir.Node buildTryBody(IrBuilder builder) {
+      ir.Node buildLoopCondition(IrBuilder builder) {
+        ir.Primitive moveNext = builder.buildDynamicInvocation(
+            iterator,
+            Selectors.moveNext,
+            elements.getMoveNextTypeMask(node),
+            <ir.Primitive>[]);
+        return builder.addPrimitive(new ir.Await(moveNext));
+      }
+
+      ir.Node buildLoopBody(IrBuilder builder) {
+        return withBuilder(builder, () {
+          ir.Primitive current = irBuilder.buildDynamicInvocation(
+              iterator,
+              Selectors.current,
+              elements.getCurrentTypeMask(node),
+              <ir.Primitive>[]);
+          Element variable = elements.getForInVariable(node);
+          if (Elements.isLocal(variable)) {
+            if (node.declaredIdentifier.asVariableDefinitions() != null) {
+              irBuilder.declareLocalVariable(variable);
+            }
+            irBuilder.buildLocalVariableSet(variable, current);
+          } else if (Elements.isError(variable) ||
+                     Elements.isMalformed(variable)) {
+            Selector selector =
+                new Selector.setter(new Name(variable.name, variable.library));
+            List<ir.Primitive> args = <ir.Primitive>[current];
+            // Note the comparison below.  It can be the case that an element
+            // isError and isMalformed.
+            if (Elements.isError(variable)) {
+              irBuilder.buildStaticNoSuchMethod(selector, args);
+            } else {
+              irBuilder.buildErroneousInvocation(variable, selector, args);
+            }
+          } else if (Elements.isStaticOrTopLevel(variable)) {
+            if (variable.isField) {
+              irBuilder.addPrimitive(new ir.SetStatic(variable, current));
+            } else {
+              irBuilder.buildStaticSetterSet(variable, current);
+            }
+          } else {
+            ir.Primitive receiver = irBuilder.buildThis();
+            ast.Node identifier = node.declaredIdentifier;
+            irBuilder.buildDynamicSet(
+                receiver,
+                elements.getSelector(identifier),
+                elements.getTypeMask(identifier),
+                current);
+          }
+          visit(node.body);
+        });
+      }
+
+      builder.buildWhile(
+          buildCondition: buildLoopCondition,
+          buildBody: buildLoopBody,
+          target: elements.getTargetDefinition(node),
+          closureScope: getClosureScopeForNode(node));
+    }
+
+    ir.Node buildFinallyBody(IrBuilder builder) {
+      ir.Primitive cancellation = builder.buildDynamicInvocation(
+          iterator,
+          Selectors.cancel,
+          backend.dynamicType,
+          <ir.Primitive>[],
+          sourceInformation: sourceInformationBuilder.buildGeneric(node));
+      return builder.addPrimitive(new ir.Await(cancellation));
+    }
+
+    irBuilder.buildTryFinally(new TryStatementInfo(), buildTryBody,
+        buildFinallyBody);
   }
 
   visitAwait(ast.Await node) {
@@ -3921,4 +4021,22 @@
   void addNativeMethod(FunctionElement function) {
     _backend.emitter.nativeEmitter.nativeMethods.add(function);
   }
+
+  bool get trustJSInteropTypeAnnotations =>
+      _compiler.trustJSInteropTypeAnnotations;
+
+  bool isNative(ClassElement element) => _backend.isNative(element);
+
+  bool isJsInterop(FunctionElement element) => _backend.isJsInterop(element);
+
+  bool isJsInteropAnonymous(FunctionElement element) =>
+    _backend.jsInteropAnalysis.hasAnonymousAnnotation(element.contextClass);
+
+  String getJsInteropTargetPath(FunctionElement element) {
+    return '${_backend.namer.fixedBackendPath(element)}.'
+      '${_backend.getFixedBackendName(element)}';
+  }
+
+  DartType get jsJavascriptObjectType =>
+    _backend.helpers.jsJavaScriptObjectClass.thisType;
 }
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 7cb9260..1562262 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
@@ -781,14 +781,21 @@
 
 /// Checks that [index] is a valid index on a given indexable [object].
 ///
-/// Compiles to the following, with a subset of the conditions in the `if`:
+/// In the simplest form, compiles to the following:
 ///
-///     if (index < 0 || index >= object.length || object.length === 0)
+///     if (index < 0 || index >= object.length)
 ///         ThrowIndexOutOfRangeException(object, index);
 ///
-/// [index] must be an integer, and [object] must refer to null or an indexable
-/// object, and [length] must be the length of [object] at the time of the
-/// check.
+/// In the general form, any of the following conditions can be checked:
+///
+///  Lower bound: `index >= 0`
+///  Upper bound: `index < object.length`
+///  Emptiness:   `object.length !== 0`
+///  Integerness: `index >>> 0 === index`
+///
+/// [index] must be an integer unless integerness is checked, and [object] must
+/// refer to null or an indexable object, and [length] must be the length of
+/// [object] at the time of the check.
 ///
 /// Returns [object] so the bounds check can be used to restrict code motion.
 /// It is possible to have a bounds check node that performs no checks but
@@ -825,6 +832,9 @@
   /// because that corresponds to `object.length - 1` in the error case.
   bool get hasEmptinessCheck => checks & EMPTINESS != 0;
 
+  /// If true, check that `index` is an integer.
+  bool get hasIntegerCheck => checks & INTEGER != 0;
+
   /// True if the [length] is needed to perform the check.
   bool get lengthUsedInCheck => checks & (UPPER_BOUND | EMPTINESS) != 0;
 
@@ -833,6 +843,7 @@
   static const int UPPER_BOUND = 1 << 0;
   static const int LOWER_BOUND = 1 << 1;
   static const int EMPTINESS = 1 << 2; // See [hasEmptinessCheck].
+  static const int INTEGER = 1 << 3; // Check if index is an int.
   static const int BOTH_BOUNDS = UPPER_BOUND | LOWER_BOUND;
   static const int NONE = 0;
 
@@ -859,17 +870,13 @@
   }
 
   String get checkString {
-    if (hasUpperBoundCheck && hasLowerBoundCheck) {
-      return 'upper-lower-checks';
-    } else if (hasUpperBoundCheck) {
-      return 'upper-check';
-    } else if (hasLowerBoundCheck) {
-      return 'lower-check';
-    } else if (hasEmptinessCheck) {
-      return 'emptiness-check';
-    } else {
-      return 'no-check';
-    }
+    if (hasNoChecks) return 'no-check';
+    return [hasUpperBoundCheck ? 'upper' : null,
+        hasLowerBoundCheck ? 'lower' : null,
+        hasEmptinessCheck ? 'emptiness' : null,
+        hasIntegerCheck ? 'integer' : null,
+        'check']
+        .where((x) => x != null).join('-');
   }
 
   bool get isSafeForElimination => checks == NONE;
diff --git a/pkg/compiler/lib/src/cps_ir/finalize.dart b/pkg/compiler/lib/src/cps_ir/finalize.dart
index 7e3b6e1..dad9e51 100644
--- a/pkg/compiler/lib/src/cps_ir/finalize.dart
+++ b/pkg/compiler/lib/src/cps_ir/finalize.dart
@@ -42,9 +42,14 @@
       return cps;
     }
     Continuation fail = cps.letCont();
-    if (node.hasLowerBoundCheck) {
+    Primitive index = node.index.definition;
+    if (node.hasIntegerCheck) {
+      cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.IsNotUnsigned32BitInteger,
+          [index, index]))
+          .invokeContinuation(fail);
+    } else if (node.hasLowerBoundCheck) {
       cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.NumLt,
-          [node.index.definition, cps.makeZero()]))
+          [index, cps.makeZero()]))
           .invokeContinuation(fail);
     }
     if (node.hasUpperBoundCheck) {
@@ -59,7 +64,7 @@
         cps.letPrim(length);
       }
       cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.NumGe,
-          [node.index.definition, length]))
+          [index, length]))
           .invokeContinuation(fail);
     }
     if (node.hasEmptinessCheck) {
@@ -69,7 +74,7 @@
     }
     cps.insideContinuation(fail).invokeStaticThrower(
           helpers.throwIndexOutOfRangeException,
-          [node.object.definition, node.index.definition]);
+          [node.object.definition, index]);
     node..replaceUsesWith(node.object.definition)..destroy();
     return cps;
   }
diff --git a/pkg/compiler/lib/src/cps_ir/inline.dart b/pkg/compiler/lib/src/cps_ir/inline.dart
index 87892d3..28ea3d5 100644
--- a/pkg/compiler/lib/src/cps_ir/inline.dart
+++ b/pkg/compiler/lib/src/cps_ir/inline.dart
@@ -374,6 +374,7 @@
     Primitive result = cps.invokeMethod(thisParameter, newSelector, node.mask,
         arguments, node.callingConvention);
     result.type = typeSystem.getInvokeReturnType(node.selector, node.mask);
+    returnContinuation.parameters.single.type = result.type;
     cps.invokeContinuation(returnContinuation, <Primitive>[result]);
     return new FunctionDefinition(target, thisParameter, parameters,
         returnContinuation,
@@ -394,6 +395,7 @@
     // AST node, targets that are asynchronous or generator functions, or
     // targets containing a try statement.
     if (!target.hasNode) return null;
+    if (backend.isJsInterop(target)) return null;
     if (target.asyncMarker != AsyncMarker.SYNC) return null;
     // V8 does not optimize functions containing a try statement.  Inlining
     // code containing a try statement will make the optimizable calling code
@@ -596,6 +598,7 @@
       // These should be handled by operator specialization.
       return true;
     }
+    if (target == backend.helpers.stringInterpolationHelper) return true;
     return false;
   }
 }
diff --git a/pkg/compiler/lib/src/cps_ir/type_mask_system.dart b/pkg/compiler/lib/src/cps_ir/type_mask_system.dart
index ea8bb43..2042320 100644
--- a/pkg/compiler/lib/src/cps_ir/type_mask_system.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_mask_system.dart
@@ -450,6 +450,13 @@
     return interceptedTypes.containsMask(t.nonNullable(), classWorld);
   }
 
+  @override
+  bool isDefinitelySelfInterceptor(TypeMask t, {bool allowNull: false}) {
+    assert(allowNull != null);
+    if (!allowNull && t.isNullable) return false;
+    return areDisjoint(t, interceptorType);
+  }
+
   /// Given a class from the interceptor hierarchy, returns a [TypeMask]
   /// matching all values with that interceptor (or a subtype thereof).
   @override
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index fe35b1f..a9a99fa 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -1420,16 +1420,24 @@
   /// Returns a CPS fragment whose context is the branch where no error
   /// was thrown.
   Primitive makeBoundsCheck(CpsFragment cps,
-                            Primitive list,
-                            Primitive index,
-                            [int checkKind = BoundsCheck.BOTH_BOUNDS]) {
+        Primitive list,
+        Primitive index,
+        [int checkKind = BoundsCheck.BOTH_BOUNDS | BoundsCheck.INTEGER]) {
     if (compiler.trustPrimitives) {
       return cps.letPrim(new BoundsCheck.noCheck(list, cps.sourceInformation));
     } else {
       GetLength length = cps.letPrim(new GetLength(list));
       list = cps.refine(list, typeSystem.nonNullType);
-      return cps.letPrim(new BoundsCheck(list, index, length, checkKind,
-          cps.sourceInformation));
+      BoundsCheck check = cps.letPrim(new BoundsCheck(list, index, length,
+          checkKind, cps.sourceInformation));
+      if (check.hasIntegerCheck) {
+        if (typeSystem.isDefinitelyInt(index.type)) {
+          check.checks &= ~BoundsCheck.INTEGER;
+        } else {
+          cps.refine(index, typeSystem.uint32Type);
+        }
+      }
+      return check;
     }
   }
 
@@ -1468,8 +1476,6 @@
 
       case '[]':
         Primitive index = node.dartArgument(0);
-        // TODO(asgerf): Consider inserting a guard and specialize anyway.
-        if (!lattice.isDefinitelyInt(getValue(index))) return null;
         CpsFragment cps = new CpsFragment(node.sourceInformation);
         receiver = makeBoundsCheck(cps, receiver, index);
         GetIndex get = cps.letPrim(new GetIndex(receiver, index));
@@ -1485,7 +1491,6 @@
         }
         Primitive index = node.dartArgument(0);
         Primitive value = node.dartArgument(1);
-        if (!lattice.isDefinitelyInt(getValue(index))) return null;
         CpsFragment cps = new CpsFragment(node.sourceInformation);
         receiver = makeBoundsCheck(cps, receiver, index);
         cps.letPrim(new SetIndex(receiver, index, value));
@@ -2043,10 +2048,24 @@
   /// Specialize calls to internal static methods.
   specializeInternalMethodCall(InvokeStatic node) {
     if (node.target == backend.helpers.stringInterpolationHelper) {
-      AbstractConstantValue value = getValue(node.arguments[0].definition);
+      Primitive argument = node.arguments[0].definition;
+      AbstractConstantValue value = getValue(argument);
       if (lattice.isDefinitelyString(value)) {
-        node.replaceUsesWith(node.arguments[0].definition);
+        node.replaceUsesWith(argument);
         return new CpsFragment();
+      } else if (typeSystem.isDefinitelySelfInterceptor(value.type)) {
+        TypeMask toStringReturn = typeSystem.getInvokeReturnType(
+            Selectors.toString_, value.type);
+        if (typeSystem.isDefinitelyString(toStringReturn)) {
+          CpsFragment cps = new CpsFragment(node.sourceInformation);
+          Primitive invoke = cps.invokeMethod(argument,
+              Selectors.toString_,
+              value.type,
+              [cps.makeZero()],
+              CallingConvention.DummyIntercepted);
+          node.replaceUsesWith(invoke);
+          return cps;
+        }
       }
     } else if (node.target == compiler.identicalFunction) {
       if (node.arguments.length == 2) {
@@ -2245,7 +2264,7 @@
         return unaryBuiltinOperator(BuiltinOperator.IsNumber);
       }
       return new ApplyBuiltinOperator(
-          BuiltinOperator.IsNumberAndFloor,
+          BuiltinOperator.IsInteger,
           <Primitive>[prim, prim, prim],
           node.sourceInformation);
     }
@@ -2321,7 +2340,8 @@
     // The [BoundsChecker] pass does not try to eliminate checks that could be
     // eliminated by constant folding.
     if (node.hasNoChecks) return;
-    int index = lattice.intValue(getValue(node.index.definition));
+    Primitive indexPrim = node.index.definition;
+    int index = lattice.intValue(getValue(indexPrim));
     int length = node.length == null
         ? null
         : lattice.intValue(getValue(node.length.definition));
@@ -2334,6 +2354,9 @@
     if (length != null && length > 0) {
       node.checks &= ~BoundsCheck.EMPTINESS;
     }
+    if (typeSystem.isDefinitelyInt(indexPrim.type)) {
+      node.checks &= ~BoundsCheck.INTEGER;
+    }
     if (!node.lengthUsedInCheck && node.length != null) {
       node..length.unlink()..length = null;
     }
@@ -2888,8 +2911,11 @@
       case BuiltinOperator.IsFalsy:
       case BuiltinOperator.IsNumber:
       case BuiltinOperator.IsNotNumber:
+      case BuiltinOperator.IsNotInteger:
       case BuiltinOperator.IsFloor:
-      case BuiltinOperator.IsNumberAndFloor:
+      case BuiltinOperator.IsInteger:
+      case BuiltinOperator.IsUnsigned32BitInteger:
+      case BuiltinOperator.IsNotUnsigned32BitInteger:
         setValue(node, nonConstant(typeSystem.boolType));
         break;
 
diff --git a/pkg/compiler/lib/src/cps_ir/update_refinements.dart b/pkg/compiler/lib/src/cps_ir/update_refinements.dart
index 3500521..5ce47a2 100644
--- a/pkg/compiler/lib/src/cps_ir/update_refinements.dart
+++ b/pkg/compiler/lib/src/cps_ir/update_refinements.dart
@@ -73,6 +73,14 @@
     });
   }
 
+  visitBoundsCheck(BoundsCheck node) {
+    super.visitBoundsCheck(node);
+    if (node.hasIntegerCheck &&
+        typeSystem.isDefinitelyInt(node.index.definition.type)) {
+      node.checks &= ~BoundsCheck.INTEGER;
+    }
+  }
+
   processReference(Reference ref) {
     refine(ref);
   }
diff --git a/pkg/compiler/lib/src/diagnostics/source_span.dart b/pkg/compiler/lib/src/diagnostics/source_span.dart
index 95c3c75..25bdc6c 100644
--- a/pkg/compiler/lib/src/diagnostics/source_span.dart
+++ b/pkg/compiler/lib/src/diagnostics/source_span.dart
@@ -20,7 +20,7 @@
 
   factory SourceSpan.fromNode(Uri uri, Node node) {
     return new SourceSpan.fromTokens(
-        uri, node.getBeginToken(), node.getEndToken());
+        uri, node.getBeginToken(), node.getPrefixEndToken());
   }
 
   factory SourceSpan.fromTokens(Uri uri, Token begin, Token end) {
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index 3f0d70c..121a882 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -2115,14 +2115,7 @@
     if (span != null && hasNode) {
       FunctionExpression functionExpression = node.asFunctionExpression();
       if (functionExpression != null) {
-        Token begin = functionExpression.getBeginToken();
-        Token end;
-        if (functionExpression.parameters != null) {
-          end = functionExpression.parameters.getEndToken();
-        } else {
-          end = functionExpression.name.getEndToken();
-        }
-        span = new SourceSpan.fromTokens(span.uri, begin, end);
+        span = new SourceSpan.fromNode(span.uri, functionExpression);
       }
     }
     return span;
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index faa4de3..14d1f6e 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -2577,6 +2577,7 @@
   @override
   bool enableCodegenWithErrorsIfSupported(Spannable node) {
     if (compiler.useCpsIr) {
+      // TODO(25747): Support code generation with compile-time errors.
       reporter.reportHintMessage(
           node,
           MessageKind.GENERIC,
diff --git a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
index eb1e699..1d2549d 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
@@ -1123,8 +1123,14 @@
         return js.js('typeof # !== "number"', args);
       case BuiltinOperator.IsFloor:
         return js.js('Math.floor(#) === #', args);
-      case BuiltinOperator.IsNumberAndFloor:
+      case BuiltinOperator.IsInteger:
         return js.js('typeof # === "number" && Math.floor(#) === #', args);
+      case BuiltinOperator.IsNotInteger:
+        return js.js('typeof # !== "number" || Math.floor(#) !== #', args);
+      case BuiltinOperator.IsUnsigned32BitInteger:
+        return js.js('# >>> 0 === #', args);
+      case BuiltinOperator.IsNotUnsigned32BitInteger:
+        return js.js('# >>> 0 !== #', args);
       case BuiltinOperator.IsFixedLengthJSArray:
         // TODO(sra): Remove boolify (i.e. !!).
         return js.js(r'!!#.fixed$length', args);
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index d06a002..85fd583 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -7535,7 +7535,10 @@
     TypeMask mask = elements.getIteratorTypeMask(node);
 
     ClassWorld classWorld = compiler.world;
-    if (mask != null && mask.satisfies(helpers.jsIndexableClass, classWorld)) {
+    if (mask != null &&
+        mask.satisfies(helpers.jsIndexableClass, classWorld) &&
+        // String is indexable but not iterable.
+        !mask.satisfies(helpers.jsStringClass, classWorld)) {
       return buildSyncForInIndexable(node, mask);
     }
     buildSyncForInIterator(node);
diff --git a/pkg/compiler/lib/src/tree/nodes.dart b/pkg/compiler/lib/src/tree/nodes.dart
index 04d46f5..e95497b 100644
--- a/pkg/compiler/lib/src/tree/nodes.dart
+++ b/pkg/compiler/lib/src/tree/nodes.dart
@@ -147,6 +147,12 @@
 
   Token getBeginToken();
 
+  /// Returns the token that ends the 'prefix' of this node.
+  ///
+  /// For instance the end of the parameters in a [FunctionExpression] or the
+  /// last token before the start of a class body for a [ClassNode].
+  Token getPrefixEndToken() => getEndToken();
+
   Token getEndToken();
 
   Assert asAssert() => null;
@@ -263,6 +269,25 @@
 
   Token getBeginToken() => beginToken;
 
+  @override
+  Token getPrefixEndToken() {
+    Token token;
+    if (interfaces != null) {
+      token = interfaces.getEndToken();
+    }
+    if (token == null && superclass != null) {
+      token = superclass.getEndToken();
+    }
+    if (token == null && typeParameters != null) {
+      token == typeParameters.getEndToken();
+    }
+    if (token == null) {
+      token = name.getEndToken();
+    }
+    assert(invariant(beginToken, token != null));
+    return token;
+  }
+
   Token getEndToken() => endToken;
 }
 
@@ -738,6 +763,10 @@
   visitChildren(Visitor visitor) => function.accept(visitor);
 
   Token getBeginToken() => function.getBeginToken();
+
+  @override
+  Token getPrefixEndToken() => function.getPrefixEndToken();
+
   Token getEndToken() => function.getEndToken();
 }
 
@@ -826,6 +855,11 @@
     return firstBeginToken(name, parameters);
   }
 
+  @override
+  Token getPrefixEndToken() {
+    return parameters != null ? parameters.getEndToken() : name.getEndToken();
+  }
+
   Token getEndToken() {
     Token token = (body == null) ? null : body.getEndToken();
     token = (token == null) ? parameters.getEndToken() : token;
@@ -1300,7 +1334,10 @@
 
   Token getBeginToken() => typeName.getBeginToken();
 
-  Token getEndToken() => typeName.getEndToken();
+  Token getEndToken() {
+    if (typeArguments != null) return typeArguments.getEndToken();
+    return typeName.getEndToken();
+  }
 }
 
 class TypeVariable extends Node {
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart
index b4f6dd8..dd44f1d 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart
@@ -353,7 +353,8 @@
       case BuiltinOperator.IsNumber:
       case BuiltinOperator.IsNotNumber:
       case BuiltinOperator.IsFloor:
-      case BuiltinOperator.IsNumberAndFloor:
+      case BuiltinOperator.IsInteger:
+      case BuiltinOperator.IsNotInteger:
       case BuiltinOperator.Identical:
         return true;
       default:
@@ -373,6 +374,12 @@
       case BuiltinOperator.LooseNeq: return BuiltinOperator.LooseEq;
       case BuiltinOperator.IsNumber: return BuiltinOperator.IsNotNumber;
       case BuiltinOperator.IsNotNumber: return BuiltinOperator.IsNumber;
+      case BuiltinOperator.IsInteger: return BuiltinOperator.IsNotInteger;
+      case BuiltinOperator.IsNotInteger: return BuiltinOperator.IsInteger;
+      case BuiltinOperator.IsUnsigned32BitInteger:
+        return BuiltinOperator.IsNotUnsigned32BitInteger;
+      case BuiltinOperator.IsNotUnsigned32BitInteger:
+        return BuiltinOperator.IsUnsigned32BitInteger;
 
       // Because of NaN, these do not have a negated form.
       case BuiltinOperator.NumLt:
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart b/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
index 3785f78..8840c8e 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
@@ -265,6 +265,12 @@
     return node;
   }
 
+  Expression visitAwait(Await node) {
+    super.visitAwait(node);
+    ++impureCounter;
+    return node;
+  }
+
   Expression visitConditional(Conditional node) {
     node.condition = visitExpression(node.condition);
     // Visit the branches to detect impure subexpressions, but do not pull
diff --git a/pkg/compiler/lib/src/types/abstract_value_domain.dart b/pkg/compiler/lib/src/types/abstract_value_domain.dart
index 3bf01da..73e8ae4 100644
--- a/pkg/compiler/lib/src/types/abstract_value_domain.dart
+++ b/pkg/compiler/lib/src/types/abstract_value_domain.dart
@@ -136,6 +136,8 @@
 
   bool isDefinitelyIntercepted(AbstractValue t, {bool allowNull});
 
+  bool isDefinitelySelfInterceptor(AbstractValue t, {bool allowNull: false});
+
   /// Given a class from the interceptor hierarchy, returns an [AbstractValue]
   /// matching all values with that interceptor (or a subtype thereof).
   AbstractValue getInterceptorSubtypes(ClassElement class_);
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 94de113..6932f93 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -50,6 +50,10 @@
     defines += ["NDEBUG"]
   }
 
+  if (is_ios || is_mac) {
+    defines += ["DART_PRECOMPILER"]
+  }
+
   cflags = [
     "-Werror",
     "-Wall",
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index adf0aa4..197eb32 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -76,17 +76,18 @@
 }
 
 
-iolib_sources_gypi =
+sdk_io_sources_gypi =
     exec_script("../../tools/gypi_to_gn.py",
-                [rebase_path("../../sdk/lib/io/iolib_sources.gypi")],
+                [rebase_path("../../sdk/lib/io/io_sources.gypi")],
                 "scope",
-                ["../../sdk/lib/io/iolib_sources.gypi"])
-iolib_sources = rebase_path(iolib_sources_gypi.sources, ".", "../../sdk/lib/io")
+                ["../../sdk/lib/io/io_sources.gypi"])
+sdk_io_sources =
+    rebase_path(sdk_io_sources_gypi.sources, ".", "../../sdk/lib/io")
 
 gen_library_src_path("generate_io_cc_file") {
   name = "io"
   kind = "source"
-  sources = ["../../sdk/lib/io/io.dart"] + iolib_sources
+  sources = ["../../sdk/lib/io/io.dart"] + sdk_io_sources
   output = "$target_gen_dir/io_gen.cc"
 }
 
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index f271fbd..cb4b63e 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -62,7 +62,7 @@
         '../../sdk/lib/io/io.dart',
       ],
       'includes': [
-        '../../sdk/lib/io/iolib_sources.gypi',
+        '../../sdk/lib/io/io_sources.gypi',
       ],
       'actions': [
         {
@@ -545,6 +545,9 @@
     {
       'target_name': 'generate_bootstrap_resources_cc_file',
       'type': 'none',
+      'dependencies': [
+        'bin/zlib.gyp:zlib_dart',
+      ],
       'toolsets':['host'],
       'includes': [
         'vmservice/vmservice_sources.gypi',
@@ -575,6 +578,40 @@
       ]
     },
     {
+      # dart_product binary.
+      'target_name': 'dart_product',
+      'type': 'executable',
+      'dependencies': [
+        'libdart',
+        'libdart_builtin',
+        'libdart_io',
+      ],
+      'include_dirs': [
+        '..',
+        '../../third_party/', # Zlib
+      ],
+      'defines': [
+        'DART_PRODUCT_BINARY',
+      ],
+      'sources': [
+        'main.cc',
+        'builtin_common.cc',
+        'builtin_natives.cc',
+        'builtin_nolib.cc',
+        'builtin.h',
+        'io_natives.h',
+        'snapshot_empty.cc',
+        'observatory_assets_empty.cc',
+      ],
+      'conditions': [
+        ['OS=="win"', {
+          'link_settings': {
+            'libraries': [ '-lws2_32.lib', '-lRpcrt4.lib', '-lwinmm.lib' ],
+          },
+        }],
+      ],
+    },
+    {
       # dart binary with a snapshot of corelibs built in.
       'target_name': 'dart',
       'type': 'executable',
diff --git a/runtime/bin/extensions_android.cc b/runtime/bin/extensions_android.cc
index 0c79bff..e33c195 100644
--- a/runtime/bin/extensions_android.cc
+++ b/runtime/bin/extensions_android.cc
@@ -13,7 +13,8 @@
 namespace bin {
 
 const char* kPrecompiledLibraryName = "libprecompiled.so";
-const char* kPrecompiledSymbolName = "_kInstructionsSnapshot";
+const char* kPrecompiledInstructionsSymbolName = "_kInstructionsSnapshot";
+const char* kPrecompiledDataSymbolName = "_kDataSnapshot";
 
 void* Extensions::LoadExtensionLibrary(const char* library_file) {
   return dlopen(library_file, RTLD_LAZY);
diff --git a/runtime/bin/extensions_linux.cc b/runtime/bin/extensions_linux.cc
index e172f0d..54a88a4 100644
--- a/runtime/bin/extensions_linux.cc
+++ b/runtime/bin/extensions_linux.cc
@@ -13,7 +13,8 @@
 namespace bin {
 
 const char* kPrecompiledLibraryName = "libprecompiled.so";
-const char* kPrecompiledSymbolName = "_kInstructionsSnapshot";
+const char* kPrecompiledInstructionsSymbolName = "_kInstructionsSnapshot";
+const char* kPrecompiledDataSymbolName = "_kDataSnapshot";
 
 void* Extensions::LoadExtensionLibrary(const char* library_file) {
   return dlopen(library_file, RTLD_LAZY);
diff --git a/runtime/bin/extensions_macos.cc b/runtime/bin/extensions_macos.cc
index e248a47..0edb6b5 100644
--- a/runtime/bin/extensions_macos.cc
+++ b/runtime/bin/extensions_macos.cc
@@ -13,7 +13,8 @@
 namespace bin {
 
 const char* kPrecompiledLibraryName = "libprecompiled.dylib";
-const char* kPrecompiledSymbolName = "kInstructionsSnapshot";
+const char* kPrecompiledInstructionsSymbolName = "kInstructionsSnapshot";
+const char* kPrecompiledDataSymbolName = "kDataSnapshot";
 
 void* Extensions::LoadExtensionLibrary(const char* library_file) {
   return dlopen(library_file, RTLD_LAZY);
diff --git a/runtime/bin/extensions_win.cc b/runtime/bin/extensions_win.cc
index d3b49f2..224bcdf 100644
--- a/runtime/bin/extensions_win.cc
+++ b/runtime/bin/extensions_win.cc
@@ -14,7 +14,8 @@
 namespace bin {
 
 const char* kPrecompiledLibraryName = "precompiled.dll";
-const char* kPrecompiledSymbolName = "_kInstructionsSnapshot";
+const char* kPrecompiledInstructionsSymbolName = "_kInstructionsSnapshot";
+const char* kPrecompiledDataSymbolName = "_kDataSnapshot";
 
 void* Extensions::LoadExtensionLibrary(const char* library_file) {
   SetLastError(0);
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index d783c85..f1f7e2c 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -435,7 +435,11 @@
   if (Dart_IsError(source)) {
     return source;
   }
-  return Dart_LoadLibrary(resolved_script_uri, source, 0, 0);
+  if (IsSnapshottingForPrecompilation()) {
+    return Dart_LoadScript(resolved_script_uri, source, 0, 0);
+  } else {
+    return Dart_LoadLibrary(resolved_script_uri, source, 0, 0);
+  }
 }
 
 
@@ -1028,6 +1032,7 @@
   char* error = Dart_Initialize(
       NULL,
       NULL,
+      NULL,
       CreateServiceIsolate,
       NULL,
       NULL,
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 6be11f0..e5e60dc 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -99,7 +99,8 @@
 
 
 extern const char* kPrecompiledLibraryName;
-extern const char* kPrecompiledSymbolName;
+extern const char* kPrecompiledInstructionsSymbolName;
+extern const char* kPrecompiledDataSymbolName;
 static const char* kPrecompiledVmIsolateName = "precompiled.vmisolate";
 static const char* kPrecompiledIsolateName = "precompiled.isolate";
 static const char* kPrecompiledInstructionsName = "precompiled.S";
@@ -407,12 +408,10 @@
 
 static bool ProcessRunFullSnapshotOption(
     const char* filename, CommandLineOptions* vm_options) {
-  // Ensure that we are not running 'dart_no_snapshot'.
-  if (isolate_snapshot_buffer == NULL) {
-    Log::PrintErr("Full Application snapshots cannot be run with"
-                  " dart_no_snapshot\n");
-    return false;
-  }
+#ifndef DART_PRODUCT_BINARY
+  Log::PrintErr("Full Application snapshots can only be be run with"
+                " dart_product\n");
+#endif
   return ProcessSnapshotOptionHelper(filename, &run_full_snapshot);
 }
 
@@ -742,8 +741,15 @@
                                                 char** error,
                                                 int* exit_code) {
   ASSERT(script_uri != NULL);
+#if defined(DART_PRODUCT_BINARY)
+  if (strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) {
+    // No service isolate support.
+    return NULL;
+  }
+#endif  // defined(DART_PRODUCT_BINARY)
+
   if (run_full_snapshot &&
-      !strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME)) {
+      (strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0)) {
     // We do not create a service isolate when running a full application
     // snapshot.
     return NULL;
@@ -777,6 +783,9 @@
   Dart_Handle result = Dart_SetLibraryTagHandler(DartUtils::LibraryTagHandler);
   CHECK_RESULT(result);
 
+#if defined(DART_PRODUCT_BINARY)
+  ASSERT(!Dart_IsServiceIsolate(isolate));
+#else
   if (Dart_IsServiceIsolate(isolate)) {
     // If this is the service isolate, load embedder specific bits and return.
     if (!VmService::Setup(vm_service_server_ip,
@@ -793,6 +802,7 @@
     Dart_ExitIsolate();
     return isolate;
   }
+#endif  // defined(DART_PRODUCT_BINARY)
 
   // Prepare builtin and other core libraries for use to resolve URIs.
   // Set up various closures, e.g: printing, timers etc.
@@ -1109,15 +1119,19 @@
 
   void* file = DartUtils::OpenFile(qualified_filename, false);
   if (file == NULL) {
-    ErrorExit(kErrorExitCode,
-              "Error: Unable to open file %s for reading snapshot\n",
-              qualified_filename);
+    fprintf(stderr,
+            "Error: Unable to open file %s for reading snapshot\n",
+            qualified_filename);
+    fflush(stderr);
+    Platform::Exit(kErrorExitCode);
   }
   intptr_t len = -1;
   DartUtils::ReadFile(buffer, &len, file);
   if (*buffer == NULL || len == -1) {
-    ErrorExit(kErrorExitCode,
-              "Error: Unable to read snapshot file %s\n", qualified_filename);
+    fprintf(stderr,
+            "Error: Unable to read snapshot file %s\n", qualified_filename);
+    fflush(stderr);
+    Platform::Exit(kErrorExitCode);
   }
   DartUtils::CloseFile(file);
   if (concat != NULL) {
@@ -1268,6 +1282,7 @@
         reinterpret_cast<IsolateData*>(Dart_IsolateData(isolate));
     result = Dart_LibraryImportLibrary(
         isolate_data->builtin_lib(), root_lib, Dart_Null());
+#ifndef DART_PRODUCT_BINARY
     if (is_noopt || gen_precompiled_snapshot) {
       // Load the embedder's portion of the VM service's Dart code so it will
       // be included in the precompiled snapshot.
@@ -1279,6 +1294,7 @@
         exit(kErrorExitCode);
       }
     }
+#endif  // !DART_PRODUCT_BINARY
 
     if (compile_all) {
       result = Dart_CompileAll();
@@ -1382,12 +1398,14 @@
 
       // Keep handling messages until the last active receive port is closed.
       result = Dart_RunLoop();
-      CHECK_RESULT(result);
-
       // Generate a full snapshot after execution if specified.
       if (generate_full_snapshot_after_run) {
-        GenerateFullSnapshot();
+        if (!Dart_IsCompilationError(result) &&
+            !Dart_IsVMRestartRequest(result)) {
+          GenerateFullSnapshot();
+        }
       }
+      CHECK_RESULT(result);
     }
   }
 
@@ -1536,7 +1554,9 @@
     Platform::Exit(kErrorExitCode);
   }
 
-  if (generate_script_snapshot || generate_full_snapshot_after_run) {
+  if (generate_script_snapshot ||
+      generate_full_snapshot_after_run ||
+      run_full_snapshot) {
     vm_options.AddArgument("--load_deferred_eagerly");
   }
 
@@ -1553,15 +1573,21 @@
   EventHandler::Start();
 
   const uint8_t* instructions_snapshot = NULL;
+  const uint8_t* data_snapshot = NULL;
   if (run_precompiled_snapshot) {
     instructions_snapshot = reinterpret_cast<const uint8_t*>(
-        LoadLibrarySymbol(kPrecompiledLibraryName, kPrecompiledSymbolName));
+        LoadLibrarySymbol(kPrecompiledLibraryName,
+                          kPrecompiledInstructionsSymbolName));
+    data_snapshot = reinterpret_cast<const uint8_t*>(
+        LoadLibrarySymbol(kPrecompiledLibraryName,
+                          kPrecompiledDataSymbolName));
     ReadSnapshotFile(precompiled_snapshot_directory,
                      kPrecompiledVmIsolateName,
                      &vm_isolate_snapshot_buffer);
     ReadSnapshotFile(precompiled_snapshot_directory,
                      kPrecompiledIsolateName,
                      &isolate_snapshot_buffer);
+
   } else if (run_full_snapshot) {
     char* vm_snapshot_fname;
     char* isolate_snapshot_fname;
@@ -1579,7 +1605,7 @@
 
   // Initialize the Dart VM.
   char* error = Dart_Initialize(
-      vm_isolate_snapshot_buffer, instructions_snapshot,
+      vm_isolate_snapshot_buffer, instructions_snapshot, data_snapshot,
       CreateIsolateAndSetup, NULL, NULL, ShutdownIsolate,
       DartUtils::OpenFile,
       DartUtils::ReadFile,
diff --git a/runtime/bin/process_patch.dart b/runtime/bin/process_patch.dart
index 1917b46..60fb2b5 100644
--- a/runtime/bin/process_patch.dart
+++ b/runtime/bin/process_patch.dart
@@ -188,9 +188,9 @@
                bool runInShell,
                ProcessStartMode mode) : super() {
     if (!connectedResourceHandler) {
-      registerExtension('__getProcesses',
+      registerExtension('ext.dart.io.getProcesses',
                         _ProcessResourceInfo.getStartedProcesses);
-      registerExtension('__getProcessById',
+      registerExtension('ext.dart.io.getProcessById',
                         _ProcessResourceInfo.getProcessInfoMapById);
       connectedResourceHandler = true;
     }
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index bfb597b..ec9479a 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -106,7 +106,7 @@
                                                              dart_argv);
   ASSERT(set_vm_flags_success);
   const char* err_msg = Dart::InitOnce(dart::bin::vm_isolate_snapshot_buffer,
-                                       NULL,
+                                       NULL, NULL,
                                        NULL, NULL,
                                        dart::bin::DartUtils::OpenFile,
                                        dart::bin::DartUtils::ReadFile,
diff --git a/runtime/bin/secure_socket.cc b/runtime/bin/secure_socket.cc
index fa1f7f1..d7735af 100644
--- a/runtime/bin/secure_socket.cc
+++ b/runtime/bin/secure_socket.cc
@@ -12,6 +12,7 @@
 
 #include <openssl/bio.h>
 #include <openssl/err.h>
+#include <openssl/pkcs12.h>
 #include <openssl/safestack.h>
 #include <openssl/ssl.h>
 #include <openssl/tls1.h>
@@ -381,11 +382,11 @@
 // BIO is allocated. Leaving the scope cleans up the BIO and the buffer that
 // was used to create it.
 //
-// Do not make Dart_ API calls while in a MemBIOScope.
-// Do not call Dart_PropagateError while in a MemBIOScope.
-class MemBIOScope {
+// Do not make Dart_ API calls while in a ScopedMemBIO.
+// Do not call Dart_PropagateError while in a ScopedMemBIO.
+class ScopedMemBIO {
  public:
-  explicit MemBIOScope(Dart_Handle object) {
+  explicit ScopedMemBIO(Dart_Handle object) {
     if (!Dart_IsTypedData(object) && !Dart_IsList(object)) {
       Dart_ThrowException(DartUtils::NewDartArgumentError(
           "Argument is not a List<int>"));
@@ -418,7 +419,7 @@
     is_typed_data_ = is_typed_data;
   }
 
-  ~MemBIOScope() {
+  ~ScopedMemBIO() {
     ASSERT(bio_ != NULL);
     if (is_typed_data_) {
       BIO_free(bio_);
@@ -441,10 +442,120 @@
   bool is_typed_data_;
 
   DISALLOW_ALLOCATION();
-  DISALLOW_COPY_AND_ASSIGN(MemBIOScope);
+  DISALLOW_COPY_AND_ASSIGN(ScopedMemBIO);
 };
 
 
+template<typename T, void (*free_func)(T*)>
+class ScopedSSLType {
+ public:
+  explicit ScopedSSLType(T* obj) : obj_(obj) {}
+
+  ~ScopedSSLType() {
+    if (obj_ != NULL) {
+      free_func(obj_);
+    }
+  }
+
+  T* get() { return obj_; }
+  const T* get() const { return obj_; }
+
+  T* release() {
+    T* result = obj_;
+    obj_ = NULL;
+    return result;
+  }
+
+ private:
+  T* obj_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(ScopedSSLType);
+};
+
+template<typename T, typename E, void (*func)(E*)>
+class ScopedSSLStackType {
+ public:
+  explicit ScopedSSLStackType(T* obj) : obj_(obj) {}
+
+  ~ScopedSSLStackType() {
+    if (obj_ != NULL) {
+      sk_pop_free(reinterpret_cast<_STACK*>(obj_),
+                  reinterpret_cast<void (*)(void *)>(func));
+    }
+  }
+
+  T* get() { return obj_; }
+  const T* get() const { return obj_; }
+
+  T* release() {
+    T* result = obj_;
+    obj_ = NULL;
+    return result;
+  }
+
+ private:
+  T* obj_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(ScopedSSLStackType);
+};
+
+typedef ScopedSSLType<PKCS12, PKCS12_free> ScopedPKCS12;
+typedef ScopedSSLType<X509, X509_free> ScopedX509;
+
+typedef ScopedSSLStackType<STACK_OF(X509), X509, X509_free> ScopedX509Stack;
+typedef ScopedSSLStackType<STACK_OF(X509_NAME), X509_NAME, X509_NAME_free>
+    ScopedX509NAMEStack;
+
+
+// We try reading data as PKCS12 only if reading as PEM was unsuccessful and
+// if there is no indication that the data is malformed PEM. We assume the data
+// is malformed PEM if it contains the start line, i.e. a line with ----- BEGIN.
+static bool TryPKCS12(bool pem_success) {
+  uint32_t last_error = ERR_peek_last_error();
+  return !pem_success &&
+      (ERR_GET_LIB(last_error) == ERR_LIB_PEM) &&
+      (ERR_GET_REASON(last_error) == PEM_R_NO_START_LINE);
+}
+
+
+static EVP_PKEY* GetPrivateKeyPKCS12(BIO* bio, const char* password) {
+  ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
+  if (p12.get() == NULL) {
+    return NULL;
+  }
+
+  EVP_PKEY* key = NULL;
+  X509 *cert = NULL;
+  STACK_OF(X509) *ca_certs = NULL;
+  int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs);
+  if (status == 0) {
+    return NULL;
+  }
+
+  // We only care about the private key.
+  ScopedX509 delete_cert(cert);
+  ScopedX509Stack delete_ca_certs(ca_certs);
+  return key;
+}
+
+
+static EVP_PKEY* GetPrivateKey(BIO* bio, const char* password) {
+  EVP_PKEY *key = PEM_read_bio_PrivateKey(
+      bio, NULL, PasswordCallback, const_cast<char*>(password));
+  if (TryPKCS12(key != NULL)) {
+    // Reset the bio, and clear the error from trying to read as PEM.
+    ERR_clear_error();
+    BIO_reset(bio);
+
+    // Try to decode as PKCS12
+    key = GetPrivateKeyPKCS12(bio, password);
+  }
+  return key;
+}
+
+
 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)(
     Dart_NativeArguments args) {
   SSL_CTX* context = GetSecurityContext(args);
@@ -467,9 +578,8 @@
 
   int status;
   {
-    MemBIOScope bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
-    EVP_PKEY *key = PEM_read_bio_PrivateKey(
-        bio.bio(), NULL, PasswordCallback, const_cast<char*>(password));
+    ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+    EVP_PKEY *key = GetPrivateKey(bio.bio(), password);
     status = SSL_CTX_use_PrivateKey(context, key);
   }
 
@@ -480,7 +590,52 @@
 }
 
 
-static int SetTrustedCertificatesBytes(SSL_CTX* context, BIO* bio) {
+static int SetTrustedCertificatesBytesPKCS12(SSL_CTX* context, BIO* bio) {
+  ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
+  if (p12.get() == NULL) {
+    return NULL;
+  }
+
+  EVP_PKEY* key = NULL;
+  X509 *cert = NULL;
+  STACK_OF(X509) *ca_certs = NULL;
+  // There should be no private keys in this file, so we hardcode the password
+  // to "".
+  // TODO(zra): Allow passing a password anyway.
+  int status = PKCS12_parse(p12.get(), "", &key, &cert, &ca_certs);
+  if (status == 0) {
+    return status;
+  }
+
+  ScopedX509Stack cert_stack(ca_certs);
+
+  // There should be no private key.
+  if (key != NULL) {
+    X509_free(cert);
+    return 0;
+  }
+
+  X509_STORE* store = SSL_CTX_get_cert_store(context);
+  status = X509_STORE_add_cert(store, cert);
+  if (status == 0) {
+    X509_free(cert);
+    return status;
+  }
+
+  X509* ca;
+  while ((ca = sk_X509_shift(cert_stack.get())) != NULL) {
+    status = X509_STORE_add_cert(store, ca);
+    if (status == 0) {
+      X509_free(ca);
+      return status;
+    }
+  }
+
+  return status;
+}
+
+
+static int SetTrustedCertificatesBytesPEM(SSL_CTX* context, BIO* bio) {
   X509_STORE* store = SSL_CTX_get_cert_store(context);
 
   int status = 0;
@@ -493,13 +648,13 @@
     }
   }
 
+  // If bio does not contain PEM data, the first call to PEM_read_bio_X509 will
+  // return NULL, and the while-loop will exit while status is still 0.
   uint32_t err = ERR_peek_last_error();
-  if ((ERR_GET_LIB(err) == ERR_LIB_PEM) &&
-      (ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
-    // Reached the end of the buffer.
-    ERR_clear_error();
-  } else {
-    // Some real error happened.
+  if ((ERR_GET_LIB(err) != ERR_LIB_PEM) ||
+      (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) {
+    // If bio contains data that is trying to be PEM but is malformed, then
+    // this case will be triggered.
     status = 0;
   }
 
@@ -507,12 +662,26 @@
 }
 
 
+static int SetTrustedCertificatesBytes(SSL_CTX* context, BIO* bio) {
+  int status = SetTrustedCertificatesBytesPEM(context, bio);
+  if (TryPKCS12(status != 0)) {
+    ERR_clear_error();
+    BIO_reset(bio);
+    status = SetTrustedCertificatesBytesPKCS12(context, bio);
+  } else if (status != 0) {
+    // The PEM file was successfully parsed.
+    ERR_clear_error();
+  }
+  return status;
+}
+
+
 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)(
     Dart_NativeArguments args) {
   SSL_CTX* context = GetSecurityContext(args);
   int status;
   {
-    MemBIOScope bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+    ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
     status = SetTrustedCertificatesBytes(context, bio.bio());
   }
   CheckStatus(status,
@@ -539,34 +708,78 @@
 }
 
 
-static int UseChainBytes(SSL_CTX* context, BIO* bio) {
-  int status = 0;
-  X509* x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
-  if (x509 == NULL) {
+static int UseChainBytesPKCS12(SSL_CTX* context, BIO* bio) {
+  ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
+  if (p12.get() == NULL) {
+    return NULL;
+  }
+
+  EVP_PKEY* key = NULL;
+  X509 *cert = NULL;
+  STACK_OF(X509) *ca_certs = NULL;
+  // There should be no private keys in this file, so we hardcode the password
+  // to "".
+  // TODO(zra): Allow passing a password anyway.
+  int status = PKCS12_parse(p12.get(), "", &key, &cert, &ca_certs);
+  if (status == 0) {
+    return status;
+  }
+
+  ScopedX509 x509(cert);
+  ScopedX509Stack certs(ca_certs);
+
+  // There should be no private key.
+  if (key != NULL) {
     return 0;
   }
 
-  status = SSL_CTX_use_certificate(context, x509);
+  status = SSL_CTX_use_certificate(context, x509.get());
   if (ERR_peek_error() != 0) {
     // Key/certificate mismatch doesn't imply status is 0.
     status = 0;
   }
   if (status == 0) {
-    X509_free(x509);
     return status;
   }
 
   SSL_CTX_clear_chain_certs(context);
 
-  while (true) {
-    X509* ca = PEM_read_bio_X509(bio, NULL, NULL, NULL);
-    if (ca == NULL) {
-      break;
-    }
+  X509* ca;
+  while ((ca = sk_X509_shift(certs.get())) != NULL) {
     status = SSL_CTX_add0_chain_cert(context, ca);
     if (status == 0) {
       X509_free(ca);
-      X509_free(x509);
+      return status;
+    }
+  }
+
+  return status;
+}
+
+
+static int UseChainBytesPEM(SSL_CTX* context, BIO* bio) {
+  int status = 0;
+  ScopedX509 x509(PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL));
+  if (x509.get() == NULL) {
+    return 0;
+  }
+
+  status = SSL_CTX_use_certificate(context, x509.get());
+  if (ERR_peek_error() != 0) {
+    // Key/certificate mismatch doesn't imply status is 0.
+    status = 0;
+  }
+  if (status == 0) {
+    return status;
+  }
+
+  SSL_CTX_clear_chain_certs(context);
+
+  X509* ca;
+  while ((ca = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
+    status = SSL_CTX_add0_chain_cert(context, ca);
+    if (status == 0) {
+      X509_free(ca);
       return status;
     }
     // Note that we must not free `ca` if it was successfully added to the
@@ -574,17 +787,30 @@
     // count is increased by SSL_CTX_use_certificate.
   }
 
+  // If bio does not contain PEM data, the first call to PEM_read_bio_X509 will
+  // return NULL, and the while-loop will exit while status is still 0.
   uint32_t err = ERR_peek_last_error();
-  if ((ERR_GET_LIB(err) == ERR_LIB_PEM) &&
-      (ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
-    // Reached the end of the buffer.
-    ERR_clear_error();
-  } else {
-    // Some real error happened.
+  if ((ERR_GET_LIB(err) != ERR_LIB_PEM) ||
+      (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) {
+    // If bio contains data that is trying to be PEM but is malformed, then
+    // this case will be triggered.
     status = 0;
   }
 
-  X509_free(x509);
+  return status;
+}
+
+
+static int UseChainBytes(SSL_CTX* context, BIO* bio) {
+  int status = UseChainBytesPEM(context, bio);
+  if (TryPKCS12(status != 0)) {
+    ERR_clear_error();
+    BIO_reset(bio);
+    status = UseChainBytesPKCS12(context, bio);
+  } else if (status != 0) {
+    // The PEM file was successfully read.
+    ERR_clear_error();
+  }
   return status;
 }
 
@@ -594,7 +820,7 @@
   SSL_CTX* context = GetSecurityContext(args);
   int status;
   {
-    MemBIOScope bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+    ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
     status = UseChainBytes(context, bio.bio());
   }
   CheckStatus(status,
@@ -603,36 +829,122 @@
 }
 
 
-static STACK_OF(X509_NAME)* GetCertificateNames(BIO* bio) {
-  STACK_OF(X509_NAME)* result = sk_X509_NAME_new_null();
-  if (result == NULL) {
+static STACK_OF(X509_NAME)* GetCertificateNamesPKCS12(BIO* bio) {
+  ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
+  if (p12.get() == NULL) {
+    return NULL;
+  }
+
+  ScopedX509NAMEStack result(sk_X509_NAME_new_null());
+  if (result.get() == NULL) {
+    return NULL;
+  }
+
+  EVP_PKEY* key = NULL;
+  X509 *cert = NULL;
+  STACK_OF(X509) *ca_certs = NULL;
+  // There should be no private keys in this file, so we hardcode the password
+  // to "".
+  // TODO(zra): Allow passing a password anyway.
+  int status = PKCS12_parse(p12.get(), "", &key, &cert, &ca_certs);
+  if (status == 0) {
+    return NULL;
+  }
+
+  ScopedX509 x509(cert);
+  ScopedX509Stack certs(ca_certs);
+
+  // There should be no private key.
+  if (key != NULL) {
+    return NULL;
+  }
+
+  X509_NAME* x509_name = X509_get_subject_name(x509.get());
+  if (x509_name == NULL) {
+    return NULL;
+  }
+
+  x509_name = X509_NAME_dup(x509_name);
+  if (x509_name == NULL) {
+    return NULL;
+  }
+
+  sk_X509_NAME_push(result.get(), x509_name);
+
+  while (true) {
+    ScopedX509 ca(sk_X509_shift(certs.get()));
+    if (ca.get() == NULL) {
+      break;
+    }
+
+    X509_NAME* x509_name = X509_get_subject_name(ca.get());
+    if (x509_name == NULL) {
+      return NULL;
+    }
+
+    x509_name = X509_NAME_dup(x509_name);
+    if (x509_name == NULL) {
+      return NULL;
+    }
+
+    sk_X509_NAME_push(result.get(), x509_name);
+  }
+
+  return result.release();
+}
+
+
+static STACK_OF(X509_NAME)* GetCertificateNamesPEM(BIO* bio) {
+  ScopedX509NAMEStack result(sk_X509_NAME_new_null());
+  if (result.get() == NULL) {
     return NULL;
   }
 
   while (true) {
-    X509* x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
-    if (x509 == NULL) {
+    ScopedX509 x509(PEM_read_bio_X509(bio, NULL, NULL, NULL));
+    if (x509.get() == NULL) {
       break;
     }
 
-    X509_NAME* x509_name = X509_get_subject_name(x509);
+    X509_NAME* x509_name = X509_get_subject_name(x509.get());
     if (x509_name == NULL) {
-      sk_X509_NAME_pop_free(result, X509_NAME_free);
-      X509_free(x509);
       return NULL;
     }
 
     // Duplicate the name to put it on the stack.
     x509_name = X509_NAME_dup(x509_name);
     if (x509_name == NULL) {
-      sk_X509_NAME_pop_free(result, X509_NAME_free);
-      X509_free(x509);
       return NULL;
     }
-    sk_X509_NAME_push(result, x509_name);
-    X509_free(x509);
+    sk_X509_NAME_push(result.get(), x509_name);
   }
 
+  if (sk_X509_NAME_num(result.get()) == 0) {
+    // The data was not PEM.
+    return NULL;
+  }
+
+  uint32_t err = ERR_peek_last_error();
+  if ((ERR_GET_LIB(err) != ERR_LIB_PEM) ||
+      (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) {
+    // The data was trying to be PEM, but was malformed.
+    return NULL;
+  }
+
+  return result.release();
+}
+
+
+static STACK_OF(X509_NAME)* GetCertificateNames(BIO* bio) {
+  STACK_OF(X509_NAME)* result = GetCertificateNamesPEM(bio);
+  if (TryPKCS12(result != NULL)) {
+    ERR_clear_error();
+    BIO_reset(bio);
+    result = GetCertificateNamesPKCS12(bio);
+  } else if (result != NULL) {
+    // The PEM file was successfully parsed.
+    ERR_clear_error();
+  }
   return result;
 }
 
@@ -643,7 +955,7 @@
   STACK_OF(X509_NAME)* certificate_names;
 
   {
-    MemBIOScope bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+    ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
     certificate_names = GetCertificateNames(bio.bio());
   }
 
diff --git a/runtime/bin/secure_socket.h b/runtime/bin/secure_socket.h
index 29adef4..bd5eda3 100644
--- a/runtime/bin/secure_socket.h
+++ b/runtime/bin/secure_socket.h
@@ -116,7 +116,6 @@
   bool in_handshake_;
   bool is_server_;
   char* hostname_;
-  X509_VERIFY_PARAM* certificate_checking_parameters_;
 
   static bool isBufferEncrypted(int i) {
     return static_cast<BufferIndex>(i) >= kFirstEncrypted;
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index 7de16a9..09904b4 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -932,9 +932,9 @@
       eventPort = new RawReceivePort(multiplex);
     }
     if (!connectedResourceHandler) {
-      registerExtension('__getOpenSockets',
+      registerExtension('ext.dart.io.getOpenSockets',
                         _SocketResourceInfo.getOpenSockets);
-      registerExtension('__getSocketByID',
+      registerExtension('ext.dart.io.getSocketByID',
                         _SocketResourceInfo.getSocketInfoMapByID);
 
       connectedResourceHandler = true;
diff --git a/runtime/bin/zlib.gyp b/runtime/bin/zlib.gyp
index 6f2f913..98555f9f 100644
--- a/runtime/bin/zlib.gyp
+++ b/runtime/bin/zlib.gyp
@@ -20,7 +20,6 @@
     'zlib_path': '../../third_party/zlib',
   },
   # Added by Dart.  We do not indent, so diffs with the original are clearer.
-  'conditions': [[ 'dart_io_support==1', {
   'targets': [
     {
       'target_name': 'zlib_dart',  # Added by Dart (the _dart postfix)
@@ -72,5 +71,4 @@
       ],
     },
   ],
-  }]],
 }
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index abc92eb..77d1289 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -797,6 +797,7 @@
 DART_EXPORT char* Dart_Initialize(
     const uint8_t* vm_isolate_snapshot,
     const uint8_t* instructions_snapshot,
+    const uint8_t* data_snapshot,
     Dart_IsolateCreateCallback create,
     Dart_IsolateInterruptCallback interrupt,
     Dart_IsolateUnhandledExceptionCallback unhandled_exception,
diff --git a/runtime/lib/core_patch.dart b/runtime/lib/core_patch.dart
index 224d532..11e307a 100644
--- a/runtime/lib/core_patch.dart
+++ b/runtime/lib/core_patch.dart
@@ -40,9 +40,13 @@
 class _SyncIterator implements Iterator {
   bool isYieldEach;  // Set by generated code for the yield* statement.
   Iterator yieldEachIterator;
-  var current;  // Set by generated code for the yield and yield* statement.
+  var _current;  // Set by generated code for the yield and yield* statement.
   SyncGeneratorCallback moveNextFn;
 
+  get current => yieldEachIterator != null
+      ? yieldEachIterator.current
+      : _current;
+
   _SyncIterator(this.moveNextFn);
 
   bool moveNext() {
@@ -52,7 +56,6 @@
     while(true) {
       if (yieldEachIterator != null) {
         if (yieldEachIterator.moveNext()) {
-          current = yieldEachIterator.current;
           return true;
         }
         yieldEachIterator = null;
@@ -60,13 +63,14 @@
       isYieldEach = false;
       if (!moveNextFn(this)) {
         moveNextFn = null;
-        current = null;
+        _current = null;
         return false;
       }
       if (isYieldEach) {
         // Spec mandates: it is a dynamic error if the class of [the object
         // returned by yield*] does not implement Iterable.
-        yieldEachIterator = (current as Iterable).iterator;
+        yieldEachIterator = (_current as Iterable).iterator;
+        _current = null;
         continue;
       }
       return true;
diff --git a/runtime/lib/developer.dart b/runtime/lib/developer.dart
index af505ff..f7b45f0 100644
--- a/runtime/lib/developer.dart
+++ b/runtime/lib/developer.dart
@@ -67,7 +67,8 @@
               List<String> parameterKeys,
               List<String> parameterValues,
               SendPort replyPort,
-              Object id) {
+              Object id,
+              bool trace_service) {
   var parameters = {};
   for (var i = 0; i < parameterKeys.length; i++) {
     parameters[parameterKeys[i]] = parameterValues[i];
@@ -80,14 +81,14 @@
     response = new ServiceExtensionResponse.error(
         ServiceExtensionResponse.kExtensionError,
         errorDetails);
-    _postResponse(replyPort, id, response);
+    _postResponse(replyPort, id, response, trace_service);
     return;
   }
   if (response is! Future) {
     response = new ServiceExtensionResponse.error(
           ServiceExtensionResponse.kExtensionError,
           "Extension handler must return a Future");
-    _postResponse(replyPort, id, response);
+    _postResponse(replyPort, id, response, trace_service);
     return;
   }
   response.catchError((e, st) {
@@ -104,7 +105,7 @@
           ServiceExtensionResponse.kExtensionError,
           "Extension handler must complete to a ServiceExtensionResponse");
     }
-    _postResponse(replyPort, id, response);
+    _postResponse(replyPort, id, response, trace_service);
   }).catchError((e, st) {
     // We do not expect any errors to occur in the .then or .catchError blocks
     // but, suppress them just in case.
@@ -114,9 +115,13 @@
 // This code is only invoked by _runExtension.
 _postResponse(SendPort replyPort,
               Object id,
-              ServiceExtensionResponse response) {
+              ServiceExtensionResponse response,
+              bool trace_service) {
   assert(replyPort != null);
   if (id == null) {
+    if (trace_service) {
+      print("vm-service: posting no response for request");
+    }
     // No id -> no response.
     replyPort.send(null);
     return;
@@ -125,8 +130,14 @@
   StringBuffer sb = new StringBuffer();
   sb.write('{"jsonrpc":"2.0",');
   if (response._isError()) {
+    if (trace_service) {
+      print("vm-service: posting error response for request $id");
+    }
     sb.write('"error":');
   } else {
+    if (trace_service) {
+      print("vm-service: posting response for request $id");
+    }
     sb.write('"result":');
   }
   sb.write('${response._toString()},');
diff --git a/runtime/lib/errors.cc b/runtime/lib/errors.cc
index dd7acd8..785950b 100644
--- a/runtime/lib/errors.cc
+++ b/runtime/lib/errors.cc
@@ -10,17 +10,11 @@
 
 namespace dart {
 
-DECLARE_FLAG(bool, abort_on_assertion_errors);
-
 // Allocate and throw a new AssertionError.
 // Arg0: index of the first token of the failed assertion.
 // Arg1: index of the first token after the failed assertion.
 // Return value: none, throws an exception.
 DEFINE_NATIVE_ENTRY(AssertionError_throwNew, 2) {
-  if (FLAG_abort_on_assertion_errors) {
-    Exceptions::PrintStackTraceAndAbort("an assertion failure");
-  }
-
   // No need to type check the arguments. This function can only be called
   // internally from the VM.
   const TokenPosition assertion_start =
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index 59a61ec..0165ed9 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -362,18 +362,3 @@
     return msg_buf.toString();
   }
 }
-
-class _JavascriptIntegerOverflowError extends Error {
-  final Object _value;
-
-  _JavascriptIntegerOverflowError(this._value);
-  String toString() => "Javascript Integer Overflow: $_value";
-}
-
-class _JavascriptCompatibilityError extends Error {
-  final String _msg;
-
-  _JavascriptCompatibilityError(this._msg);
-  String toString() => "Javascript Compatibility Error: $_msg";
-}
-
diff --git a/runtime/lib/identical.cc b/runtime/lib/identical.cc
index 6440726..4b24219 100644
--- a/runtime/lib/identical.cc
+++ b/runtime/lib/identical.cc
@@ -9,45 +9,10 @@
 
 namespace dart {
 
-DECLARE_FLAG(bool, warn_on_javascript_compatibility);
-
 DEFINE_NATIVE_ENTRY(Identical_comparison, 2) {
   GET_NATIVE_ARGUMENT(Instance, a, arguments->NativeArgAt(0));
   GET_NATIVE_ARGUMENT(Instance, b, arguments->NativeArgAt(1));
   const bool is_identical = a.IsIdenticalTo(b);
-  if (FLAG_warn_on_javascript_compatibility) {
-    if (!is_identical) {
-      if (a.IsString()) {
-        if (String::Cast(a).Equals(b)) {
-          Report::JSWarningFromNative(
-              true,  // Identical_comparison is static.
-              "strings that are equal are also identical");
-        }
-      } else if (a.IsInteger()) {
-        if (b.IsDouble()) {
-          const int64_t a_value = Integer::Cast(a).AsInt64Value();
-          const double b_value = Double::Cast(b).value();
-          if (a_value == floor(b_value)) {
-            Report::JSWarningFromNative(
-                true,  // Identical_comparison is static.
-                "integer value and integral double value that are equal "
-                "are also identical");
-          }
-        }
-      } else if (a.IsDouble()) {
-        if (b.IsInteger()) {
-          const double a_value = Double::Cast(a).value();
-          const int64_t b_value = Integer::Cast(b).AsInt64Value();
-          if (floor(a_value) == b_value) {
-            Report::JSWarningFromNative(
-                true,  // Identical_comparison is static.
-                "integral double value and integer value that are equal "
-                "are also identical");
-          }
-        }
-      }
-    }
-  }
   return Bool::Get(is_identical).raw();
 }
 
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index 8deeee4..9478fcc 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -251,17 +251,15 @@
 }
 
 
-// Passing true for 'silent' prevents throwing JavascriptIntegerOverflow.
 static RawInteger* ShiftOperationHelper(Token::Kind kind,
                                         const Integer& value,
-                                        const Smi& amount,
-                                        const bool silent = false) {
+                                        const Smi& amount) {
   if (amount.Value() < 0) {
     Exceptions::ThrowArgumentError(amount);
   }
   if (value.IsSmi()) {
     const Smi& smi_value = Smi::Cast(value);
-    return smi_value.ShiftOp(kind, amount, Heap::kNew, silent);
+    return smi_value.ShiftOp(kind, amount, Heap::kNew);
   }
   if (value.IsMint()) {
     const int64_t mint_value = value.AsInt64Value();
@@ -273,11 +271,11 @@
     if ((count + shift_count) < Mint::kBits) {
       switch (kind) {
         case Token::kSHL:
-          return Integer::New(mint_value << shift_count, Heap::kNew, silent);
+          return Integer::New(mint_value << shift_count, Heap::kNew);
         case Token::kSHR:
           shift_count =
               (-shift_count > Mint::kBits) ? Mint::kBits : -shift_count;
-          return Integer::New(mint_value >> shift_count, Heap::kNew, silent);
+          return Integer::New(mint_value >> shift_count, Heap::kNew);
         default:
           UNIMPLEMENTED();
       }
@@ -307,7 +305,7 @@
   }
   const Smi& smi_shift_count = Smi::Cast(shift_count);
   const Integer& shift_result = Integer::Handle(
-      ShiftOperationHelper(Token::kSHL, value, smi_shift_count, true));
+      ShiftOperationHelper(Token::kSHL, value, smi_shift_count));
   const Integer& result =
       Integer::Handle(shift_result.BitOp(Token::kBIT_AND, mask));
   return result.AsValidInteger();
diff --git a/runtime/lib/math_patch.dart b/runtime/lib/math_patch.dart
index 667174c..4f0b852 100644
--- a/runtime/lib/math_patch.dart
+++ b/runtime/lib/math_patch.dart
@@ -116,6 +116,7 @@
   //   _state[_kSTATE_HI] = state >> 32;
   // This is a native to prevent 64-bit operations in Dart, which
   // fail with --throw_on_javascript_int_overflow.
+  // TODO(regis): Implement in Dart and remove Random_nextState in math.cc.
   void _nextState() native "Random_nextState";
 
   int nextInt(int max) {
@@ -160,6 +161,7 @@
 
   // This is a native to prevent 64-bit operations in Dart, which
   // fail with --throw_on_javascript_int_overflow.
+  // TODO(regis): Implement here in Dart and remove native in math.cc.
   static Uint32List _setupSeed(int seed) native "Random_setupSeed";
   // Get a seed from the VM's random number provider.
   static Uint32List _initialSeed() native "Random_initialSeed";
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index b7d95b1..e2ded52 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -2086,7 +2086,7 @@
 DEFINE_NATIVE_ENTRY(TypeMirror_subtypeTest, 2) {
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, a, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, b, arguments->NativeArgAt(1));
-  return Bool::Get(a.IsSubtypeOf(b, NULL)).raw();
+  return Bool::Get(a.IsSubtypeOf(b, NULL, NULL, Heap::kNew)).raw();
 }
 
 
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index cc64a06..95f2661 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -17,7 +17,6 @@
 namespace dart {
 
 DECLARE_FLAG(bool, trace_type_checks);
-DECLARE_FLAG(bool, warn_on_javascript_compatibility);
 
 // Helper function in stacktrace.cc.
 void _printCurrentStacktrace();
@@ -121,40 +120,6 @@
 }
 
 
-static void WarnOnJSIntegralNumTypeTest(
-    const Instance& instance,
-    const TypeArguments& instantiator_type_arguments,
-    const AbstractType& type) {
-  const bool instance_is_int = instance.IsInteger();
-  const bool instance_is_double = instance.IsDouble();
-  if (!(instance_is_int || instance_is_double)) {
-    return;
-  }
-  AbstractType& instantiated_type = AbstractType::Handle(type.raw());
-  if (!type.IsInstantiated()) {
-    instantiated_type = type.InstantiateFrom(instantiator_type_arguments, NULL);
-  }
-  if (instance_is_double) {
-    if (instantiated_type.IsIntType()) {
-      const double value = Double::Cast(instance).value();
-      if (floor(value) == value) {
-        Report::JSWarningFromNative(
-            false,  // Object_instanceOf and Object_as are not static calls.
-            "integral value of type 'double' is also considered to be "
-            "of type 'int'");
-      }
-    }
-  } else {
-    ASSERT(instance_is_int);
-    if (instantiated_type.IsDoubleType()) {
-      Report::JSWarningFromNative(
-          false,  // Object_instanceOf and Object_as are not static calls.
-          "integer value is also considered to be of type 'double'");
-    }
-  }
-}
-
-
 DEFINE_NATIVE_ENTRY(Object_instanceOf, 4) {
   const Instance& instance =
       Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
@@ -166,12 +131,6 @@
   ASSERT(type.IsFinalized());
   ASSERT(!type.IsMalformed());
   ASSERT(!type.IsMalbounded());
-
-  // Check for javascript compatibility.
-  if (FLAG_warn_on_javascript_compatibility) {
-    WarnOnJSIntegralNumTypeTest(instance, instantiator_type_arguments, type);
-  }
-
   Error& bound_error = Error::Handle(zone, Error::null());
   const bool is_instance_of = instance.IsInstanceOf(type,
                                                     instantiator_type_arguments,
@@ -278,12 +237,6 @@
   if (instance.IsNull()) {
     return instance.raw();
   }
-
-  // Check for javascript compatibility.
-  if (FLAG_warn_on_javascript_compatibility) {
-    WarnOnJSIntegralNumTypeTest(instance, instantiator_type_arguments, type);
-  }
-
   const bool is_instance_of = instance.IsInstanceOf(type,
                                                     instantiator_type_arguments,
                                                     &bound_error);
@@ -312,7 +265,8 @@
     if (!type.IsInstantiated()) {
       // Instantiate type before reporting the error.
       const AbstractType& instantiated_type = AbstractType::Handle(
-          type.InstantiateFrom(instantiator_type_arguments, NULL));
+          type.InstantiateFrom(instantiator_type_arguments, NULL,
+                               NULL, NULL, Heap::kNew));
       // Note that instantiated_type may be malformed.
       type_name = instantiated_type.UserVisibleName();
     } else {
diff --git a/runtime/lib/timeline.cc b/runtime/lib/timeline.cc
index 51319d7..ddc2f5a 100644
--- a/runtime/lib/timeline.cc
+++ b/runtime/lib/timeline.cc
@@ -16,9 +16,7 @@
 // Native implementations for the dart:developer library.
 
 DEFINE_NATIVE_ENTRY(Timeline_getIsolateNum, 0) {
-  return Integer::New(static_cast<int64_t>(isolate->main_port()),
-                      Heap::kOld,
-                      true);
+  return Integer::New(static_cast<int64_t>(isolate->main_port()), Heap::kOld);
 }
 
 
@@ -35,7 +33,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Timeline_getTraceClock, 0) {
-  return Integer::New(OS::GetCurrentMonotonicMicros(), Heap::kNew, true);
+  return Integer::New(OS::GetCurrentMonotonicMicros(), Heap::kNew);
 }
 
 
diff --git a/runtime/observatory/lib/object_graph.dart b/runtime/observatory/lib/object_graph.dart
index e70570e..8b491e8 100644
--- a/runtime/observatory/lib/object_graph.dart
+++ b/runtime/observatory/lib/object_graph.dart
@@ -8,8 +8,6 @@
 import 'dart:collection';
 import 'dart:typed_data';
 
-import 'package:logging/logging.dart';
-
 class _JenkinsSmiHash {
   static int combine(int hash, int value) {
     hash = 0x1fffffff & (hash + value);
@@ -499,7 +497,7 @@
         if (childId != null) {
           succs[edge] = childId;
           edge++;
-        } else { 
+        } else {
           // Reference into VM isolate's heap.
         }
         stream.readUnsigned();
@@ -519,7 +517,6 @@
 
   void _dfs() {
     var N = _N;
-    var E = _E;
     var firstSuccs = _firstSuccs;
     var succs = _succs;
 
@@ -531,7 +528,6 @@
     var parent = new Uint32List(N + 1);
     var dfsNumber = 0;
 
-    var dfsCount = 0;
     var stackTop = 0;
     var root = 1;
 
diff --git a/runtime/observatory/lib/src/app/page.dart b/runtime/observatory/lib/src/app/page.dart
index 21305e1..6be5e88 100644
--- a/runtime/observatory/lib/src/app/page.dart
+++ b/runtime/observatory/lib/src/app/page.dart
@@ -122,6 +122,8 @@
       }
     }).catchError((e, stack) {
       Logger.root.severe('VMPage visit error: $e');
+      // Reroute to vm-connect.
+      app.locationManager.go(app.locationManager.makeLink('/vm-connect'));
     });
   }
 }
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index 06f91e7..3692d6a 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -1826,7 +1826,8 @@
       if (event.asyncContinuation == null) {
         console.print("No async continuation at this location");
       } else {
-        return isolate.asyncStepOver()[Isolate.kFirstResume];
+        List<Future> asyncStepFutures = await isolate.asyncStepOver();
+        return asyncStepFutures[Isolate.kFirstResume];
       }
     } else {
       console.print('The program is already running');
diff --git a/runtime/observatory/lib/src/elements/timeline_page.dart b/runtime/observatory/lib/src/elements/timeline_page.dart
index 04a7376..b7a5462 100644
--- a/runtime/observatory/lib/src/elements/timeline_page.dart
+++ b/runtime/observatory/lib/src/elements/timeline_page.dart
@@ -57,14 +57,14 @@
   }
 
   Future recordOn() async {
-    return app.vm.invokeRpc('_setVMTimelineFlag', {
-      '_record': 'all',
+    return app.vm.invokeRpc('_setVMTimelineFlags', {
+      'recordedStreams': ['all'],
     });
   }
 
   Future recordOff() async {
-    return app.vm.invokeRpc('_setVMTimelineFlag', {
-      '_record': 'none',
+    return app.vm.invokeRpc('_setVMTimelineFlags', {
+      'recordedStreams': [],
     });
   }
 
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index bbf1c34..bd76e67 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -1590,11 +1590,13 @@
   /// result[kSecondResume] completes after the second resume. Tests should
   /// wait on this future to avoid confusing the pause event at the
   /// state-machine switch with the pause event after the state-machine switch.
-  List<Future> asyncStepOver() {
-    Completer firstResume = new Completer();
-    Completer secondResume = new Completer();
-    var subscription;
+  Future<List<Future>> asyncStepOver() async {
+    final Completer firstResume = new Completer();
+    final Completer secondResume = new Completer();
+    final List<Future> result = [firstResume.future, secondResume.future];
+    StreamSubscription subscription;
 
+    // Inner error handling function.
     handleError(error) {
       if (subscription != null) {
         subscription.cancel();
@@ -1611,35 +1613,56 @@
     } else {
       Instance continuation = pauseEvent.asyncContinuation;
       assert(continuation.isClosure);
-      addBreakOnActivation(continuation).then((Breakpoint continuationBpt) {
-        vm.getEventStream(VM.kDebugStream).then((stream) {
-          var onResume = firstResume;
-          subscription = stream.listen((ServiceEvent event) {
-            if ((event.kind == ServiceEvent.kPauseBreakpoint) &&
-                (event.breakpoint == continuationBpt)) {
-              // We are stopped before state-machine dispatch; step-over to
-              // reach user code.
-              removeBreakpoint(continuationBpt).then((_) {
-                onResume = secondResume;
-                stepOver().catchError(handleError);
-              });
-            } else if (event.kind == ServiceEvent.kResume) {
-              if (onResume == secondResume) {
-                subscription.cancel();
-                subscription = null;
-              }
-              if (onResume != null) {
-                onResume.complete(this);
-                onResume = null;
-              }
-            }
-          });
-          resume().catchError(handleError);
-        }).catchError(handleError);
-      }).catchError(handleError);
-    }
 
-    return [firstResume.future, secondResume.future];
+      // Add breakpoint at continuation.
+      Breakpoint continuationBpt;
+      try {
+        continuationBpt = await addBreakOnActivation(continuation);
+      } catch (e) {
+        handleError(e);
+        return result;
+      }
+
+      // Subscribe to the debugger event stream.
+      Stream stream;
+      try {
+        stream = await vm.getEventStream(VM.kDebugStream);
+      } catch (e) {
+        handleError(e);
+        return result;
+      }
+
+      Completer onResume = firstResume;
+      subscription = stream.listen((ServiceEvent event) async {
+        if ((event.kind == ServiceEvent.kPauseBreakpoint) &&
+            (event.breakpoint == continuationBpt)) {
+          // We are stopped before state-machine dispatch:
+          // 1) Remove the continuation breakpoint.
+          // 2) step over.
+          // reach user code.
+          await removeBreakpoint(continuationBpt);
+          onResume = secondResume;
+          stepOver().catchError(handleError);
+        } else if (event.kind == ServiceEvent.kResume) {
+          // We've resumed.
+          if (onResume == secondResume) {
+            // This is our second resume, cancel our subscription to the debug
+            // stream.
+            subscription.cancel();
+            subscription = null;
+          }
+          // Complete onResume and clear it.
+          if (onResume != null) {
+            onResume.complete(this);
+            onResume = null;
+          }
+        }
+      });
+
+      // Call resume, which will eventually cause us to hit continuationBpt.
+      resume().catchError(handleError);
+    }
+    return result;
   }
 
   Future setName(String newName) {
@@ -2416,7 +2439,7 @@
     elements = map['elements'];
     associations = map['associations'];
     if (map['bytes'] != null) {
-      var bytes = BASE64.decode(map['bytes']);
+      Uint8List bytes = BASE64.decode(map['bytes']);
       switch (map['kind']) {
         case "Uint8ClampedList":
           typedElements = bytes.buffer.asUint8ClampedList(); break;
@@ -3634,7 +3657,7 @@
 
   @observable bool hasDisassembly = false;
 
-  void _processDisassembly(List<String> disassembly){
+  void _processDisassembly(List disassembly) {
     assert(disassembly != null);
     instructions.clear();
     instructionsByAddressOffset = new List(endAddress - startAddress);
diff --git a/runtime/observatory/tests/service/async_next_test.dart b/runtime/observatory/tests/service/async_next_test.dart
index f3c64d9..dbdc19b 100644
--- a/runtime/observatory/tests/service/async_next_test.dart
+++ b/runtime/observatory/tests/service/async_next_test.dart
@@ -26,7 +26,8 @@
 
 asyncNext(Isolate isolate) async {
   print('asyncNext');
-  return isolate.asyncStepOver()[Isolate.kSecondResume];
+  List asyncStepFutures = await isolate.asyncStepOver();
+  return asyncStepFutures[Isolate.kSecondResume];
 }
 
 var tests = [
diff --git a/runtime/observatory/tests/service/developer_extension_test.dart b/runtime/observatory/tests/service/developer_extension_test.dart
index e29686b..b4bafac 100644
--- a/runtime/observatory/tests/service/developer_extension_test.dart
+++ b/runtime/observatory/tests/service/developer_extension_test.dart
@@ -16,7 +16,7 @@
                                          Map paremeters) {
   print('Invoked extension: $method');
   switch (method) {
-    case '__delay':
+    case 'ext..delay':
       Completer c = new Completer();
       new Timer(new Duration(seconds: 1), () {
         c.complete(new ServiceExtensionResponse.result(JSON.encode({
@@ -26,23 +26,23 @@
           })));
       });
       return c.future;
-    case '__error':
+    case 'ext..error':
       return new Future.value(
               new ServiceExtensionResponse.error(
-                  ServiceExtensionResponse.kExtensionErrorMin,
+                  ServiceExtensionResponse.extensionErrorMin,
                   'My error detail.'));
-    case '__exception':
+    case 'ext..exception':
       throw "I always throw!";
-    case '__success':
+    case 'ext..success':
       return new Future.value(
           new ServiceExtensionResponse.result(JSON.encode({
               'type': '_extensionType',
               'method': method,
               'parameters': paremeters,
           })));
-    case '__null':
+    case 'ext..null':
       return null;
-    case '__nullFuture':
+    case 'ext..nullFuture':
       return new Future.value(null);
   }
 }
@@ -54,25 +54,25 @@
 }
 
 void test() {
-  registerExtension('__delay', Handler);
+  registerExtension('ext..delay', Handler);
   debugger();
   postEvent('ALPHA', {
     'cat': 'dog'
   });
   debugger();
-  registerExtension('__error', Handler);
-  registerExtension('__exception', Handler);
-  registerExtension('__null', Handler);
-  registerExtension('__nullFuture', Handler);
-  registerExtension('__success', Handler);
+  registerExtension('ext..error', Handler);
+  registerExtension('ext..exception', Handler);
+  registerExtension('ext..null', Handler);
+  registerExtension('ext..nullFuture', Handler);
+  registerExtension('ext..success', Handler);
   bool exceptionThrown = false;
   try {
-    registerExtension('__delay', Handler);
+    registerExtension('ext..delay', Handler);
   } catch (e) {
     exceptionThrown = true;
   }
   expect(exceptionThrown, isTrue);
-  registerExtension('__languageError', LanguageErrorHandler);
+  registerExtension('ext..languageError', LanguageErrorHandler);
 }
 
 var tests = [
@@ -80,7 +80,7 @@
   (Isolate isolate) async {
     await isolate.load();
     expect(isolate.extensionRPCs.length, 1);
-    expect(isolate.extensionRPCs[0], equals('__delay'));
+    expect(isolate.extensionRPCs[0], equals('ext..delay'));
   },
   resumeIsolateAndAwaitEvent(Isolate.kExtensionStream, (ServiceEvent event) {
     expect(event.kind, equals(ServiceEvent.kExtension));
@@ -92,65 +92,65 @@
   resumeIsolateAndAwaitEvent(VM.kIsolateStream, (ServiceEvent event) {
     // Check that we received an event when '__error' was registered.
     expect(event.kind, equals(ServiceEvent.kServiceExtensionAdded));
-    expect(event.extensionRPC, equals('__error'));
+    expect(event.extensionRPC, equals('ext..error'));
   }),
   // Initial.
   (Isolate isolate) async {
     var result;
 
-    result = await isolate.invokeRpcNoUpgrade('__delay', {});
+    result = await isolate.invokeRpcNoUpgrade('ext..delay', {});
     expect(result['type'], equals('_delayedType'));
-    expect(result['method'], equals('__delay'));
+    expect(result['method'], equals('ext..delay'));
     expect(result['parameters']['isolateId'], isNotNull);
 
     try {
-      await isolate.invokeRpcNoUpgrade('__error', {});
+      await isolate.invokeRpcNoUpgrade('ext..error', {});
     } on ServerRpcException catch (e, st) {
-      expect(e.code, equals(ServiceExtensionResponse.kExtensionErrorMin));
+      expect(e.code, equals(ServiceExtensionResponse.extensionErrorMin));
       expect(e.message, equals('My error detail.'));
     }
 
     try {
-      await isolate.invokeRpcNoUpgrade('__exception', {});
+      await isolate.invokeRpcNoUpgrade('ext..exception', {});
     } on ServerRpcException catch (e, st) {
-      expect(e.code, equals(ServiceExtensionResponse.kExtensionError));
+      expect(e.code, equals(ServiceExtensionResponse.extensionError));
       expect(e.message.startsWith('I always throw!\n'), isTrue);
     }
 
     try {
-      await isolate.invokeRpcNoUpgrade('__null', {});
+      await isolate.invokeRpcNoUpgrade('ext..null', {});
     } on ServerRpcException catch (e, st) {
-      expect(e.code, equals(ServiceExtensionResponse.kExtensionError));
+      expect(e.code, equals(ServiceExtensionResponse.extensionError));
       expect(e.message, equals('Extension handler must return a Future'));
     }
 
     try {
-      await isolate.invokeRpcNoUpgrade('__nullFuture', {});
+      await isolate.invokeRpcNoUpgrade('ext..nullFuture', {});
     } on ServerRpcException catch (e, st) {
-      expect(e.code, equals(ServiceExtensionResponse.kExtensionError));
+      expect(e.code, equals(ServiceExtensionResponse.extensionError));
       expect(e.message, equals('Extension handler must complete to a '
                                'ServiceExtensionResponse'));
     }
 
-    result = await isolate.invokeRpcNoUpgrade('__success',
+    result = await isolate.invokeRpcNoUpgrade('ext..success',
                                               {'apple': 'banana'});
     expect(result['type'], equals('_extensionType'));
-    expect(result['method'], equals('__success'));
+    expect(result['method'], equals('ext..success'));
     expect(result['parameters']['isolateId'], isNotNull);
     expect(result['parameters']['apple'], equals('banana'));
 
 
     try {
-      result = await isolate.invokeRpcNoUpgrade('__languageError', {});
+      result = await isolate.invokeRpcNoUpgrade('ext..languageError', {});
     } on ServerRpcException catch (e, st) {
-      expect(e.code, equals(ServiceExtensionResponse.kExtensionError));
+      expect(e.code, equals(ServiceExtensionResponse.extensionError));
       expect(e.message, stringContainsInOrder([
-          'Error in extension `__languageError`:',
+          'Error in extension `ext..languageError`:',
           'developer_extension_test.dart',
           'semicolon expected']));
     }
-
   },
 ];
 
-main(args) async => runIsolateTests(args, tests, testeeConcurrent:test);
+main(args) async => runIsolateTests(args, tests, testeeConcurrent:test,
+                                    trace_compiler: true);
diff --git a/runtime/observatory/tests/service/file_service_test.dart b/runtime/observatory/tests/service/file_service_test.dart
index 22b5827..25500c6 100644
--- a/runtime/observatory/tests/service/file_service_test.dart
+++ b/runtime/observatory/tests/service/file_service_test.dart
@@ -64,20 +64,21 @@
     var result = JSON.encode({'type' : 'foobar'});
     return new Future.value(new ServiceExtensionResponse.result(result));
   }
-  registerExtension('__cleanup', cleanup);
-  registerExtension('__setup', setup);
+  registerExtension('ext.dart.io.cleanup', cleanup);
+  registerExtension('ext.dart.io.setup', setup);
 }
 
 var fileTests = [
   (Isolate isolate) async {
-    await isolate.invokeRpcNoUpgrade('__setup', {});
+    await isolate.invokeRpcNoUpgrade('ext.dart.io.setup', {});
     try {
-      var result = await isolate.invokeRpcNoUpgrade('__getOpenFiles', {});
+      var result =
+          await isolate.invokeRpcNoUpgrade('ext.dart.io.getOpenFiles', {});
       expect(result['type'], equals('_openfiles'));
 
       expect(result['data'].length, equals(2));
       var writing = await isolate.invokeRpcNoUpgrade(
-           '__getFileByID', { 'id' : result['data'][0]['id'] });
+           'ext.dart.io.getFileByID', { 'id' : result['data'][0]['id'] });
 
       expect(writing['totalRead'], equals(0));
       expect(writing['readCount'], equals(0));
@@ -87,7 +88,7 @@
       expect(writing['lastRead'], equals(0));
 
       var reading = await isolate.invokeRpcNoUpgrade(
-          '__getFileByID', { 'id' : result['data'][1]['id'] });
+          'ext.dart.io.getFileByID', { 'id' : result['data'][1]['id'] });
 
       expect(reading['totalRead'], equals(5));
       expect(reading['readCount'], equals(5));
@@ -97,7 +98,7 @@
       expect(reading['lastRead'], greaterThan(0));
 
     } finally {
-      await isolate.invokeRpcNoUpgrade('__cleanup', {});
+      await isolate.invokeRpcNoUpgrade('ext.dart.io.cleanup', {});
     }
   },
 ];
diff --git a/runtime/observatory/tests/service/get_object_rpc_test.dart b/runtime/observatory/tests/service/get_object_rpc_test.dart
index 2fc74f4..a98c535 100644
--- a/runtime/observatory/tests/service/get_object_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_object_rpc_test.dart
@@ -448,7 +448,7 @@
     expect(result['offset'], isNull);
     expect(result['count'], isNull);
     expect(result['bytes'], equals('AwIB'));
-    var bytes = BASE64.decode(result['bytes']);
+    Uint8List bytes = BASE64.decode(result['bytes']);
     expect(bytes.buffer.asUint8List().toString(), equals('[3, 2, 1]'));
   },
 
@@ -474,7 +474,7 @@
     expect(result['offset'], isNull);
     expect(result['count'], equals(2));
     expect(result['bytes'], equals('AwI='));
-    var bytes = BASE64.decode(result['bytes']);
+    Uint8List bytes = BASE64.decode(result['bytes']);
     expect(bytes.buffer.asUint8List().toString(), equals('[3, 2]'));
   },
 
@@ -501,7 +501,7 @@
     expect(result['offset'], equals(2));
     expect(result['count'], equals(1));
     expect(result['bytes'], equals('AQ=='));
-    var bytes = BASE64.decode(result['bytes']);
+    Uint8List bytes = BASE64.decode(result['bytes']);
     expect(bytes.buffer.asUint8List().toString(), equals('[1]'));
   },
 
@@ -551,7 +551,7 @@
     expect(result['offset'], isNull);
     expect(result['count'], isNull);
     expect(result['bytes'], equals('AwAAAAAAAAACAAAAAAAAAAEAAAAAAAAA'));
-    var bytes = BASE64.decode(result['bytes']);
+    Uint8List bytes = BASE64.decode(result['bytes']);
     expect(bytes.buffer.asUint64List().toString(), equals('[3, 2, 1]'));
   },
 
@@ -577,7 +577,7 @@
     expect(result['offset'], isNull);
     expect(result['count'], equals(2));
     expect(result['bytes'], equals('AwAAAAAAAAACAAAAAAAAAA=='));
-    var bytes = BASE64.decode(result['bytes']);
+    Uint8List bytes = BASE64.decode(result['bytes']);
     expect(bytes.buffer.asUint64List().toString(), equals('[3, 2]'));
   },
 
@@ -604,7 +604,7 @@
     expect(result['offset'], equals(2));
     expect(result['count'], equals(1));
     expect(result['bytes'], equals('AQAAAAAAAAA='));
-    var bytes = BASE64.decode(result['bytes']);
+    Uint8List bytes = BASE64.decode(result['bytes']);
     expect(bytes.buffer.asUint64List().toString(), equals('[1]'));
   },
 
diff --git a/runtime/observatory/tests/service/process_service_test.dart b/runtime/observatory/tests/service/process_service_test.dart
index 956cc77..ee529c9 100644
--- a/runtime/observatory/tests/service/process_service_test.dart
+++ b/runtime/observatory/tests/service/process_service_test.dart
@@ -73,31 +73,32 @@
     return  process3.exitCode.then((int exit) => returnValue);
   }
 
-  registerExtension('__cleanup', cleanup);
-  registerExtension('__setup', setup);
-  registerExtension('__closeStdin', closeStdin);
+  registerExtension('ext.dart.io.cleanup', cleanup);
+  registerExtension('ext.dart.io.setup', setup);
+  registerExtension('ext.dart.io.closeStdin', closeStdin);
 
 }
 
 var processTests = [
   // Initial.
   (Isolate isolate) async {
-    var setup = await isolate.invokeRpcNoUpgrade('__setup', {});
+    var setup = await isolate.invokeRpcNoUpgrade('ext.dart.io.setup', {});
     try {
-      var all = await isolate.invokeRpcNoUpgrade('__getProcesses', {});
+      var all =
+          await isolate.invokeRpcNoUpgrade('ext.dart.io.getProcesses', {});
       expect(all['type'], equals('_startedprocesses'));
 
       expect(all['data'].length, equals(3));
 
       var first = await isolate.invokeRpcNoUpgrade(
-          '__getProcessById', { 'id' : all['data'][0]['id'] });
+          'ext.dart.io.getProcessById', { 'id' : all['data'][0]['id'] });
       expect(first['name'], io.Platform.executable);
       expect(first['pid'], equals(setup['pids'][0]));
       expect(first['arguments'].contains('foobar'), isFalse);
       expect(first['startedAt'], greaterThan(0));
 
       var second = await isolate.invokeRpcNoUpgrade(
-          '__getProcessById', { 'id' : all['data'][1]['id'] });
+          'ext.dart.io.getProcessById', { 'id' : all['data'][1]['id'] });
       expect(second['name'], io.Platform.executable);
       expect(second['pid'], equals(setup['pids'][1]));
       expect(second['arguments'].contains('foobar'), isTrue);
@@ -106,19 +107,19 @@
       expect(second['startedAt'], greaterThanOrEqualTo(first['startedAt']));
 
       var third = await isolate.invokeRpcNoUpgrade(
-          '__getProcessById', { 'id' : all['data'][2]['id'] });
+          'ext.dart.io.getProcessById', { 'id' : all['data'][2]['id'] });
       expect(third['name'], io.Platform.executable);
       expect(third['pid'], equals(setup['pids'][2]));
       expect(third['pid'] != first['pid'], isTrue);
       expect(third['pid'] != second['pid'], isTrue);
       expect(third['startedAt'], greaterThanOrEqualTo(second['startedAt']));
 
-      await isolate.invokeRpcNoUpgrade('__closeStdin', {});
-      all = await isolate.invokeRpcNoUpgrade('__getProcesses', {});
+      await isolate.invokeRpcNoUpgrade('ext.dart.io.closeStdin', {});
+      all = await isolate.invokeRpcNoUpgrade('ext.dart.io.getProcesses', {});
       expect(all['type'], equals('_startedprocesses'));
       expect(all['data'].length, equals(2));
     } finally {
-      await isolate.invokeRpcNoUpgrade('__cleanup', {});
+      await isolate.invokeRpcNoUpgrade('ext.dart.io.cleanup', {});
     }
   },
 ];
diff --git a/runtime/observatory/tests/service/smart_next_test.dart b/runtime/observatory/tests/service/smart_next_test.dart
index aeb819f..34bac34 100644
--- a/runtime/observatory/tests/service/smart_next_test.dart
+++ b/runtime/observatory/tests/service/smart_next_test.dart
@@ -47,7 +47,8 @@
 smartNext(Isolate isolate) async {
   if (isolate.pauseEvent.atAsyncJump) {
     print("next-async");
-    return isolate.asyncStepOver()[Isolate.kSecondResume];
+    List asyncStepFutures = await isolate.asyncStepOver();
+    return asyncStepFutures[Isolate.kSecondResume];
   } else {
     print("next-sync");
     return stepOverAwaitingResume(isolate);
diff --git a/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart b/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart
index 20a9b76..38e415b 100644
--- a/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart
+++ b/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart
@@ -54,13 +54,14 @@
 var tests = [
   // Initial.
   (Isolate isolate) async {
-    var result = await isolate.invokeRpcNoUpgrade('__getOpenSockets', {});
+    var result =
+        await isolate.invokeRpcNoUpgrade('ext.dart.io.getOpenSockets', {});
     expect(result['type'], equals('_opensockets'));
     // We expect only one socket to be open, the server socket create at the
     // end of test.
     expect(result['data'].length, equals(1));
     var server = await isolate.invokeRpcNoUpgrade(
-        '__getSocketByID', { 'id' : result['data'][0]['id'] });
+        'ext.dart.io.getSocketByID', { 'id' : result['data'][0]['id'] });
     expect(server['listening'], isTrue);
     expect(server['lastRead'], equals(0));
     expect(server['totalRead'], equals(0));
diff --git a/runtime/observatory/tests/service/tcp_socket_service_test.dart b/runtime/observatory/tests/service/tcp_socket_service_test.dart
index c80cad5..646b5f6 100644
--- a/runtime/observatory/tests/service/tcp_socket_service_test.dart
+++ b/runtime/observatory/tests/service/tcp_socket_service_test.dart
@@ -30,7 +30,8 @@
 var tcpTests = [
   // Initial.
   (Isolate isolate) async {
-    var result = await isolate.invokeRpcNoUpgrade('__getOpenSockets', {});
+    var result =
+            await isolate.invokeRpcNoUpgrade('ext.dart.io.getOpenSockets', {});
     expect(result['type'], equals('_opensockets'));
     // We expect 3 sockets to be open (in this order):
     //   The server socket accepting connections, on port X
@@ -48,7 +49,7 @@
     expect(result['data'][2]['name'].startsWith('127.0.0.1:'), isTrue);
 
     var listening = await isolate.invokeRpcNoUpgrade(
-        '__getSocketByID', { 'id' : result['data'][0]['id'] });
+        'ext.dart.io.getSocketByID', { 'id' : result['data'][0]['id'] });
     expect(listening['id'], equals(result['data'][0]['id']));
     expect(listening['listening'], isTrue);
     expect(listening['socketType'], equals('TCP'));
@@ -64,11 +65,11 @@
     expect(listening['remotePort'], equals('NA'));
 
     var client = await isolate.invokeRpcNoUpgrade(
-        '__getSocketByID', { 'id' : result['data'][1]['id'] });
+        'ext.dart.io.getSocketByID', { 'id' : result['data'][1]['id'] });
     expect(client['id'], equals(result['data'][1]['id']));
 
     var server = await isolate.invokeRpcNoUpgrade(
-        '__getSocketByID', { 'id' : result['data'][2]['id'] });
+        'ext.dart.io.getSocketByID', { 'id' : result['data'][2]['id'] });
     expect(server['id'], equals(result['data'][2]['id']));
 
     // We expect the client to be connected on the port and
@@ -115,10 +116,10 @@
     }
 
     var secondClient = await isolate.invokeRpcNoUpgrade(
-        '__getSocketByID', { 'id' : result['data'][3]['id'] });
+        'ext.dart.io.getSocketByID', { 'id' : result['data'][3]['id'] });
     expect(secondClient['id'], equals(result['data'][3]['id']));
     var secondServer = await isolate.invokeRpcNoUpgrade(
-        '__getSocketByID', { 'id' : result['data'][4]['id'] });
+        'ext.dart.io.getSocketByID', { 'id' : result['data'][4]['id'] });
     expect(secondServer['id'], equals(result['data'][4]['id']));
 
     // We expect the client to be connected on the port and
diff --git a/runtime/observatory/tests/service/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart
index 1adcd66..1920369 100644
--- a/runtime/observatory/tests/service/test_helper.dart
+++ b/runtime/observatory/tests/service/test_helper.dart
@@ -29,7 +29,8 @@
   Future<int> launch(bool pause_on_start,
                      bool pause_on_exit,
                      bool pause_on_unhandled_exceptions,
-                     bool trace_service) {
+                     bool trace_service,
+                     bool trace_compiler) {
     assert(pause_on_start != null);
     assert(pause_on_exit != null);
     assert(trace_service != null);
@@ -40,6 +41,10 @@
     var fullArgs = [];
     if (trace_service) {
       fullArgs.add('--trace-service');
+      fullArgs.add('--trace-service-verbose');
+    }
+    if (trace_compiler) {
+      fullArgs.add('--trace-compiler');
     }
     if (pause_on_start) {
       fullArgs.add('--pause-isolates-on-start');
@@ -119,6 +124,7 @@
                         bool pause_on_start: false,
                         bool pause_on_exit: false,
                         bool trace_service: false,
+                        bool trace_compiler: false,
                         bool verbose_vm: false,
                         bool pause_on_unhandled_exceptions: false}) async {
   assert(!pause_on_start || testeeBefore == null);
@@ -142,7 +148,8 @@
   } else {
     var process = new _TestLauncher();
     process.launch(pause_on_start, pause_on_exit,
-                   pause_on_unhandled_exceptions, trace_service).then((port) {
+                   pause_on_unhandled_exceptions,
+                   trace_service, trace_compiler).then((port) {
       if (mainArgs.contains("--gdb")) {
         port = 8181;
       }
@@ -190,6 +197,7 @@
                                  bool pause_on_start: false,
                                  bool pause_on_exit: false,
                                  bool trace_service: false,
+                                 bool trace_compiler: false,
                                  bool verbose_vm: false,
                                  bool pause_on_unhandled_exceptions: false}) {
   assert(!pause_on_start || testeeBefore == null);
@@ -210,7 +218,8 @@
   } else {
     var process = new _TestLauncher();
     process.launch(pause_on_start, pause_on_exit,
-                   pause_on_unhandled_exceptions, trace_service).then((port) {
+                   pause_on_unhandled_exceptions,
+                   trace_service, trace_compiler).then((port) {
       if (mainArgs.contains("--gdb")) {
         port = 8181;
       }
@@ -400,6 +409,7 @@
                    bool pause_on_start: false,
                    bool pause_on_exit: false,
                    bool trace_service: false,
+                   bool trace_compiler: false,
                    bool verbose_vm: false,
                    bool pause_on_unhandled_exceptions: false}) async {
   if (mainArgs.contains(_TESTEE_MODE_FLAG)) {
@@ -421,7 +431,7 @@
     process.launch(pause_on_start,
                    pause_on_exit,
                    pause_on_unhandled_exceptions,
-                   trace_service).then((port) async {
+                   trace_service, trace_compiler).then((port) async {
       if (mainArgs.contains("--gdb")) {
         port = 8181;
       }
diff --git a/runtime/observatory/tests/service/udp_socket_service_test.dart b/runtime/observatory/tests/service/udp_socket_service_test.dart
index 49ff5e4..6a6a0e0 100644
--- a/runtime/observatory/tests/service/udp_socket_service_test.dart
+++ b/runtime/observatory/tests/service/udp_socket_service_test.dart
@@ -25,7 +25,8 @@
 var udpTests = [
   // Initial.
   (Isolate isolate) async {
-    var result = await isolate.invokeRpcNoUpgrade('__getOpenSockets', {});
+    var result =
+        await isolate.invokeRpcNoUpgrade('ext.dart.io.getOpenSockets', {});
     expect(result['type'], equals('_opensockets'));
     // We expect 2 sockets to be open (in this order):
     //   The server socket accepting connections, on port X
@@ -38,7 +39,7 @@
     expect(result['data'][1]['name'].startsWith('127.0.0.1:'), isTrue);
 
     var server = await isolate.invokeRpcNoUpgrade(
-        '__getSocketByID', { 'id' : result['data'][0]['id'] });
+        'ext.dart.io.getSocketByID', { 'id' : result['data'][0]['id'] });
     expect(server['id'], equals(result['data'][0]['id']));
     expect(server['remotePort'], equals('NA'));
     expect(server['remoteHost'], equals('NA'));
@@ -58,7 +59,7 @@
     expect(server['readCount'], greaterThanOrEqualTo(1));
 
     var client = await isolate.invokeRpcNoUpgrade(
-        '__getSocketByID', { 'id' : result['data'][1]['id'] });
+        'ext.dart.io.getSocketByID', { 'id' : result['data'][1]['id'] });
     expect(client['id'], equals(result['data'][1]['id']));
     expect(client['remotePort'], equals('NA'));
     expect(client['remoteHost'], equals('NA'));
diff --git a/runtime/observatory/tests/service/vm_timeline_flags_test.dart b/runtime/observatory/tests/service/vm_timeline_flags_test.dart
new file mode 100644
index 0000000..6e8994e
--- /dev/null
+++ b/runtime/observatory/tests/service/vm_timeline_flags_test.dart
@@ -0,0 +1,112 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--error_on_bad_type --error_on_bad_override
+
+import 'dart:developer';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+
+import 'test_helper.dart';
+
+primeDartTimeline() {
+  while (true) {
+    Timeline.startSync('apple');
+    Timeline.finishSync();
+    debugger();
+  }
+}
+
+bool isDart(Map event) => event['cat'] == 'Dart';
+bool isMetaData(Map event) => event['ph'] == 'M';
+bool isNotMetaData(Map event) => !isMetaData(event);
+bool isNotDartAndMetaData(Map event) => !isDart(event) && !isMetaData(event);
+
+List<Map> filterEvents(List<Map> events, filter) {
+  return events.where(filter).toList();
+}
+
+int dartEventCount;
+
+var tests = [
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Get the flags.
+    Map flags = await isolate.vm.invokeRpcNoUpgrade('_getVMTimelineFlags', {});
+    expect(flags['type'], 'TimelineFlags');
+    // Confirm that 'Dart' is available.
+    expect(flags['availableStreams'].contains('Dart'), isTrue);
+    // Confirm that nothing is being recorded.
+    expect(flags['recordedStreams'].length, equals(0));
+  },
+  (Isolate isolate) async {
+    // Get the timeline.
+    Map result = await isolate.vm.invokeRpcNoUpgrade('_getVMTimeline', {});
+    expect(result['type'], equals('_Timeline'));
+    expect(result['traceEvents'], new isInstanceOf<List>());
+    // Confirm that it as no non-meta data events.
+    expect(filterEvents(result['traceEvents'], isNotMetaData).length, 0);
+  },
+  (Isolate isolate) async {
+    // Enable the Dart category.
+    await isolate.vm.invokeRpcNoUpgrade('_setVMTimelineFlags', {
+      "recordedStreams": ["Dart"]
+    });
+  },
+  (Isolate isolate) async {
+    // Get the flags.
+    Map flags = await isolate.vm.invokeRpcNoUpgrade('_getVMTimelineFlags', {});
+    expect(flags['type'], 'TimelineFlags');
+    // Confirm that only Dart is being recorded.
+    expect(flags['recordedStreams'].length, equals(1));
+    expect(flags['recordedStreams'].contains('Dart'), isTrue);
+  },
+  resumeIsolate,
+  (Isolate isolate) async {
+    // Get the timeline.
+    Map result = await isolate.vm.invokeRpcNoUpgrade('_getVMTimeline', {});
+    expect(result['type'], equals('_Timeline'));
+    expect(result['traceEvents'], new isInstanceOf<List>());
+    // Confirm that Dart events are added.
+    expect(filterEvents(result['traceEvents'], isDart).length, greaterThan(0));
+    // Confirm that zero non-Dart events are added.
+    expect(
+        filterEvents(result['traceEvents'], isNotDartAndMetaData).length,
+        equals(0));
+  },
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Disable the Dart category.
+    await isolate.vm.invokeRpcNoUpgrade('_setVMTimelineFlags', {
+      "recordedStreams": []
+    });
+    // Grab the timeline and remember the number of Dart events.
+    Map result = await isolate.vm.invokeRpcNoUpgrade('_getVMTimeline', {});
+    expect(result['type'], equals('_Timeline'));
+    expect(result['traceEvents'], new isInstanceOf<List>());
+    dartEventCount = filterEvents(result['traceEvents'], isDart).length;
+  },
+  (Isolate isolate) async {
+    // Get the flags.
+    Map flags = await isolate.vm.invokeRpcNoUpgrade('_getVMTimelineFlags', {});
+    expect(flags['type'], 'TimelineFlags');
+    // Confirm that 'Dart' is not being recorded.
+    expect(flags['recordedStreams'].length, equals(0));
+  },
+  resumeIsolate,
+  (Isolate isolate) async {
+    // Grab the timeline and verify that we haven't added any new Dart events.
+    Map result = await isolate.vm.invokeRpcNoUpgrade('_getVMTimeline', {});
+    expect(result['type'], equals('_Timeline'));
+    expect(result['traceEvents'], new isInstanceOf<List>());
+    expect(filterEvents(result['traceEvents'], isDart).length, dartEventCount);
+    // Confirm that zero non-Dart events are added.
+    expect(
+        filterEvents(result['traceEvents'], isNotDartAndMetaData).length,
+        equals(0));
+  },
+];
+
+main(args) async => runIsolateTests(args,
+                                    tests,
+                                    testeeConcurrent: primeDartTimeline);
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index f626ee9..e8a5074 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -20,6 +20,8 @@
 
 namespace dart {
 
+DECLARE_FLAG(bool, background_compilation);
+
 Benchmark* Benchmark::first_ = NULL;
 Benchmark* Benchmark::tail_ = NULL;
 const char* Benchmark::executable_ = NULL;
@@ -338,7 +340,10 @@
   }
   Timer timer(true, "Compile all of dart2js benchmark");
   timer.Start();
+  const bool old_flag = FLAG_background_compilation;
+  FLAG_background_compilation = false;
   Dart_Handle result = Dart_CompileAll();
+  FLAG_background_compilation = old_flag;
   EXPECT_VALID(result);
   timer.Stop();
   int64_t elapsed_time = timer.TotalElapsedTime();
@@ -373,7 +378,10 @@
   stats->EnableBenchmark();
   Timer timer(true, "Compile all of dart2js benchmark");
   timer.Start();
+  const bool old_flag = FLAG_background_compilation;
+  FLAG_background_compilation = false;
   Dart_Handle result = Dart_CompileAll();
+  FLAG_background_compilation = old_flag;
   EXPECT_VALID(result);
   timer.Stop();
   int64_t elapsed_time = timer.TotalElapsedTime();
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index c9105ae..3296bcc 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -144,6 +144,7 @@
 
 
 void ClassTable::RegisterAt(intptr_t index, const Class& cls) {
+  ASSERT(Thread::Current()->IsMutatorThread());
   ASSERT(index != kIllegalCid);
   ASSERT(index >= kNumPredefinedCids);
   if (index >= capacity_) {
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index bf7508a..4f5b2a1 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -40,6 +40,10 @@
 DEFINE_FLAG(int, regexp_optimization_counter_threshold, 1000,
     "RegExp's usage-counter value before it is optimized, -1 means never");
 DEFINE_FLAG(charp, optimization_filter, NULL, "Optimize only named function");
+// TODO(srdjan): Remove this flag once background compilation of regular
+// expressions is possible.
+DEFINE_FLAG(bool, regexp_opt_in_background, false,
+    "Optimize reg-exp functions in background");
 DEFINE_FLAG(int, reoptimization_counter_threshold, 4000,
     "Counter threshold before a function gets reoptimized.");
 DEFINE_FLAG(bool, stop_on_excessive_deoptimization, false,
@@ -61,8 +65,9 @@
 DECLARE_FLAG(int, max_deoptimization_counter_threshold);
 DECLARE_FLAG(bool, enable_inlining_annotations);
 DECLARE_FLAG(bool, trace_compiler);
+DECLARE_FLAG(bool, trace_field_guards);
+DECLARE_FLAG(bool, trace_optimization);
 DECLARE_FLAG(bool, trace_optimizing_compiler);
-DECLARE_FLAG(bool, warn_on_javascript_compatibility);
 DECLARE_FLAG(int, max_polymorphic_checks);
 DECLARE_FLAG(bool, precompilation);
 
@@ -318,7 +323,8 @@
     // Instantiate type before printing.
     Error& bound_error = Error::Handle();
     const AbstractType& instantiated_type = AbstractType::Handle(
-        type.InstantiateFrom(instantiator_type_arguments, &bound_error));
+        type.InstantiateFrom(instantiator_type_arguments, &bound_error,
+                             NULL, NULL, Heap::kOld));
     OS::PrintErr("%s: '%s' %s '%s' instantiated from '%s' (pc: %#" Px ").\n",
                  message,
                  String::Handle(instance_type.Name()).ToCString(),
@@ -418,7 +424,8 @@
     if (!test_type.IsInstantiated()) {
       Error& bound_error = Error::Handle();
       test_type = type.InstantiateFrom(instantiator_type_arguments,
-                                       &bound_error);
+                                       &bound_error,
+                                       NULL, NULL, Heap::kNew);
       ASSERT(bound_error.IsNull());  // Malbounded types are not optimized.
     }
     OS::PrintErr("  Updated test cache %p ix: %" Pd " with "
@@ -533,7 +540,8 @@
     if (!dst_type.IsInstantiated()) {
       // Instantiate dst_type before reporting the error.
       const AbstractType& instantiated_dst_type = AbstractType::Handle(
-          dst_type.InstantiateFrom(instantiator_type_arguments, NULL));
+          dst_type.InstantiateFrom(instantiator_type_arguments, NULL,
+                                   NULL, NULL, Heap::kNew));
       // Note that instantiated_dst_type may be malbounded.
       dst_type_name = instantiated_dst_type.UserVisibleName();
       dst_type_lib =
@@ -885,18 +893,6 @@
   const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
   GrowableArray<const Instance*> args(1);
   args.Add(&receiver);
-  if (FLAG_warn_on_javascript_compatibility) {
-    if (receiver.IsDouble() &&
-        String::Handle(ic_data.target_name()).Equals(Symbols::toString())) {
-      const double value = Double::Cast(receiver).value();
-      if (floor(value) == value) {
-        Report::JSWarningFromIC(ic_data,
-                                "string representation of an integral value "
-                                "of type 'double' has no decimal mark and "
-                                "no fractional part");
-      }
-    }
-  }
   const Function& result =
       Function::Handle(InlineCacheMissHandler(args, ic_data));
   arguments.SetReturn(result);
@@ -1491,6 +1487,20 @@
 
   if (CanOptimizeFunction(function, thread)) {
     if (FLAG_background_compilation) {
+      Field& field = Field::Handle(zone, isolate->GetDeoptimizingBoxedField());
+      while (!field.IsNull()) {
+        if (FLAG_trace_optimization || FLAG_trace_field_guards) {
+          THR_Print("Lazy disabling unboxing of %s\n", field.ToCString());
+        }
+        field.set_is_unboxing_candidate(false);
+        field.DeoptimizeDependentCode();
+        // Get next field.
+        field = isolate->GetDeoptimizingBoxedField();
+      }
+    }
+    // TODO(srdjan): Fix background compilation of regular expressions.
+    if (FLAG_background_compilation &&
+        (!function.IsIrregexpFunction() || FLAG_regexp_opt_in_background)) {
       if (FLAG_enable_inlining_annotations) {
         FATAL("Cannot enable inlining annotations and background compilation");
       }
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 5b67de0..4d88bae 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -25,6 +25,7 @@
 #include "vm/flow_graph_compiler.h"
 #include "vm/flow_graph_inliner.h"
 #include "vm/flow_graph_optimizer.h"
+#include "vm/flow_graph_range_analysis.h"
 #include "vm/flow_graph_type_propagator.h"
 #include "vm/il_printer.h"
 #include "vm/longjump.h"
@@ -518,18 +519,8 @@
     }
 
     // Register code with the classes it depends on because of CHA and
-    // fields it depends on because of store guards.
-    // 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();
-    }
+    // fields it depends on because of store guards, unless we cannot
+    // deopt.
     for (intptr_t i = 0;
          i < thread()->cha()->leaf_classes().length();
          ++i) {
@@ -584,7 +575,7 @@
   // longjmp from the ARM or MIPS assemblers. In all other paths through this
   // while loop, done is set to true. use_far_branches is always false on ia32
   // and x64.
-  bool done = false;
+  volatile bool done = false;
   // volatile because the variable may be clobbered by a longjmp.
   volatile bool use_far_branches = false;
   const bool use_speculative_inlining = false;
@@ -615,8 +606,8 @@
 
           // 'Freeze' ICData in background compilation so that it does not
           // change while compiling.
-          const bool clone_descriptors = Compiler::IsBackgroundCompilation();
-          function.RestoreICDataMap(ic_data_array, clone_descriptors);
+          const bool clone_ic_data = Compiler::IsBackgroundCompilation();
+          function.RestoreICDataMap(ic_data_array, clone_ic_data);
 
           if (Compiler::IsBackgroundCompilation() &&
               (function.ic_data_array() == Array::null())) {
@@ -895,7 +886,8 @@
           // We have to perform range analysis after LICM because it
           // optimistically moves CheckSmi through phis into loop preheaders
           // making some phis smi.
-          optimizer.InferIntRanges();
+          RangeAnalysis range_analysis(flow_graph);
+          range_analysis.Analyze();
           DEBUG_ASSERT(flow_graph->VerifyUseLists());
         }
 
@@ -1325,8 +1317,11 @@
 
   // Optimization must happen in non-mutator/Dart thread if background
   // compilation is on. OSR compilation still occurs in the main thread.
+  // TODO(Srdjan): Remove assert allowance for regular expression functions
+  // once they can be compiled in background.
   ASSERT((osr_id != kNoOSRDeoptId) || !FLAG_background_compilation ||
-         !thread->IsMutatorThread());
+         !thread->IsMutatorThread() ||
+         function.IsIrregexpFunction());
   CompilationPipeline* pipeline =
       CompilationPipeline::New(thread->zone(), function);
   return CompileFunctionHelper(pipeline,
@@ -1531,6 +1526,9 @@
 
 
 void Compiler::AbortBackgroundCompilation(intptr_t deopt_id) {
+  if (FLAG_trace_compiler) {
+    THR_Print("ABORT background compilation.");
+  }
   ASSERT(Compiler::IsBackgroundCompilation());
   Thread::Current()->long_jump_base()->Jump(
       deopt_id, Object::background_compilation_error());
diff --git a/runtime/vm/coverage.cc b/runtime/vm/coverage.cc
index 8ce260b..2e85c3d 100644
--- a/runtime/vm/coverage.cc
+++ b/runtime/vm/coverage.cc
@@ -89,7 +89,7 @@
   // Print the hit counts for all IC datas.
   ZoneGrowableArray<const ICData*>* ic_data_array =
       new(zone) ZoneGrowableArray<const ICData*>();
-  function.RestoreICDataMap(ic_data_array, false /* clone descriptors */);
+  function.RestoreICDataMap(ic_data_array, false /* clone ic-data */);
   const PcDescriptors& descriptors = PcDescriptors::Handle(
       zone, code.pc_descriptors());
 
diff --git a/runtime/vm/cpuid.h b/runtime/vm/cpuid.h
index b9d193a..b33812e 100644
--- a/runtime/vm/cpuid.h
+++ b/runtime/vm/cpuid.h
@@ -26,14 +26,14 @@
   static const char* field(CpuInfoIndices idx) { return NULL; }
 #endif
 
-  static bool sse2() { return sse2_; }
-  static bool sse41() { return sse41_; }
-
+ private:
   // Caller must free the result of id_string and brand_string.
   static const char* id_string();
   static const char* brand_string();
 
- private:
+  static bool sse2() { return sse2_; }
+  static bool sse41() { return sse41_; }
+
   static bool sse2_;
   static bool sse41_;
   static const char* id_string_;
diff --git a/runtime/vm/cpuinfo.h b/runtime/vm/cpuinfo.h
index cd1247e..95b6ec3 100644
--- a/runtime/vm/cpuinfo.h
+++ b/runtime/vm/cpuinfo.h
@@ -45,16 +45,10 @@
 
   // Returns true if the cpuinfo field contains the string.
   static bool FieldContains(CpuInfoIndices idx, const char* search_string);
-  static bool FieldContainsByString(
-      const char* field, const char* search_string);
 
   // Returns true if the cpuinfo field [field] exists and is non-empty.
   static bool HasField(const char* field);
 
-  // Returns the field. Caller is responsible for freeing the result.
-  static const char* ExtractField(CpuInfoIndices idx);
-  static const char* ExtractFieldByString(const char* field);
-
   // Returns the field describing the CPU model. Caller is responsible for
   // freeing the result.
   static const char* GetCpuModel() {
@@ -66,6 +60,9 @@
   }
 
  private:
+  // Returns the field. Caller is responsible for freeing the result.
+  static const char* ExtractField(CpuInfoIndices idx);
+
   // The method to use to acquire info about the CPU.
   static CpuInfoMethod method_;
 
diff --git a/runtime/vm/cpuinfo_android.cc b/runtime/vm/cpuinfo_android.cc
index e4e4826..1e4229c 100644
--- a/runtime/vm/cpuinfo_android.cc
+++ b/runtime/vm/cpuinfo_android.cc
@@ -52,25 +52,12 @@
 }
 
 
-bool CpuInfo::FieldContainsByString(const char* field,
-                                    const char* search_string) {
-  ASSERT(method_ != kCpuInfoDefault);
-  return ProcCpuInfo::FieldContains(field, search_string);
-}
-
-
 const char* CpuInfo::ExtractField(CpuInfoIndices idx) {
   ASSERT(method_ != kCpuInfoDefault);
   return ProcCpuInfo::ExtractField(FieldName(idx));
 }
 
 
-const char* CpuInfo::ExtractFieldByString(const char* field) {
-  ASSERT(method_ != kCpuInfoDefault);
-  return ProcCpuInfo::ExtractField(field);
-}
-
-
 bool CpuInfo::HasField(const char* field) {
   ASSERT(method_ != kCpuInfoDefault);
   return ProcCpuInfo::HasField(field);
diff --git a/runtime/vm/cpuinfo_linux.cc b/runtime/vm/cpuinfo_linux.cc
index e58bac1..8d76233 100644
--- a/runtime/vm/cpuinfo_linux.cc
+++ b/runtime/vm/cpuinfo_linux.cc
@@ -67,7 +67,10 @@
 
 bool CpuInfo::FieldContains(CpuInfoIndices idx, const char* search_string) {
   if (method_ == kCpuInfoCpuId) {
-    return strstr(CpuId::field(idx), search_string);
+    const char* field = CpuId::field(idx);
+    bool contains = (strstr(field, search_string) != NULL);
+    free(const_cast<char*>(field));
+    return contains;
   } else {
     ASSERT(method_ == kCpuInfoSystem);
     return ProcCpuInfo::FieldContains(FieldName(idx), search_string);
@@ -75,23 +78,6 @@
 }
 
 
-bool CpuInfo::FieldContainsByString(const char* field,
-                                    const char* search_string) {
-  if (method_ == kCpuInfoCpuId) {
-    for (int i = 0; i < kCpuInfoMax; i++) {
-      if (strcmp(field, fields_[i]) == 0) {
-        return FieldContains(static_cast<CpuInfoIndices>(i), search_string);
-      }
-    }
-    UNIMPLEMENTED();
-    return false;
-  } else {
-    ASSERT(method_ == kCpuInfoSystem);
-    return ProcCpuInfo::FieldContains(field, search_string);
-  }
-}
-
-
 const char* CpuInfo::ExtractField(CpuInfoIndices idx) {
   if (method_ == kCpuInfoCpuId) {
     return CpuId::field(idx);
@@ -102,22 +88,6 @@
 }
 
 
-const char* CpuInfo::ExtractFieldByString(const char* field) {
-  if (method_ == kCpuInfoCpuId) {
-    for (int i = 0; i < kCpuInfoMax; i++) {
-      if (strcmp(field, fields_[i]) == 0) {
-        return ExtractField(static_cast<CpuInfoIndices>(i));
-      }
-    }
-    UNIMPLEMENTED();
-    return NULL;
-  } else {
-    ASSERT(method_ == kCpuInfoSystem);
-    return ProcCpuInfo::ExtractField(field);
-  }
-}
-
-
 bool CpuInfo::HasField(const char* field) {
   if (method_ == kCpuInfoCpuId) {
     return (strcmp(field, fields_[kCpuInfoProcessor]) == 0) ||
diff --git a/runtime/vm/cpuinfo_macos.cc b/runtime/vm/cpuinfo_macos.cc
index 6352391..eef06d9 100644
--- a/runtime/vm/cpuinfo_macos.cc
+++ b/runtime/vm/cpuinfo_macos.cc
@@ -31,10 +31,10 @@
 void CpuInfo::Cleanup() {}
 
 
-bool CpuInfo::FieldContainsByString(const char* field,
-                                    const char* search_string) {
+bool CpuInfo::FieldContains(CpuInfoIndices idx, const char* search_string) {
   ASSERT(method_ != kCpuInfoDefault);
   ASSERT(search_string != NULL);
+  const char* field = FieldName(idx);
   char dest[1024];
   size_t dest_len = 1024;
 
@@ -48,14 +48,9 @@
 }
 
 
-bool CpuInfo::FieldContains(CpuInfoIndices idx, const char* search_string) {
+const char* CpuInfo::ExtractField(CpuInfoIndices idx) {
   ASSERT(method_ != kCpuInfoDefault);
-  return FieldContainsByString(FieldName(idx), search_string);
-}
-
-
-const char* CpuInfo::ExtractFieldByString(const char* field) {
-  ASSERT(method_ != kCpuInfoDefault);
+  const char* field = FieldName(idx);
   ASSERT(field != NULL);
   size_t result_len;
 
@@ -65,7 +60,7 @@
     return 0;
   }
 
-  char* result = new char[result_len];
+  char* result = reinterpret_cast<char*>(malloc(result_len));
   if (sysctlbyname(field, result, &result_len, NULL, 0) != 0) {
     UNREACHABLE();
     return 0;
@@ -75,12 +70,6 @@
 }
 
 
-const char* CpuInfo::ExtractField(CpuInfoIndices idx) {
-  ASSERT(method_ != kCpuInfoDefault);
-  return ExtractFieldByString(FieldName(idx));
-}
-
-
 bool CpuInfo::HasField(const char* field) {
   ASSERT(method_ != kCpuInfoDefault);
   ASSERT(field != NULL);
diff --git a/runtime/vm/cpuinfo_test.cc b/runtime/vm/cpuinfo_test.cc
index 860c407..0b6113b 100644
--- a/runtime/vm/cpuinfo_test.cc
+++ b/runtime/vm/cpuinfo_test.cc
@@ -12,6 +12,8 @@
 UNIT_TEST_CASE(GetCpuModelTest) {
   const char* cpumodel = CpuInfo::GetCpuModel();
   EXPECT_NE(strlen(cpumodel), 0UL);
+  // caller is responsible for deleting the returned cpumodel string.
+  free(const_cast<char*>(cpumodel));
 }
 
 }  // namespace dart
diff --git a/runtime/vm/cpuinfo_win.cc b/runtime/vm/cpuinfo_win.cc
index b648566..1570af7 100644
--- a/runtime/vm/cpuinfo_win.cc
+++ b/runtime/vm/cpuinfo_win.cc
@@ -43,37 +43,12 @@
 }
 
 
-bool CpuInfo::FieldContainsByString(const char* field,
-                                    const char* search_string) {
-  ASSERT(method_ != kCpuInfoDefault);
-  for (int i = 0; i < kCpuInfoMax; i++) {
-    if (strcmp(field, fields_[i]) == 0) {
-      return FieldContains(static_cast<CpuInfoIndices>(i), search_string);
-    }
-  }
-  UNIMPLEMENTED();
-  return false;
-}
-
-
 const char* CpuInfo::ExtractField(CpuInfoIndices idx) {
   ASSERT(method_ != kCpuInfoDefault);
   return CpuId::field(idx);
 }
 
 
-const char* CpuInfo::ExtractFieldByString(const char* field) {
-  ASSERT(method_ != kCpuInfoDefault);
-  for (int i = 0; i < kCpuInfoMax; i++) {
-    if (strcmp(field, fields_[i]) == 0) {
-      return ExtractField(static_cast<CpuInfoIndices>(i));
-    }
-  }
-  UNIMPLEMENTED();
-  return NULL;
-}
-
-
 bool CpuInfo::HasField(const char* field) {
   ASSERT(method_ != kCpuInfoDefault);
   return (strcmp(field, fields_[kCpuInfoProcessor]) == 0) ||
diff --git a/runtime/vm/custom_isolate_test.cc b/runtime/vm/custom_isolate_test.cc
index 8f7796d..d720f70 100644
--- a/runtime/vm/custom_isolate_test.cc
+++ b/runtime/vm/custom_isolate_test.cc
@@ -16,6 +16,8 @@
 
 namespace dart {
 
+DECLARE_FLAG(bool, trace_shutdown);
+
 static void native_echo(Dart_NativeArguments args);
 static void CustomIsolateImpl_start(Dart_NativeArguments args);
 static Dart_NativeFunction NativeLookup(Dart_Handle name,
@@ -210,6 +212,7 @@
     OS::Print("<< Shutting down isolate(%p)\n", isolate());
     event_queue->RemoveEventsForIsolate(isolate());
     Dart_SetMessageNotifyCallback(NULL);
+    Dart_ExitScope();
     Dart_ShutdownIsolate();
   } else {
     Dart_ExitScope();
@@ -315,6 +318,8 @@
 
 
 UNIT_TEST_CASE(CustomIsolates) {
+  bool saved_flag = FLAG_trace_shutdown;
+  FLAG_trace_shutdown = true;
   FLAG_verify_handles = true;
   FLAG_verify_on_transition = true;
   event_queue = new EventQueue();
@@ -354,6 +359,7 @@
 
   delete event_queue;
   event_queue = NULL;
+  FLAG_trace_shutdown = saved_flag;
 }
 
 }  // namespace dart
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index bace9af..5e563eb 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -42,12 +42,15 @@
 DEFINE_FLAG(bool, keep_code, false,
             "Keep deoptimized code for profiling.");
 DEFINE_FLAG(bool, shutdown, true, "Do a clean shutdown of the VM");
+DEFINE_FLAG(bool, trace_shutdown, false, "Trace VM shutdown on stderr");
 
 Isolate* Dart::vm_isolate_ = NULL;
+int64_t Dart::start_time_ = 0;
 ThreadPool* Dart::thread_pool_ = NULL;
 DebugInfo* Dart::pprof_symbol_generator_ = NULL;
 ReadOnlyHandles* Dart::predefined_handles_ = NULL;
 const uint8_t* Dart::instructions_snapshot_buffer_ = NULL;
+const uint8_t* Dart::data_snapshot_buffer_ = NULL;
 
 // Structure for managing read-only global handles allocation used for
 // creating global read-only handles that are pre created and initialized
@@ -75,6 +78,7 @@
 
 const char* Dart::InitOnce(const uint8_t* vm_isolate_snapshot,
                            const uint8_t* instructions_snapshot,
+                           const uint8_t* data_snapshot,
                            Dart_IsolateCreateCallback create,
                            Dart_IsolateShutdownCallback shutdown,
                            Dart_FileOpenCallback file_open,
@@ -133,6 +137,7 @@
     Dart_IsolateFlags api_flags;
     vm_flags.CopyTo(&api_flags);
     vm_isolate_ = Isolate::Init("vm-isolate", api_flags, is_vm_isolate);
+    start_time_ = vm_isolate_->start_time();
     vm_isolate_->set_compilation_allowed(!precompiled);
     // Verify assumptions about executing in the VM isolate.
     ASSERT(vm_isolate_ == Isolate::Current());
@@ -155,6 +160,8 @@
     if (vm_isolate_snapshot != NULL) {
       if (instructions_snapshot != NULL) {
         vm_isolate_->SetupInstructionsSnapshotPage(instructions_snapshot);
+        ASSERT(data_snapshot != NULL);
+        vm_isolate_->SetupDataSnapshotPage(data_snapshot);
       }
       const Snapshot* snapshot = Snapshot::SetupFromBuffer(vm_isolate_snapshot);
       if (snapshot == NULL) {
@@ -164,6 +171,7 @@
       VmIsolateSnapshotReader reader(snapshot->content(),
                                      snapshot->length(),
                                      instructions_snapshot,
+                                     data_snapshot,
                                      T);
       const Error& error = Error::Handle(reader.ReadVmIsolateSnapshot());
       if (!error.IsNull()) {
@@ -234,8 +242,17 @@
     return "VM already terminated.";
   }
 
+  if (FLAG_trace_shutdown) {
+    OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Starting shutdown\n",
+                 timestamp());
+  }
+
   if (FLAG_profiler) {
     // Shut down profiling.
+    if (FLAG_trace_shutdown) {
+      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down profiling\n",
+                   timestamp());
+    }
     Profiler::Shutdown();
   }
 
@@ -243,6 +260,10 @@
   {
     // Set the VM isolate as current isolate when shutting down
     // Metrics so that we can use a StackZone.
+    if (FLAG_trace_shutdown) {
+      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Entering vm isolate\n",
+                   timestamp());
+    }
     bool result = Thread::EnterIsolate(vm_isolate_);
     ASSERT(result);
     Metric::Cleanup();
@@ -251,19 +272,39 @@
 
   if (FLAG_shutdown) {
     // Disable the creation of new isolates.
+    if (FLAG_trace_shutdown) {
+      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Disabling isolate creation\n",
+                   timestamp());
+    }
     Isolate::DisableIsolateCreation();
 
     // Send the OOB Kill message to all remaining application isolates.
+    if (FLAG_trace_shutdown) {
+      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Killing all app isolates\n",
+                   timestamp());
+    }
     Isolate::KillAllIsolates(Isolate::kInternalKillMsg);
 
     // Shutdown the service isolate.
+    if (FLAG_trace_shutdown) {
+      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down service isolate\n",
+                   timestamp());
+    }
     ServiceIsolate::Shutdown();
 
     // Wait for all application isolates and the service isolate to shutdown
     // before shutting down the thread pool.
+    if (FLAG_trace_shutdown) {
+      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Waiting for isolate shutdown\n",
+                   timestamp());
+    }
     WaitForIsolateShutdown();
 
     // Shutdown the thread pool. On return, all thread pool threads have exited.
+    if (FLAG_trace_shutdown) {
+      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleting thread pool\n",
+                   timestamp());
+    }
     delete thread_pool_;
     thread_pool_ = NULL;
 
@@ -273,9 +314,17 @@
     // 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.
+    if (FLAG_trace_shutdown) {
+      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Disabling OS Thread creation\n",
+                   timestamp());
+    }
     OSThread::DisableOSThreadCreation();
 
     // Set the VM isolate as current isolate.
+    if (FLAG_trace_shutdown) {
+      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Cleaning up vm isolate\n",
+                   timestamp());
+    }
     bool result = Thread::EnterIsolate(vm_isolate_);
     ASSERT(result);
 
@@ -292,18 +341,41 @@
     OSThread* os_thread = OSThread::Current();
     OSThread::SetCurrent(NULL);
     delete os_thread;
+    if (FLAG_trace_shutdown) {
+      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleted os_thread\n",
+                   timestamp());
+    }
   } else {
     // Shutdown the service isolate.
+    if (FLAG_trace_shutdown) {
+      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down service isolate\n",
+                   timestamp());
+    }
     ServiceIsolate::Shutdown();
 
     // Disable thread creation.
+    if (FLAG_trace_shutdown) {
+      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Disabling OS Thread creation\n",
+                   timestamp());
+    }
     OSThread::DisableOSThreadCreation();
   }
 
+  if (FLAG_trace_shutdown) {
+    OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleting code observers\n",
+                 timestamp());
+  }
   CodeObservers::DeleteAll();
   if (FLAG_support_timeline) {
+    if (FLAG_trace_shutdown) {
+      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down timeline\n",
+                   timestamp());
+    }
     Timeline::Shutdown();
   }
+  if (FLAG_trace_shutdown) {
+    OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Done\n", timestamp());
+  }
 
   return NULL;
 }
@@ -360,6 +432,7 @@
     IsolateSnapshotReader reader(snapshot->content(),
                                  snapshot->length(),
                                  Dart::instructions_snapshot_buffer(),
+                                 Dart::data_snapshot_buffer(),
                                  T);
     const Error& error = Error::Handle(reader.ReadFullSnapshot());
     if (!error.IsNull()) {
@@ -466,6 +539,12 @@
 }
 
 
+int64_t Dart::timestamp() {
+  return ((OS::GetCurrentTimeMicros() - Dart::start_time_) /
+          kMillisecondsPerSecond);
+}
+
+
 uword Dart::AllocateReadOnlyHandle() {
   ASSERT(Isolate::Current() == Dart::vm_isolate());
   ASSERT(predefined_handles_ != NULL);
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index 412eef2..aa43e12 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -23,6 +23,7 @@
   static const char* InitOnce(
       const uint8_t* vm_isolate_snapshot,
       const uint8_t* instructions_snapshot,
+      const uint8_t* data_snapshot,
       Dart_IsolateCreateCallback create,
       Dart_IsolateShutdownCallback shutdown,
       Dart_FileOpenCallback file_open,
@@ -43,6 +44,10 @@
   static Isolate* vm_isolate() { return vm_isolate_; }
   static ThreadPool* thread_pool() { return thread_pool_; }
 
+  // Returns a timestamp for use in debugging output in milliseconds
+  // since start time.
+  static int64_t timestamp();
+
   static void set_pprof_symbol_generator(DebugInfo* value) {
     pprof_symbol_generator_ = value;
   }
@@ -64,14 +69,23 @@
     return instructions_snapshot_buffer_ != NULL;
   }
 
+  static const uint8_t* data_snapshot_buffer() {
+    return data_snapshot_buffer_;
+  }
+  static void set_data_snapshot_buffer(const uint8_t* buffer) {
+    data_snapshot_buffer_ = buffer;
+  }
+
  private:
   static void WaitForIsolateShutdown();
 
   static Isolate* vm_isolate_;
+  static int64_t start_time_;
   static ThreadPool* thread_pool_;
   static DebugInfo* pprof_symbol_generator_;
   static ReadOnlyHandles* predefined_handles_;
   static const uint8_t* instructions_snapshot_buffer_;
+  static const uint8_t* data_snapshot_buffer_;
 };
 
 }  // namespace dart
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index a826afe..dad463e 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -150,7 +150,9 @@
     if (obj_class.IsSubtypeOf(Object::null_type_arguments(),
                               list_class,
                               Object::null_type_arguments(),
-                              &malformed_type_error)) {
+                              &malformed_type_error,
+                              NULL,
+                              Heap::kNew)) {
       ASSERT(malformed_type_error.IsNull());  // Type is a raw List.
       return instance.raw();
     }
@@ -170,7 +172,9 @@
     if (obj_class.IsSubtypeOf(Object::null_type_arguments(),
                               map_class,
                               Object::null_type_arguments(),
-                              &malformed_type_error)) {
+                              &malformed_type_error,
+                              NULL,
+                              Heap::kNew)) {
       ASSERT(malformed_type_error.IsNull());  // Type is a raw Map.
       return instance.raw();
     }
@@ -1134,6 +1138,7 @@
 DART_EXPORT char* Dart_Initialize(
     const uint8_t* vm_isolate_snapshot,
     const uint8_t* instructions_snapshot,
+    const uint8_t* data_snapshot,
     Dart_IsolateCreateCallback create,
     Dart_IsolateInterruptCallback interrupt,
     Dart_IsolateUnhandledExceptionCallback unhandled,
@@ -1157,6 +1162,7 @@
   }
   const char* err_msg = Dart::InitOnce(vm_isolate_snapshot,
                                        instructions_snapshot,
+                                       data_snapshot,
                                        create, shutdown,
                                        file_open, file_read, file_write,
                                        file_close, entropy_source,
@@ -2016,7 +2022,9 @@
     bool is_future = obj_class.IsSubtypeOf(Object::null_type_arguments(),
                                            future_class,
                                            Object::null_type_arguments(),
-                                           &malformed_type_error);
+                                           &malformed_type_error,
+                                           NULL,
+                                           Heap::kNew);
     ASSERT(malformed_type_error.IsNull());  // Type is a raw Future.
     return is_future;
   }
@@ -3798,7 +3806,8 @@
       // type arguments of the type argument.
       Error& bound_error = Error::Handle();
       redirect_type ^= redirect_type.InstantiateFrom(type_arguments,
-                                                     &bound_error);
+                                                     &bound_error,
+                                                     NULL, NULL, Heap::kNew);
       if (!bound_error.IsNull()) {
         return Api::NewHandle(T, bound_error.raw());
       }
@@ -5131,6 +5140,10 @@
   NoHeapGrowthControlScope no_growth_control;
 
   const Snapshot* snapshot = Snapshot::SetupFromBuffer(buffer);
+  if (snapshot == NULL) {
+    return Api::NewError("%s expects parameter 'buffer' to be a script type"
+                         " snapshot with a valid length.", CURRENT_FUNC);
+  }
   if (!snapshot->IsScriptSnapshot()) {
     return Api::NewError("%s expects parameter 'buffer' to be a script type"
                          " snapshot.", CURRENT_FUNC);
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index a35bf99..8e7d698 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -2819,6 +2819,7 @@
                                &peer,
                                0,
                                WeakPersistentHandlePeerFinalizer);
+  Dart_ExitScope();
   Dart_ShutdownIsolate();
   EXPECT(peer == 42);
 }
diff --git a/runtime/vm/debugger_api_impl_test.cc b/runtime/vm/debugger_api_impl_test.cc
index fdfd262..85faf11 100644
--- a/runtime/vm/debugger_api_impl_test.cc
+++ b/runtime/vm/debugger_api_impl_test.cc
@@ -14,6 +14,7 @@
 DECLARE_FLAG(bool, background_compilation);
 DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, use_osr);
+DECLARE_FLAG(bool, trace_shutdown);
 
 #ifndef PRODUCT
 
@@ -1513,6 +1514,8 @@
 
 
 TEST_CASE(Debug_InterruptIsolate) {
+  bool saved_flag = FLAG_trace_shutdown;
+  FLAG_trace_shutdown = true;
   sync = new Monitor();
   Dart_SetIsolateEventHandler(&TestInterruptIsolate);
   EXPECT(interrupt_isolate_id == ILLEGAL_ISOLATE_ID);
@@ -1522,6 +1525,7 @@
 
   // Wait for the test isolate to be created.
   {
+    OS::PrintErr("Waiting for isolate to be created\n");
     MonitorLocker ml(sync);
     while (interrupt_isolate_id == ILLEGAL_ISOLATE_ID) {
       ml.Wait();
@@ -1535,6 +1539,7 @@
 
   // Wait for the test isolate to be interrupted.
   {
+    OS::PrintErr("Waiting for isolate to be interrupted\n");
     MonitorLocker ml(sync);
     while (!isolate_interrupted || !pause_event_handled) {
       ml.Wait();
@@ -1545,12 +1550,15 @@
 
   // Wait for the test isolate to shutdown.
   {
+    OS::PrintErr("Waiting for isolate to be shut down\n");
     MonitorLocker ml(sync);
     while (interrupt_isolate_id != ILLEGAL_ISOLATE_ID) {
       ml.Wait();
     }
   }
   EXPECT(interrupt_isolate_id == ILLEGAL_ISOLATE_ID);
+  OS::PrintErr("Complete\n");
+  FLAG_trace_shutdown = saved_flag;
 }
 
 
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 369d099..800a802 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -19,8 +19,6 @@
 
 namespace dart {
 
-DEFINE_FLAG(bool, abort_on_assertion_errors, false,
-            "Abort on assertion and typecheck failures");
 DEFINE_FLAG(bool, print_stacktrace_at_throw, false,
             "Prints a stack trace everytime a throw occurs.");
 
@@ -459,7 +457,7 @@
 
   // Type errors in the core library may be difficult to diagnose.
   // Print type error information before throwing the error when debugging.
-  if (FLAG_print_stacktrace_at_throw || FLAG_abort_on_assertion_errors) {
+  if (FLAG_print_stacktrace_at_throw) {
     if (!error_msg.IsNull()) {
       OS::Print("%s\n", error_msg.ToCString());
     }
@@ -475,10 +473,6 @@
     }
   }
 
-  if (FLAG_abort_on_assertion_errors) {
-    PrintStackTraceAndAbort("a type error");
-  }
-
   // Throw TypeError or CastError instance.
   Exceptions::ThrowByType(exception_type, args);
   UNREACHABLE();
@@ -633,14 +627,6 @@
       library = Library::IsolateLibrary();
       class_name = &Symbols::IsolateSpawnException();
       break;
-    case kJavascriptIntegerOverflowError:
-      library = Library::CoreLibrary();
-      class_name = &Symbols::JavascriptIntegerOverflowError();
-      break;
-    case kJavascriptCompatibilityError:
-      library = Library::CoreLibrary();
-      class_name = &Symbols::JavascriptCompatibilityError();
-      break;
     case kAssertion:
       library = Library::CoreLibrary();
       class_name = &Symbols::AssertionError();
@@ -678,22 +664,4 @@
 }
 
 
-// Throw JavascriptCompatibilityError exception.
-void Exceptions::ThrowJavascriptCompatibilityError(const char* msg) {
-  const Array& exc_args = Array::Handle(Array::New(1));
-  const String& msg_str = String::Handle(String::New(msg));
-  exc_args.SetAt(0, msg_str);
-  Exceptions::ThrowByType(Exceptions::kJavascriptCompatibilityError, exc_args);
-}
-
-
-void Exceptions::PrintStackTraceAndAbort(const char* reason) {
-  const Instance& stacktrace = Instance::Handle(CurrentStacktrace());
-
-  OS::PrintErr("\n\n\nAborting due to %s. Stacktrace:\n%s\n",
-               reason,
-               stacktrace.ToCString());
-  OS::Abort();
-}
-
 }  // namespace dart
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index ada7606..86e3261 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -61,8 +61,6 @@
     kOutOfMemory,
     kNullThrown,
     kIsolateSpawn,
-    kJavascriptIntegerOverflowError,
-    kJavascriptCompatibilityError,
     kAssertion,
     kCast,
     kType,
@@ -81,14 +79,11 @@
                               const Integer& argument_value,
                               intptr_t expected_from,
                               intptr_t expected_to);
-  static void ThrowJavascriptCompatibilityError(const char* msg);
 
   // Returns a RawInstance if the exception is successfully created,
   // otherwise returns a RawError.
   static RawObject* Create(ExceptionType type, const Array& arguments);
 
-  static void PrintStackTraceAndAbort(const char* reason);
-
  private:
   DISALLOW_COPY_AND_ASSIGN(Exceptions);
 };
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc
index 49f81ff..1f97a72 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -44,7 +44,6 @@
     loop_headers_(NULL),
     loop_invariant_loads_(NULL),
     guarded_fields_(parsed_function.guarded_fields()),
-    deoptimize_dependent_code_(),
     deferred_prefixes_(parsed_function.deferred_prefixes()),
     captured_parameters_(new(zone()) BitVector(zone(), variable_count())),
     inlining_id_(-1) {
diff --git a/runtime/vm/flow_graph.h b/runtime/vm/flow_graph.h
index 970a7a0..9841716 100644
--- a/runtime/vm/flow_graph.h
+++ b/runtime/vm/flow_graph.h
@@ -285,10 +285,6 @@
     return guarded_fields_;
   }
 
-  GrowableArray<const Field*>& deoptimize_dependent_code() {
-    return deoptimize_dependent_code_;
-  }
-
   ZoneGrowableArray<const LibraryPrefix*>* deferred_prefixes() const {
     return deferred_prefixes_;
   }
@@ -373,7 +369,6 @@
   ZoneGrowableArray<BlockEntryInstr*>* loop_headers_;
   ZoneGrowableArray<BitVector*>* loop_invariant_loads_;
   ZoneGrowableArray<const Field*>* guarded_fields_;
-  GrowableArray<const Field*> deoptimize_dependent_code_;
   ZoneGrowableArray<const LibraryPrefix*>* deferred_prefixes_;
   DirectChainedHashMap<ConstantPoolTrait> constant_instr_pool_;
   BitVector* captured_parameters_;
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 63bdb24..458557d 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -41,7 +41,6 @@
 
 DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, profile_vm);
-DECLARE_FLAG(bool, warn_on_javascript_compatibility);
 DECLARE_FLAG(bool, use_field_guards);
 
 // Quick access to the locally defined zone() method.
@@ -1594,30 +1593,6 @@
 }
 
 
-bool FlowGraphBuilder::WarnOnJSIntegralNumTypeTest(
-    AstNode* node, const AbstractType& type) const {
-  if (!(node->IsLiteralNode() && (type.IsIntType() || type.IsDoubleType()))) {
-    return false;
-  }
-  const Instance& instance = node->AsLiteralNode()->literal();
-  if (type.IsIntType()) {
-    if (instance.IsDouble()) {
-      const Double& double_instance = Double::Cast(instance);
-      double value = double_instance.value();
-      if (floor(value) == value) {
-        return true;
-      }
-    }
-  } else {
-    ASSERT(type.IsDoubleType());
-    if (instance.IsInteger()) {
-      return true;
-    }
-  }
-  return false;
-}
-
-
 void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) {
   ASSERT(Token::IsTypeTestOperator(node->kind()));
   const AbstractType& type = node->right()->AsTypeNode()->type();
@@ -1638,41 +1613,39 @@
   node->left()->Visit(&for_left_value);
   Append(for_left_value);
 
-  if (!FLAG_warn_on_javascript_compatibility) {
-    if (type.IsNumberType() || type.IsIntType() || type.IsDoubleType() ||
-        type.IsSmiType() || type.IsStringType()) {
-      String& method_name = String::ZoneHandle(Z);
-      if (type.IsNumberType()) {
-        method_name = Symbols::_instanceOfNum().raw();
-      } else if (type.IsIntType()) {
-        method_name = Symbols::_instanceOfInt().raw();
-      } else if (type.IsDoubleType()) {
-        method_name = Symbols::_instanceOfDouble().raw();
-      } else if (type.IsSmiType()) {
-        method_name = Symbols::_instanceOfSmi().raw();
-      } else if (type.IsStringType()) {
-        method_name = Symbols::_instanceOfString().raw();
-      }
-      ASSERT(!method_name.IsNull());
-      PushArgumentInstr* push_left = PushArgument(for_left_value.value());
-      ZoneGrowableArray<PushArgumentInstr*>* arguments =
-          new(Z) ZoneGrowableArray<PushArgumentInstr*>(2);
-      arguments->Add(push_left);
-      const Bool& negate = Bool::Get(node->kind() == Token::kISNOT);
-      Value* negate_arg = Bind(new(Z) ConstantInstr(negate));
-      arguments->Add(PushArgument(negate_arg));
-      const intptr_t kNumArgsChecked = 1;
-      InstanceCallInstr* call = new(Z) InstanceCallInstr(
-          node->token_pos(),
-          Library::PrivateCoreLibName(method_name),
-          node->kind(),
-          arguments,
-          Object::null_array(),  // No argument names.
-          kNumArgsChecked,
-          owner()->ic_data_array());
-      ReturnDefinition(call);
-      return;
+  if (type.IsNumberType() || type.IsIntType() || type.IsDoubleType() ||
+      type.IsSmiType() || type.IsStringType()) {
+    String& method_name = String::ZoneHandle(Z);
+    if (type.IsNumberType()) {
+      method_name = Symbols::_instanceOfNum().raw();
+    } else if (type.IsIntType()) {
+      method_name = Symbols::_instanceOfInt().raw();
+    } else if (type.IsDoubleType()) {
+      method_name = Symbols::_instanceOfDouble().raw();
+    } else if (type.IsSmiType()) {
+      method_name = Symbols::_instanceOfSmi().raw();
+    } else if (type.IsStringType()) {
+      method_name = Symbols::_instanceOfString().raw();
     }
+    ASSERT(!method_name.IsNull());
+    PushArgumentInstr* push_left = PushArgument(for_left_value.value());
+    ZoneGrowableArray<PushArgumentInstr*>* arguments =
+        new(Z) ZoneGrowableArray<PushArgumentInstr*>(2);
+    arguments->Add(push_left);
+    const Bool& negate = Bool::Get(node->kind() == Token::kISNOT);
+    Value* negate_arg = Bind(new(Z) ConstantInstr(negate));
+    arguments->Add(PushArgument(negate_arg));
+    const intptr_t kNumArgsChecked = 1;
+    InstanceCallInstr* call = new(Z) InstanceCallInstr(
+        node->token_pos(),
+        Library::PrivateCoreLibName(method_name),
+        node->kind(),
+        arguments,
+        Object::null_array(),  // No argument names.
+        kNumArgsChecked,
+        owner()->ic_data_array());
+    ReturnDefinition(call);
+    return;
   }
 
   PushArgumentInstr* push_left = PushArgument(for_left_value.value());
@@ -1719,13 +1692,8 @@
                        for_value.value(),
                        type,
                        dst_name)) {
-    // Check for javascript compatibility.
-    // Do not skip type check if javascript compatibility warning is required.
-    if (!FLAG_warn_on_javascript_compatibility ||
-        !owner()->WarnOnJSIntegralNumTypeTest(node->left(), type)) {
-      ReturnValue(for_value.value());
-      return;
-    }
+    ReturnValue(for_value.value());
+    return;
   }
   PushArgumentInstr* push_left = PushArgument(for_value.value());
   PushArgumentInstr* push_type_args = NULL;
@@ -4442,8 +4410,23 @@
                                          *method_arguments,
                                          temp,
                                          is_super_invocation);
-  const Function& no_such_method_func = Function::ZoneHandle(Z,
-      Resolver::ResolveDynamicAnyArgs(target_class, Symbols::NoSuchMethod()));
+  // Make sure we resolve to a compatible noSuchMethod, otherwise call
+  // noSuchMethod of class Object.
+  const int kNumArguments = 2;
+  ArgumentsDescriptor args_desc(
+      Array::ZoneHandle(Z, ArgumentsDescriptor::New(kNumArguments)));
+  Function& no_such_method_func = Function::ZoneHandle(Z,
+      Resolver::ResolveDynamicForReceiverClass(target_class,
+                                               Symbols::NoSuchMethod(),
+                                               args_desc));
+  if (no_such_method_func.IsNull()) {
+    const Class& object_class =
+        Class::ZoneHandle(Z, isolate()->object_store()->object_class());
+    no_such_method_func =
+        Resolver::ResolveDynamicForReceiverClass(object_class,
+                                                 Symbols::NoSuchMethod(),
+                                                 args_desc);
+  }
   // We are guaranteed to find noSuchMethod of class Object.
   ASSERT(!no_such_method_func.IsNull());
   ZoneGrowableArray<PushArgumentInstr*>* push_arguments =
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
index 6dc14ce..27062d6 100644
--- a/runtime/vm/flow_graph_builder.h
+++ b/runtime/vm/flow_graph_builder.h
@@ -113,11 +113,6 @@
     return ic_data_array_;
   }
 
-  // Return true if a Javascript compatibility warning should be emitted at
-  // runtime for this type test.
-  bool WarnOnJSIntegralNumTypeTest(AstNode* node,
-                                   const AbstractType& type) const;
-
   void Bailout(const char* reason) const;
 
   intptr_t AllocateBlockId() { return ++last_used_block_id_; }
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 15851e6..ef109ac 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -55,7 +55,6 @@
 DECLARE_FLAG(charp, deoptimize_filter);
 DECLARE_FLAG(bool, emit_edge_counters);
 DECLARE_FLAG(bool, fields_may_be_reset);
-DECLARE_FLAG(bool, guess_icdata_cid);
 DECLARE_FLAG(bool, ic_range_profiling);
 DECLARE_FLAG(bool, intrinsify);
 DECLARE_FLAG(bool, load_deferred_eagerly);
@@ -68,7 +67,6 @@
 DECLARE_FLAG(bool, use_field_guards);
 DECLARE_FLAG(bool, use_cha_deopt);
 DECLARE_FLAG(bool, use_osr);
-DECLARE_FLAG(bool, warn_on_javascript_compatibility);
 DECLARE_FLAG(bool, print_stop_message);
 DECLARE_FLAG(bool, lazy_dispatchers);
 DECLARE_FLAG(bool, interpret_irregexp);
@@ -1098,7 +1096,7 @@
       // Reading from a mutable double box requires allocating a fresh double.
       if (load_node.field().guarded_cid() == kDynamicCid) {
         GenerateInlinedGetter(load_node.field().Offset());
-        return true;
+        return !FLAG_use_field_guards;
       }
       return false;
     }
@@ -1113,7 +1111,7 @@
           *sequence_node.NodeAt(0)->AsStoreInstanceFieldNode();
       if (store_node.field().guarded_cid() == kDynamicCid) {
         GenerateInlinedSetter(store_node.field().Offset());
-        return true;
+        return !FLAG_use_field_guards;
       }
     }
   }
@@ -1173,12 +1171,7 @@
     return;
   }
 
-  if (is_optimizing() &&
-      // Do not make the instance call megamorphic if the callee needs to decode
-      // the calling code sequence to lookup the ic data and verify if a JS
-      // warning has already been issued or not.
-      (!FLAG_warn_on_javascript_compatibility ||
-       !ic_data.MayCheckForJSWarning())) {
+  if (is_optimizing()) {
     EmitMegamorphicInstanceCall(ic_data, argument_count,
                                 deopt_id, token_pos, locs);
     return;
@@ -1213,12 +1206,7 @@
       ic_data.IsNull() ? ArgumentsDescriptor::New(argument_count,
                                                   argument_names)
                        : ic_data.arguments_descriptor());
-  // Proper reporting of Javascript incompatibilities requires icdata and
-  // may therefore prevent the optimization of some static calls.
-  if (is_optimizing() &&
-      !(FLAG_warn_on_javascript_compatibility &&
-        (MethodRecognizer::RecognizeKind(function) ==
-         MethodRecognizer::kObjectIdentical))) {
+  if (is_optimizing()) {
     EmitOptimizedStaticCall(function, arguments_descriptor,
                             argument_count, deopt_id, token_pos, locs);
   } else {
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 8cec8d7..f2fd49d 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -69,6 +69,7 @@
 
 // Quick access to the current zone.
 #define Z (zone())
+#define I (isolate())
 
 #define TRACE_INLINING(statement)                                              \
   do {                                                                         \
@@ -705,8 +706,8 @@
         // Load IC data for the callee.
         ZoneGrowableArray<const ICData*>* ic_data_array =
               new(Z) ZoneGrowableArray<const ICData*>();
-        const bool clone_descriptors = Compiler::IsBackgroundCompilation();
-        function.RestoreICDataMap(ic_data_array, clone_descriptors);
+        const bool clone_ic_data = Compiler::IsBackgroundCompilation();
+        function.RestoreICDataMap(ic_data_array, clone_ic_data);
         if (Compiler::IsBackgroundCompilation() &&
             (function.ic_data_array() == Array::null())) {
           Compiler::AbortBackgroundCompilation(Thread::kNoDeoptId);
@@ -1520,13 +1521,15 @@
         new(Z) RedefinitionInstr(new(Z) Value(receiver));
     redefinition->set_ssa_temp_index(
         owner_->caller_graph()->alloc_ssa_temp_index());
-  if (optimizer.TryInlineRecognizedMethod(receiver_cid,
-                                          target,
-                                          call_,
-                                          redefinition,
-                                          call_->instance_call()->token_pos(),
-                                          *call_->instance_call()->ic_data(),
-                                          &entry, &last)) {
+  if (FlowGraphInliner::TryInlineRecognizedMethod(
+          owner_->caller_graph(),
+          receiver_cid,
+          target,
+          call_,
+          redefinition,
+          call_->instance_call()->token_pos(),
+          *call_->instance_call()->ic_data(),
+          &entry, &last)) {
     // Create a graph fragment.
     redefinition->InsertAfter(entry);
     InlineExitCollector* exit_collector =
@@ -1948,4 +1951,1107 @@
 }
 
 
+static bool ShouldInlineSimd() {
+  return FlowGraphCompiler::SupportsUnboxedSimd128();
+}
+
+
+static bool CanUnboxDouble() {
+  return FlowGraphCompiler::SupportsUnboxedDoubles();
+}
+
+
+static bool ShouldInlineInt64ArrayOps() {
+#if defined(TARGET_ARCH_X64)
+  return true;
+#else
+  return false;
+#endif
+}
+
+
+static bool CanUnboxInt32() {
+  // Int32/Uint32 can be unboxed if it fits into a smi or the platform
+  // supports unboxed mints.
+  return (kSmiBits >= 32) || FlowGraphCompiler::SupportsUnboxedMints();
+}
+
+
+// Quick access to the current one.
+#undef Z
+#define Z (flow_graph->zone())
+
+static intptr_t PrepareInlineIndexedOp(FlowGraph* flow_graph,
+                                       Instruction* call,
+                                       intptr_t array_cid,
+                                       Definition** array,
+                                       Definition* index,
+                                       Instruction** cursor) {
+  // Insert index smi check.
+  *cursor = flow_graph->AppendTo(
+      *cursor,
+      new(Z) CheckSmiInstr(new(Z) Value(index),
+                           call->deopt_id(),
+                           call->token_pos()),
+      call->env(),
+      FlowGraph::kEffect);
+
+  // Insert array length load and bounds check.
+  LoadFieldInstr* length =
+      new(Z) LoadFieldInstr(
+          new(Z) Value(*array),
+          CheckArrayBoundInstr::LengthOffsetFor(array_cid),
+          Type::ZoneHandle(Z, Type::SmiType()),
+          call->token_pos());
+  length->set_is_immutable(
+      CheckArrayBoundInstr::IsFixedLengthArrayType(array_cid));
+  length->set_result_cid(kSmiCid);
+  length->set_recognized_kind(
+      LoadFieldInstr::RecognizedKindFromArrayCid(array_cid));
+  *cursor = flow_graph->AppendTo(*cursor,
+                                 length,
+                                 NULL,
+                                 FlowGraph::kValue);
+
+  *cursor = flow_graph->AppendTo(*cursor,
+                                 new(Z) CheckArrayBoundInstr(
+                                     new(Z) Value(length),
+                                     new(Z) Value(index),
+                                     call->deopt_id()),
+                                 call->env(),
+                                 FlowGraph::kEffect);
+
+  if (array_cid == kGrowableObjectArrayCid) {
+    // Insert data elements load.
+    LoadFieldInstr* elements =
+        new(Z) LoadFieldInstr(
+            new(Z) Value(*array),
+            GrowableObjectArray::data_offset(),
+            Object::dynamic_type(),
+            call->token_pos());
+    elements->set_result_cid(kArrayCid);
+    *cursor = flow_graph->AppendTo(*cursor,
+                                   elements,
+                                   NULL,
+                                   FlowGraph::kValue);
+    // Load from the data from backing store which is a fixed-length array.
+    *array = elements;
+    array_cid = kArrayCid;
+  } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+    LoadUntaggedInstr* elements =
+        new(Z) LoadUntaggedInstr(new(Z) Value(*array),
+                                 ExternalTypedData::data_offset());
+    *cursor = flow_graph->AppendTo(*cursor,
+                                   elements,
+                                   NULL,
+                                   FlowGraph::kValue);
+    *array = elements;
+  }
+  return array_cid;
+}
+
+
+static intptr_t MethodKindToCid(MethodRecognizer::Kind kind) {
+  switch (kind) {
+    case MethodRecognizer::kImmutableArrayGetIndexed:
+      return kImmutableArrayCid;
+
+    case MethodRecognizer::kObjectArrayGetIndexed:
+    case MethodRecognizer::kObjectArraySetIndexed:
+      return kArrayCid;
+
+    case MethodRecognizer::kGrowableArrayGetIndexed:
+    case MethodRecognizer::kGrowableArraySetIndexed:
+      return kGrowableObjectArrayCid;
+
+    case MethodRecognizer::kFloat32ArrayGetIndexed:
+    case MethodRecognizer::kFloat32ArraySetIndexed:
+      return kTypedDataFloat32ArrayCid;
+
+    case MethodRecognizer::kFloat64ArrayGetIndexed:
+    case MethodRecognizer::kFloat64ArraySetIndexed:
+      return kTypedDataFloat64ArrayCid;
+
+    case MethodRecognizer::kInt8ArrayGetIndexed:
+    case MethodRecognizer::kInt8ArraySetIndexed:
+      return kTypedDataInt8ArrayCid;
+
+    case MethodRecognizer::kUint8ArrayGetIndexed:
+    case MethodRecognizer::kUint8ArraySetIndexed:
+      return kTypedDataUint8ArrayCid;
+
+    case MethodRecognizer::kUint8ClampedArrayGetIndexed:
+    case MethodRecognizer::kUint8ClampedArraySetIndexed:
+      return kTypedDataUint8ClampedArrayCid;
+
+    case MethodRecognizer::kExternalUint8ArrayGetIndexed:
+    case MethodRecognizer::kExternalUint8ArraySetIndexed:
+      return kExternalTypedDataUint8ArrayCid;
+
+    case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
+    case MethodRecognizer::kExternalUint8ClampedArraySetIndexed:
+      return kExternalTypedDataUint8ClampedArrayCid;
+
+    case MethodRecognizer::kInt16ArrayGetIndexed:
+    case MethodRecognizer::kInt16ArraySetIndexed:
+      return kTypedDataInt16ArrayCid;
+
+    case MethodRecognizer::kUint16ArrayGetIndexed:
+    case MethodRecognizer::kUint16ArraySetIndexed:
+      return kTypedDataUint16ArrayCid;
+
+    case MethodRecognizer::kInt32ArrayGetIndexed:
+    case MethodRecognizer::kInt32ArraySetIndexed:
+      return kTypedDataInt32ArrayCid;
+
+    case MethodRecognizer::kUint32ArrayGetIndexed:
+    case MethodRecognizer::kUint32ArraySetIndexed:
+      return kTypedDataUint32ArrayCid;
+
+    case MethodRecognizer::kInt64ArrayGetIndexed:
+    case MethodRecognizer::kInt64ArraySetIndexed:
+      return kTypedDataInt64ArrayCid;
+
+    case MethodRecognizer::kFloat32x4ArrayGetIndexed:
+    case MethodRecognizer::kFloat32x4ArraySetIndexed:
+      return kTypedDataFloat32x4ArrayCid;
+
+    case MethodRecognizer::kInt32x4ArrayGetIndexed:
+    case MethodRecognizer::kInt32x4ArraySetIndexed:
+      return kTypedDataInt32x4ArrayCid;
+
+    case MethodRecognizer::kFloat64x2ArrayGetIndexed:
+    case MethodRecognizer::kFloat64x2ArraySetIndexed:
+      return kTypedDataFloat64x2ArrayCid;
+
+    default:
+      break;
+  }
+  return kIllegalCid;
+}
+
+
+static Instruction* GetCheckClass(FlowGraph* flow_graph,
+                                  Definition* to_check,
+                                  const ICData& unary_checks,
+                                  intptr_t deopt_id,
+                                  TokenPosition token_pos) {
+  if ((unary_checks.NumberOfUsedChecks() == 1) &&
+      unary_checks.HasReceiverClassId(kSmiCid)) {
+    return new(Z) CheckSmiInstr(new(Z) Value(to_check),
+                                deopt_id,
+                                token_pos);
+  }
+  return new(Z) CheckClassInstr(
+      new(Z) Value(to_check), deopt_id, unary_checks, token_pos);
+}
+
+
+static bool InlineGetIndexed(FlowGraph* flow_graph,
+                             MethodRecognizer::Kind kind,
+                             Instruction* call,
+                             Definition* receiver,
+                             TargetEntryInstr** entry,
+                             Definition** last) {
+  intptr_t array_cid = MethodKindToCid(kind);
+  ASSERT(array_cid != kIllegalCid);
+
+  Definition* array = receiver;
+  Definition* index = call->ArgumentAt(1);
+  *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
+                                   call->GetBlock()->try_index());
+  (*entry)->InheritDeoptTarget(Z, call);
+  Instruction* cursor = *entry;
+
+  array_cid = PrepareInlineIndexedOp(flow_graph,
+                                     call,
+                                     array_cid,
+                                     &array,
+                                     index,
+                                     &cursor);
+
+  intptr_t deopt_id = Thread::kNoDeoptId;
+  if ((array_cid == kTypedDataInt32ArrayCid) ||
+      (array_cid == kTypedDataUint32ArrayCid)) {
+    // Deoptimization may be needed if result does not always fit in a Smi.
+    deopt_id = (kSmiBits >= 32) ? Thread::kNoDeoptId : call->deopt_id();
+  }
+
+  // Array load and return.
+  intptr_t index_scale = Instance::ElementSizeFor(array_cid);
+  *last = new(Z) LoadIndexedInstr(new(Z) Value(array),
+                                  new(Z) Value(index),
+                                  index_scale,
+                                  array_cid,
+                                  deopt_id,
+                                  call->token_pos());
+  cursor = flow_graph->AppendTo(
+      cursor,
+      *last,
+      deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
+      FlowGraph::kValue);
+
+  if (array_cid == kTypedDataFloat32ArrayCid) {
+    *last = new(Z) FloatToDoubleInstr(new(Z) Value(*last), deopt_id);
+    flow_graph->AppendTo(cursor,
+                         *last,
+                         deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
+                         FlowGraph::kValue);
+  }
+  return true;
+}
+
+
+static bool InlineSetIndexed(FlowGraph* flow_graph,
+                             MethodRecognizer::Kind kind,
+                             const Function& target,
+                             Instruction* call,
+                             Definition* receiver,
+                             TokenPosition token_pos,
+                             const ICData& value_check,
+                             TargetEntryInstr** entry,
+                             Definition** last) {
+  intptr_t array_cid = MethodKindToCid(kind);
+  ASSERT(array_cid != kIllegalCid);
+
+  Definition* array = receiver;
+  Definition* index = call->ArgumentAt(1);
+  Definition* stored_value = call->ArgumentAt(2);
+
+  *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
+                                   call->GetBlock()->try_index());
+  (*entry)->InheritDeoptTarget(Z, call);
+  Instruction* cursor = *entry;
+  if (flow_graph->isolate()->flags().type_checks()) {
+    // Only type check for the value. A type check for the index is not
+    // needed here because we insert a deoptimizing smi-check for the case
+    // the index is not a smi.
+    const AbstractType& value_type =
+        AbstractType::ZoneHandle(Z, target.ParameterTypeAt(2));
+    Definition* type_args = NULL;
+    switch (array_cid) {
+      case kArrayCid:
+      case kGrowableObjectArrayCid: {
+        const Class& instantiator_class =  Class::Handle(Z, target.Owner());
+        intptr_t type_arguments_field_offset =
+            instantiator_class.type_arguments_field_offset();
+        LoadFieldInstr* load_type_args =
+            new(Z) LoadFieldInstr(new(Z) Value(array),
+                                  type_arguments_field_offset,
+                                  Type::ZoneHandle(Z),  // No type.
+                                  call->token_pos());
+        cursor = flow_graph->AppendTo(cursor,
+                                      load_type_args,
+                                      NULL,
+                                      FlowGraph::kValue);
+
+        type_args = load_type_args;
+        break;
+      }
+      case kTypedDataInt8ArrayCid:
+      case kTypedDataUint8ArrayCid:
+      case kTypedDataUint8ClampedArrayCid:
+      case kExternalTypedDataUint8ArrayCid:
+      case kExternalTypedDataUint8ClampedArrayCid:
+      case kTypedDataInt16ArrayCid:
+      case kTypedDataUint16ArrayCid:
+      case kTypedDataInt32ArrayCid:
+      case kTypedDataUint32ArrayCid:
+      case kTypedDataInt64ArrayCid:
+        ASSERT(value_type.IsIntType());
+        // Fall through.
+      case kTypedDataFloat32ArrayCid:
+      case kTypedDataFloat64ArrayCid: {
+        type_args = flow_graph->constant_null();
+        ASSERT((array_cid != kTypedDataFloat32ArrayCid &&
+                array_cid != kTypedDataFloat64ArrayCid) ||
+               value_type.IsDoubleType());
+        ASSERT(value_type.IsInstantiated());
+        break;
+      }
+      case kTypedDataFloat32x4ArrayCid: {
+        type_args = flow_graph->constant_null();
+        ASSERT((array_cid != kTypedDataFloat32x4ArrayCid) ||
+               value_type.IsFloat32x4Type());
+        ASSERT(value_type.IsInstantiated());
+        break;
+      }
+      case kTypedDataFloat64x2ArrayCid: {
+        type_args = flow_graph->constant_null();
+        ASSERT((array_cid != kTypedDataFloat64x2ArrayCid) ||
+               value_type.IsFloat64x2Type());
+        ASSERT(value_type.IsInstantiated());
+        break;
+      }
+      default:
+        // TODO(fschneider): Add support for other array types.
+        UNREACHABLE();
+    }
+    AssertAssignableInstr* assert_value =
+        new(Z) AssertAssignableInstr(token_pos,
+                                     new(Z) Value(stored_value),
+                                     new(Z) Value(type_args),
+                                     value_type,
+                                     Symbols::Value(),
+                                     call->deopt_id());
+    cursor = flow_graph->AppendTo(cursor,
+                                  assert_value,
+                                  call->env(),
+                                  FlowGraph::kValue);
+  }
+
+  array_cid = PrepareInlineIndexedOp(flow_graph,
+                                     call,
+                                     array_cid,
+                                     &array,
+                                     index,
+                                     &cursor);
+
+  // Check if store barrier is needed. Byte arrays don't need a store barrier.
+  StoreBarrierType needs_store_barrier =
+      (RawObject::IsTypedDataClassId(array_cid) ||
+       RawObject::IsTypedDataViewClassId(array_cid) ||
+       RawObject::IsExternalTypedDataClassId(array_cid)) ? kNoStoreBarrier
+                                                         : kEmitStoreBarrier;
+
+  // No need to class check stores to Int32 and Uint32 arrays because
+  // we insert unboxing instructions below which include a class check.
+  if ((array_cid != kTypedDataUint32ArrayCid) &&
+      (array_cid != kTypedDataInt32ArrayCid) &&
+      !value_check.IsNull()) {
+    // No store barrier needed because checked value is a smi, an unboxed mint,
+    // an unboxed double, an unboxed Float32x4, or unboxed Int32x4.
+    needs_store_barrier = kNoStoreBarrier;
+    Instruction* check = GetCheckClass(flow_graph,
+                                       stored_value,
+                                       value_check,
+                                       call->deopt_id(),
+                                       call->token_pos());
+    cursor = flow_graph->AppendTo(cursor,
+                                  check,
+                                  call->env(),
+                                  FlowGraph::kEffect);
+  }
+
+  if (array_cid == kTypedDataFloat32ArrayCid) {
+    stored_value =
+        new(Z) DoubleToFloatInstr(
+            new(Z) Value(stored_value), call->deopt_id());
+    cursor = flow_graph->AppendTo(cursor,
+                                  stored_value,
+                                  NULL,
+                                  FlowGraph::kValue);
+  } else if (array_cid == kTypedDataInt32ArrayCid) {
+    stored_value = new(Z) UnboxInt32Instr(
+        UnboxInt32Instr::kTruncate,
+        new(Z) Value(stored_value),
+        call->deopt_id());
+    cursor = flow_graph->AppendTo(cursor,
+                                  stored_value,
+                                  call->env(),
+                                  FlowGraph::kValue);
+  } else if (array_cid == kTypedDataUint32ArrayCid) {
+    stored_value = new(Z) UnboxUint32Instr(
+        new(Z) Value(stored_value),
+        call->deopt_id());
+    ASSERT(stored_value->AsUnboxInteger()->is_truncating());
+    cursor = flow_graph->AppendTo(cursor,
+                                  stored_value,
+                                  call->env(),
+                                  FlowGraph::kValue);
+  }
+
+  const intptr_t index_scale = Instance::ElementSizeFor(array_cid);
+  *last = new(Z) StoreIndexedInstr(new(Z) Value(array),
+                                   new(Z) Value(index),
+                                   new(Z) Value(stored_value),
+                                   needs_store_barrier,
+                                   index_scale,
+                                   array_cid,
+                                   call->deopt_id(),
+                                   call->token_pos());
+  flow_graph->AppendTo(cursor,
+                       *last,
+                       call->env(),
+                       FlowGraph::kEffect);
+  return true;
+}
+
+
+static bool InlineDoubleOp(FlowGraph* flow_graph,
+                           Token::Kind op_kind,
+                           Instruction* call,
+                           TargetEntryInstr** entry,
+                           Definition** last) {
+  Definition* left = call->ArgumentAt(0);
+  Definition* right = call->ArgumentAt(1);
+
+  *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
+                                   call->GetBlock()->try_index());
+  (*entry)->InheritDeoptTarget(Z, call);
+  // Arguments are checked. No need for class check.
+  BinaryDoubleOpInstr* double_bin_op =
+      new(Z) BinaryDoubleOpInstr(op_kind,
+                                 new(Z) Value(left),
+                                 new(Z) Value(right),
+                                 call->deopt_id(), call->token_pos());
+  flow_graph->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue);
+  *last = double_bin_op;
+
+  return true;
+}
+
+
+static intptr_t PrepareInlineByteArrayBaseOp(
+    FlowGraph* flow_graph,
+    Instruction* call,
+    intptr_t array_cid,
+    intptr_t view_cid,
+    Definition** array,
+    Definition* byte_index,
+    Instruction** cursor) {
+  // Insert byte_index smi check.
+  *cursor = flow_graph->AppendTo(*cursor,
+                                 new(Z) CheckSmiInstr(
+                                     new(Z) Value(byte_index),
+                                     call->deopt_id(),
+                                     call->token_pos()),
+                                 call->env(),
+                                 FlowGraph::kEffect);
+
+  LoadFieldInstr* length =
+      new(Z) LoadFieldInstr(
+          new(Z) Value(*array),
+          CheckArrayBoundInstr::LengthOffsetFor(array_cid),
+          Type::ZoneHandle(Z, Type::SmiType()),
+          call->token_pos());
+  length->set_is_immutable(true);
+  length->set_result_cid(kSmiCid);
+  length->set_recognized_kind(
+      LoadFieldInstr::RecognizedKindFromArrayCid(array_cid));
+  *cursor = flow_graph->AppendTo(*cursor,
+                                 length,
+                                 NULL,
+                                 FlowGraph::kValue);
+
+  intptr_t element_size = Instance::ElementSizeFor(array_cid);
+  ConstantInstr* bytes_per_element =
+      flow_graph->GetConstant(Smi::Handle(Z, Smi::New(element_size)));
+  BinarySmiOpInstr* len_in_bytes =
+      new(Z) BinarySmiOpInstr(Token::kMUL,
+                              new(Z) Value(length),
+                              new(Z) Value(bytes_per_element),
+                              call->deopt_id());
+  *cursor = flow_graph->AppendTo(*cursor, len_in_bytes, call->env(),
+                                 FlowGraph::kValue);
+
+  // adjusted_length = len_in_bytes - (element_size - 1).
+  Definition* adjusted_length = len_in_bytes;
+  intptr_t adjustment = Instance::ElementSizeFor(view_cid) - 1;
+  if (adjustment > 0) {
+    ConstantInstr* length_adjustment =
+        flow_graph->GetConstant(Smi::Handle(Z, Smi::New(adjustment)));
+    adjusted_length =
+        new(Z) BinarySmiOpInstr(Token::kSUB,
+                                new(Z) Value(len_in_bytes),
+                                new(Z) Value(length_adjustment),
+                                call->deopt_id());
+    *cursor = flow_graph->AppendTo(*cursor, adjusted_length, call->env(),
+                                   FlowGraph::kValue);
+  }
+
+  // Check adjusted_length > 0.
+  ConstantInstr* zero =
+      flow_graph->GetConstant(Smi::Handle(Z, Smi::New(0)));
+  *cursor = flow_graph->AppendTo(*cursor,
+                                 new(Z) CheckArrayBoundInstr(
+                                     new(Z) Value(adjusted_length),
+                                     new(Z) Value(zero),
+                                     call->deopt_id()),
+                                 call->env(),
+                                 FlowGraph::kEffect);
+  // Check 0 <= byte_index < adjusted_length.
+  *cursor = flow_graph->AppendTo(*cursor,
+                                 new(Z) CheckArrayBoundInstr(
+                                     new(Z) Value(adjusted_length),
+                                     new(Z) Value(byte_index),
+                                     call->deopt_id()),
+                                 call->env(),
+                                 FlowGraph::kEffect);
+
+  if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+    LoadUntaggedInstr* elements =
+        new(Z) LoadUntaggedInstr(new(Z) Value(*array),
+                                 ExternalTypedData::data_offset());
+    *cursor = flow_graph->AppendTo(*cursor,
+                                   elements,
+                                   NULL,
+                                   FlowGraph::kValue);
+    *array = elements;
+  }
+  return array_cid;
+}
+
+
+static bool InlineByteArrayBaseLoad(FlowGraph* flow_graph,
+                                    Instruction* call,
+                                    Definition* receiver,
+                                    intptr_t array_cid,
+                                    intptr_t view_cid,
+                                    TargetEntryInstr** entry,
+                                    Definition** last) {
+  ASSERT(array_cid != kIllegalCid);
+  Definition* array = receiver;
+  Definition* index = call->ArgumentAt(1);
+  *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
+                                   call->GetBlock()->try_index());
+  (*entry)->InheritDeoptTarget(Z, call);
+  Instruction* cursor = *entry;
+
+  array_cid = PrepareInlineByteArrayBaseOp(flow_graph,
+                                           call,
+                                           array_cid,
+                                           view_cid,
+                                           &array,
+                                           index,
+                                           &cursor);
+
+  intptr_t deopt_id = Thread::kNoDeoptId;
+  if ((array_cid == kTypedDataInt32ArrayCid) ||
+      (array_cid == kTypedDataUint32ArrayCid)) {
+    // Deoptimization may be needed if result does not always fit in a Smi.
+    deopt_id = (kSmiBits >= 32) ? Thread::kNoDeoptId : call->deopt_id();
+  }
+
+  *last = new(Z) LoadIndexedInstr(new(Z) Value(array),
+                                  new(Z) Value(index),
+                                  1,
+                                  view_cid,
+                                  deopt_id,
+                                  call->token_pos());
+  cursor = flow_graph->AppendTo(
+      cursor,
+      *last,
+      deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
+      FlowGraph::kValue);
+
+  if (view_cid == kTypedDataFloat32ArrayCid) {
+    *last = new(Z) FloatToDoubleInstr(new(Z) Value(*last), deopt_id);
+    flow_graph->AppendTo(cursor,
+                         *last,
+                         deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
+                         FlowGraph::kValue);
+  }
+  return true;
+}
+
+
+static bool InlineByteArrayBaseStore(FlowGraph* flow_graph,
+                                     const Function& target,
+                                     Instruction* call,
+                                     Definition* receiver,
+                                     intptr_t array_cid,
+                                     intptr_t view_cid,
+                                     TargetEntryInstr** entry,
+                                     Definition** last) {
+  ASSERT(array_cid != kIllegalCid);
+  Definition* array = receiver;
+  Definition* index = call->ArgumentAt(1);
+  *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
+                                   call->GetBlock()->try_index());
+  (*entry)->InheritDeoptTarget(Z, call);
+  Instruction* cursor = *entry;
+
+  array_cid = PrepareInlineByteArrayBaseOp(flow_graph,
+                                           call,
+                                           array_cid,
+                                           view_cid,
+                                           &array,
+                                           index,
+                                           &cursor);
+
+  // Extract the instance call so we can use the function_name in the stored
+  // value check ICData.
+  InstanceCallInstr* i_call = NULL;
+  if (call->IsPolymorphicInstanceCall()) {
+    i_call = call->AsPolymorphicInstanceCall()->instance_call();
+  } else {
+    ASSERT(call->IsInstanceCall());
+    i_call = call->AsInstanceCall();
+  }
+  ASSERT(i_call != NULL);
+  ICData& value_check = ICData::ZoneHandle(Z);
+  switch (view_cid) {
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid: {
+      // Check that value is always smi.
+      value_check = ICData::New(flow_graph->function(),
+                                i_call->function_name(),
+                                Object::empty_array(),  // Dummy args. descr.
+                                Thread::kNoDeoptId,
+                                1);
+      value_check.AddReceiverCheck(kSmiCid, target);
+      break;
+    }
+    case kTypedDataInt32ArrayCid:
+    case kTypedDataUint32ArrayCid:
+      // On 64-bit platforms assume that stored value is always a smi.
+      if (kSmiBits >= 32) {
+        value_check = ICData::New(flow_graph->function(),
+                                  i_call->function_name(),
+                                  Object::empty_array(),  // Dummy args. descr.
+                                  Thread::kNoDeoptId,
+                                  1);
+        value_check.AddReceiverCheck(kSmiCid, target);
+      }
+      break;
+    case kTypedDataFloat32ArrayCid:
+    case kTypedDataFloat64ArrayCid: {
+      // Check that value is always double.
+      value_check = ICData::New(flow_graph->function(),
+                                i_call->function_name(),
+                                Object::empty_array(),  // Dummy args. descr.
+                                Thread::kNoDeoptId,
+                                1);
+      value_check.AddReceiverCheck(kDoubleCid, target);
+      break;
+    }
+    case kTypedDataInt32x4ArrayCid: {
+      // Check that value is always Int32x4.
+      value_check = ICData::New(flow_graph->function(),
+                                i_call->function_name(),
+                                Object::empty_array(),  // Dummy args. descr.
+                                Thread::kNoDeoptId,
+                                1);
+      value_check.AddReceiverCheck(kInt32x4Cid, target);
+      break;
+    }
+    case kTypedDataFloat32x4ArrayCid: {
+      // Check that value is always Float32x4.
+      value_check = ICData::New(flow_graph->function(),
+                                i_call->function_name(),
+                                Object::empty_array(),  // Dummy args. descr.
+                                Thread::kNoDeoptId,
+                                1);
+      value_check.AddReceiverCheck(kFloat32x4Cid, target);
+      break;
+    }
+    default:
+      // Array cids are already checked in the caller.
+      UNREACHABLE();
+  }
+
+  Definition* stored_value = call->ArgumentAt(2);
+  if (!value_check.IsNull()) {
+    Instruction* check = GetCheckClass(flow_graph,
+                                       stored_value,
+                                       value_check,
+                                       call->deopt_id(),
+                                       call->token_pos());
+    cursor = flow_graph->AppendTo(cursor,
+                                  check,
+                                  call->env(),
+                                  FlowGraph::kEffect);
+  }
+
+  if (view_cid == kTypedDataFloat32ArrayCid) {
+    stored_value = new(Z) DoubleToFloatInstr(
+        new(Z) Value(stored_value), call->deopt_id());
+    cursor = flow_graph->AppendTo(cursor,
+                                  stored_value,
+                                  NULL,
+                                  FlowGraph::kValue);
+  } else if (view_cid == kTypedDataInt32ArrayCid) {
+    stored_value = new(Z) UnboxInt32Instr(
+        UnboxInt32Instr::kTruncate,
+        new(Z) Value(stored_value),
+        call->deopt_id());
+    cursor = flow_graph->AppendTo(cursor,
+                                  stored_value,
+                                  call->env(),
+                                  FlowGraph::kValue);
+  } else if (view_cid == kTypedDataUint32ArrayCid) {
+    stored_value = new(Z) UnboxUint32Instr(
+        new(Z) Value(stored_value),
+        call->deopt_id());
+    ASSERT(stored_value->AsUnboxInteger()->is_truncating());
+    cursor = flow_graph->AppendTo(cursor,
+                                  stored_value,
+                                  call->env(),
+                                  FlowGraph::kValue);
+  }
+
+  StoreBarrierType needs_store_barrier = kNoStoreBarrier;
+  *last = new(Z) StoreIndexedInstr(new(Z) Value(array),
+                                   new(Z) Value(index),
+                                   new(Z) Value(stored_value),
+                                   needs_store_barrier,
+                                   1,  // Index scale
+                                   view_cid,
+                                   call->deopt_id(),
+                                   call->token_pos());
+
+  flow_graph->AppendTo(cursor,
+                       *last,
+                       call->deopt_id() != Thread::kNoDeoptId ?
+                          call->env() : NULL,
+                       FlowGraph::kEffect);
+  return true;
+}
+
+
+
+// Returns the LoadIndexedInstr.
+static Definition* PrepareInlineStringIndexOp(
+    FlowGraph* flow_graph,
+    Instruction* call,
+    intptr_t cid,
+    Definition* str,
+    Definition* index,
+    Instruction* cursor) {
+
+  cursor = flow_graph->AppendTo(cursor,
+                                new(Z) CheckSmiInstr(
+                                    new(Z) Value(index),
+                                    call->deopt_id(),
+                                    call->token_pos()),
+                                call->env(),
+                                FlowGraph::kEffect);
+
+  // Load the length of the string.
+  // Treat length loads as mutable (i.e. affected by side effects) to avoid
+  // hoisting them since we can't hoist the preceding class-check. This
+  // is because of externalization of strings that affects their class-id.
+  LoadFieldInstr* length = new(Z) LoadFieldInstr(
+      new(Z) Value(str),
+      String::length_offset(),
+      Type::ZoneHandle(Z, Type::SmiType()),
+      str->token_pos());
+  length->set_result_cid(kSmiCid);
+  length->set_recognized_kind(MethodRecognizer::kStringBaseLength);
+
+  cursor = flow_graph->AppendTo(cursor, length, NULL, FlowGraph::kValue);
+  // Bounds check.
+  cursor = flow_graph->AppendTo(cursor,
+                                new(Z) CheckArrayBoundInstr(
+                                    new(Z) Value(length),
+                                    new(Z) Value(index),
+                                    call->deopt_id()),
+                                call->env(),
+                                FlowGraph::kEffect);
+
+  LoadIndexedInstr* load_indexed = new(Z) LoadIndexedInstr(
+      new(Z) Value(str),
+      new(Z) Value(index),
+      Instance::ElementSizeFor(cid),
+      cid,
+      Thread::kNoDeoptId,
+      call->token_pos());
+
+  cursor = flow_graph->AppendTo(cursor, load_indexed, NULL, FlowGraph::kValue);
+  ASSERT(cursor == load_indexed);
+  return load_indexed;
+}
+
+
+static bool InlineStringBaseCharAt(
+    FlowGraph* flow_graph,
+    Instruction* call,
+    intptr_t cid,
+    TargetEntryInstr** entry,
+    Definition** last) {
+  // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp.
+  if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) {
+    return false;
+  }
+  Definition* str = call->ArgumentAt(0);
+  Definition* index = call->ArgumentAt(1);
+
+  *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
+                                   call->GetBlock()->try_index());
+  (*entry)->InheritDeoptTarget(Z, call);
+
+  *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry);
+
+  StringFromCharCodeInstr* char_at = new(Z) StringFromCharCodeInstr(
+      new(Z) Value(*last), cid);
+
+  flow_graph->AppendTo(*last, char_at, NULL, FlowGraph::kValue);
+  *last = char_at;
+
+  return true;
+}
+
+
+static bool InlineStringCodeUnitAt(
+    FlowGraph* flow_graph,
+    Instruction* call,
+    intptr_t cid,
+    TargetEntryInstr** entry,
+    Definition** last) {
+  // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp.
+  if (RawObject::IsExternalStringClassId(cid)) {
+    return false;
+  }
+
+  Definition* str = call->ArgumentAt(0);
+  Definition* index = call->ArgumentAt(1);
+
+  *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
+                                   call->GetBlock()->try_index());
+  (*entry)->InheritDeoptTarget(Z, call);
+
+  *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry);
+
+  return true;
+}
+
+
+bool FlowGraphInliner::TryInlineRecognizedMethod(FlowGraph* flow_graph,
+                                                 intptr_t receiver_cid,
+                                                 const Function& target,
+                                                 Instruction* call,
+                                                 Definition* receiver,
+                                                 TokenPosition token_pos,
+                                                 const ICData& ic_data,
+                                                 TargetEntryInstr** entry,
+                                                 Definition** last) {
+  ICData& value_check = ICData::ZoneHandle(Z);
+  MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target);
+  switch (kind) {
+    // Recognized [] operators.
+    case MethodRecognizer::kImmutableArrayGetIndexed:
+    case MethodRecognizer::kObjectArrayGetIndexed:
+    case MethodRecognizer::kGrowableArrayGetIndexed:
+    case MethodRecognizer::kInt8ArrayGetIndexed:
+    case MethodRecognizer::kUint8ArrayGetIndexed:
+    case MethodRecognizer::kUint8ClampedArrayGetIndexed:
+    case MethodRecognizer::kExternalUint8ArrayGetIndexed:
+    case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
+    case MethodRecognizer::kInt16ArrayGetIndexed:
+    case MethodRecognizer::kUint16ArrayGetIndexed:
+      return InlineGetIndexed(flow_graph, kind, call, receiver, entry, last);
+    case MethodRecognizer::kFloat32ArrayGetIndexed:
+    case MethodRecognizer::kFloat64ArrayGetIndexed:
+      if (!CanUnboxDouble()) {
+        return false;
+      }
+      return InlineGetIndexed(flow_graph, kind, call, receiver, entry, last);
+    case MethodRecognizer::kFloat32x4ArrayGetIndexed:
+    case MethodRecognizer::kFloat64x2ArrayGetIndexed:
+      if (!ShouldInlineSimd()) {
+        return false;
+      }
+      return InlineGetIndexed(flow_graph, kind, call, receiver, entry, last);
+    case MethodRecognizer::kInt32ArrayGetIndexed:
+    case MethodRecognizer::kUint32ArrayGetIndexed:
+      if (!CanUnboxInt32()) return false;
+      return InlineGetIndexed(flow_graph, kind, call, receiver, entry, last);
+
+    case MethodRecognizer::kInt64ArrayGetIndexed:
+      if (!ShouldInlineInt64ArrayOps()) {
+        return false;
+      }
+      return InlineGetIndexed(flow_graph, kind, call, receiver, entry, last);
+    // Recognized []= operators.
+    case MethodRecognizer::kObjectArraySetIndexed:
+    case MethodRecognizer::kGrowableArraySetIndexed:
+      return InlineSetIndexed(flow_graph, kind, target, call, receiver,
+                              token_pos, value_check, entry, last);
+    case MethodRecognizer::kInt8ArraySetIndexed:
+    case MethodRecognizer::kUint8ArraySetIndexed:
+    case MethodRecognizer::kUint8ClampedArraySetIndexed:
+    case MethodRecognizer::kExternalUint8ArraySetIndexed:
+    case MethodRecognizer::kExternalUint8ClampedArraySetIndexed:
+    case MethodRecognizer::kInt16ArraySetIndexed:
+    case MethodRecognizer::kUint16ArraySetIndexed:
+      // Optimistically assume Smi.
+      if (ic_data.HasDeoptReason(ICData::kDeoptCheckSmi)) {
+        // Optimistic assumption failed at least once.
+        return false;
+      }
+      value_check = ic_data.AsUnaryClassChecksForCid(kSmiCid, target);
+      return InlineSetIndexed(flow_graph, kind, target, call, receiver,
+                              token_pos, value_check, entry, last);
+    case MethodRecognizer::kInt32ArraySetIndexed:
+    case MethodRecognizer::kUint32ArraySetIndexed: {
+      // Value check not needed for Int32 and Uint32 arrays because they
+      // implicitly contain unboxing instructions which check for right type.
+      ICData& value_check = ICData::Handle();
+      return InlineSetIndexed(flow_graph, kind, target, call, receiver,
+                              token_pos, value_check, entry, last);
+    }
+    case MethodRecognizer::kInt64ArraySetIndexed:
+      if (!ShouldInlineInt64ArrayOps()) {
+        return false;
+      }
+      return InlineSetIndexed(flow_graph, kind, target, call, receiver,
+                              token_pos, value_check, entry, last);
+    case MethodRecognizer::kFloat32ArraySetIndexed:
+    case MethodRecognizer::kFloat64ArraySetIndexed:
+      if (!CanUnboxDouble()) {
+        return false;
+      }
+      value_check = ic_data.AsUnaryClassChecksForCid(kDoubleCid, target);
+      return InlineSetIndexed(flow_graph, kind, target, call, receiver,
+                              token_pos, value_check, entry, last);
+    case MethodRecognizer::kFloat32x4ArraySetIndexed:
+      if (!ShouldInlineSimd()) {
+        return false;
+      }
+      value_check = ic_data.AsUnaryClassChecksForCid(kFloat32x4Cid, target);
+
+      return InlineSetIndexed(flow_graph, kind, target, call, receiver,
+                              token_pos, value_check, entry, last);
+    case MethodRecognizer::kFloat64x2ArraySetIndexed:
+      if (!ShouldInlineSimd()) {
+        return false;
+      }
+      value_check = ic_data.AsUnaryClassChecksForCid(kFloat64x2Cid, target);
+      return InlineSetIndexed(flow_graph, kind, target, call, receiver,
+                              token_pos, value_check, entry, last);
+    case MethodRecognizer::kByteArrayBaseGetInt8:
+      return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+                                     kTypedDataInt8ArrayCid,
+                                     entry, last);
+    case MethodRecognizer::kByteArrayBaseGetUint8:
+      return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+                                     kTypedDataUint8ArrayCid,
+                                     entry, last);
+    case MethodRecognizer::kByteArrayBaseGetInt16:
+      return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+                                     kTypedDataInt16ArrayCid,
+                                     entry, last);
+    case MethodRecognizer::kByteArrayBaseGetUint16:
+      return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+                                     kTypedDataUint16ArrayCid,
+                                     entry, last);
+    case MethodRecognizer::kByteArrayBaseGetInt32:
+      if (!CanUnboxInt32()) {
+        return false;
+      }
+      return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+                                     kTypedDataInt32ArrayCid,
+                                     entry, last);
+    case MethodRecognizer::kByteArrayBaseGetUint32:
+      if (!CanUnboxInt32()) {
+        return false;
+      }
+      return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+                                     kTypedDataUint32ArrayCid,
+                                     entry, last);
+    case MethodRecognizer::kByteArrayBaseGetFloat32:
+      if (!CanUnboxDouble()) {
+        return false;
+      }
+      return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+                                     kTypedDataFloat32ArrayCid,
+                                     entry, last);
+    case MethodRecognizer::kByteArrayBaseGetFloat64:
+      if (!CanUnboxDouble()) {
+        return false;
+      }
+      return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+                                     kTypedDataFloat64ArrayCid,
+                                     entry, last);
+    case MethodRecognizer::kByteArrayBaseGetFloat32x4:
+      if (!ShouldInlineSimd()) {
+        return false;
+      }
+      return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+                                     kTypedDataFloat32x4ArrayCid,
+                                     entry, last);
+    case MethodRecognizer::kByteArrayBaseGetInt32x4:
+      if (!ShouldInlineSimd()) {
+        return false;
+      }
+      return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+                                     kTypedDataInt32x4ArrayCid,
+                                     entry, last);
+    case MethodRecognizer::kByteArrayBaseSetInt8:
+      return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+                                      receiver_cid, kTypedDataInt8ArrayCid,
+                                      entry, last);
+    case MethodRecognizer::kByteArrayBaseSetUint8:
+      return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+                                      receiver_cid,
+                                      kTypedDataUint8ArrayCid,
+                                      entry, last);
+    case MethodRecognizer::kByteArrayBaseSetInt16:
+      return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+                                      receiver_cid,
+                                      kTypedDataInt16ArrayCid,
+                                      entry, last);
+    case MethodRecognizer::kByteArrayBaseSetUint16:
+      return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+                                      receiver_cid,
+                                      kTypedDataUint16ArrayCid,
+                                      entry, last);
+    case MethodRecognizer::kByteArrayBaseSetInt32:
+      return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+                                      receiver_cid,
+                                      kTypedDataInt32ArrayCid,
+                                      entry, last);
+    case MethodRecognizer::kByteArrayBaseSetUint32:
+      return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+                                      receiver_cid,
+                                      kTypedDataUint32ArrayCid,
+                                      entry, last);
+    case MethodRecognizer::kByteArrayBaseSetFloat32:
+      if (!CanUnboxDouble()) {
+        return false;
+      }
+      return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+                                      receiver_cid,
+                                      kTypedDataFloat32ArrayCid,
+                                      entry, last);
+    case MethodRecognizer::kByteArrayBaseSetFloat64:
+      if (!CanUnboxDouble()) {
+        return false;
+      }
+      return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+                                      receiver_cid,
+                                      kTypedDataFloat64ArrayCid,
+                                      entry, last);
+    case MethodRecognizer::kByteArrayBaseSetFloat32x4:
+      if (!ShouldInlineSimd()) {
+        return false;
+      }
+      return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+                                      receiver_cid,
+                                      kTypedDataFloat32x4ArrayCid,
+                                      entry, last);
+    case MethodRecognizer::kByteArrayBaseSetInt32x4:
+      if (!ShouldInlineSimd()) {
+        return false;
+      }
+      return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+                                      receiver_cid,
+                                      kTypedDataInt32x4ArrayCid,
+                                      entry, last);
+    case MethodRecognizer::kStringBaseCodeUnitAt:
+      return InlineStringCodeUnitAt(
+          flow_graph, call, receiver_cid, entry, last);
+    case MethodRecognizer::kStringBaseCharAt:
+      return InlineStringBaseCharAt(
+          flow_graph, call, receiver_cid, entry, last);
+    case MethodRecognizer::kDoubleAdd:
+      return InlineDoubleOp(flow_graph, Token::kADD, call, entry, last);
+    case MethodRecognizer::kDoubleSub:
+      return InlineDoubleOp(flow_graph, Token::kSUB, call, entry, last);
+    case MethodRecognizer::kDoubleMul:
+      return InlineDoubleOp(flow_graph, Token::kMUL, call, entry, last);
+    case MethodRecognizer::kDoubleDiv:
+      return InlineDoubleOp(flow_graph, Token::kDIV, call, entry, last);
+    default:
+      return false;
+  }
+}
+
+
 }  // namespace dart
diff --git a/runtime/vm/flow_graph_inliner.h b/runtime/vm/flow_graph_inliner.h
index 6e3ce09..c4d8ca2 100644
--- a/runtime/vm/flow_graph_inliner.h
+++ b/runtime/vm/flow_graph_inliner.h
@@ -10,9 +10,12 @@
 
 namespace dart {
 
+class Definition;
 class Field;
 class FlowGraph;
 class Function;
+class Instruction;
+class TargetEntryInstr;
 
 class FlowGraphInliner : ValueObject {
  public:
@@ -36,6 +39,16 @@
 
   bool trace_inlining() const { return trace_inlining_; }
 
+  static bool TryInlineRecognizedMethod(FlowGraph* flow_graph,
+                                        intptr_t receiver_cid,
+                                        const Function& target,
+                                        Instruction* call,
+                                        Definition* receiver,
+                                        TokenPosition token_pos,
+                                        const ICData& ic_data,
+                                        TargetEntryInstr** entry,
+                                        Definition** last);
+
  private:
   friend class CallSiteInliner;
 
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index f10954a..b4c3a2a 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -13,6 +13,7 @@
 #include "vm/exceptions.h"
 #include "vm/flow_graph_builder.h"
 #include "vm/flow_graph_compiler.h"
+#include "vm/flow_graph_inliner.h"
 #include "vm/flow_graph_range_analysis.h"
 #include "vm/hash_map.h"
 #include "vm/il_printer.h"
@@ -49,11 +50,8 @@
 
 DECLARE_FLAG(bool, precompilation);
 DECLARE_FLAG(bool, polymorphic_with_deopt);
-DECLARE_FLAG(bool, source_lines);
 DECLARE_FLAG(bool, trace_cha);
 DECLARE_FLAG(bool, trace_field_guards);
-DECLARE_FLAG(bool, trace_type_check_elimination);
-DECLARE_FLAG(bool, warn_on_javascript_compatibility);
 
 // Quick access to the current isolate and zone.
 #define I (isolate())
@@ -69,13 +67,6 @@
 }
 
 
-static bool ShouldInlineInt64ArrayOps() {
-#if defined(TARGET_ARCH_X64)
-  return true;
-#endif
-  return false;
-}
-
 static bool CanConvertUnboxedMintToDouble() {
 #if defined(TARGET_ARCH_IA32)
   return true;
@@ -97,9 +88,10 @@
 
 void FlowGraphOptimizer::PopulateWithICData() {
   ASSERT(current_iterator_ == NULL);
-  for (intptr_t i = 0; i < block_order_.length(); ++i) {
-    BlockEntryInstr* entry = block_order_[i];
-    ForwardInstructionIterator it(entry);
+  for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
+       !block_it.Done();
+       block_it.Advance()) {
+    ForwardInstructionIterator it(block_it.Current());
     for (; !it.Done(); it.Advance()) {
       Instruction* instr = it.Current();
       if (instr->IsInstanceCall()) {
@@ -130,9 +122,10 @@
 // e.g., receiver class id, guarded-cid, or by guessing cid-s.
 void FlowGraphOptimizer::ApplyClassIds() {
   ASSERT(current_iterator_ == NULL);
-  for (intptr_t i = 0; i < block_order_.length(); ++i) {
-    BlockEntryInstr* entry = block_order_[i];
-    ForwardInstructionIterator it(entry);
+  for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
+       !block_it.Done();
+       block_it.Advance()) {
+    ForwardInstructionIterator it(block_it.Current());
     current_iterator_ = &it;
     for (; !it.Done(); it.Advance()) {
       Instruction* instr = it.Current();
@@ -172,14 +165,6 @@
     // to megamorphic call.
     return false;
   }
-  if (FLAG_warn_on_javascript_compatibility) {
-    // Do not make the instance call megamorphic if the callee needs to decode
-    // the calling code sequence to lookup the ic data and verify if a warning
-    // has already been issued or not.
-    if (call->ic_data()->MayCheckForJSWarning()) {
-      return false;
-    }
-  }
   GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested());
   ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount());
   for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) {
@@ -418,28 +403,6 @@
 }
 
 
-
-// Used by TryMergeDivMod.
-// Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction,
-// and the using instruction. This is an intermediate step before merging.
-void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr,
-                                                    intptr_t ix,
-                                                    intptr_t cid) {
-  const intptr_t index_scale = Instance::ElementSizeFor(cid);
-  ConstantInstr* index_instr =
-      flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(ix)));
-  LoadIndexedInstr* load =
-      new(Z) LoadIndexedInstr(new(Z) Value(instr),
-                                      new(Z) Value(index_instr),
-                                      index_scale,
-                                      cid,
-                                      Thread::kNoDeoptId,
-                                      instr->token_pos());
-  instr->ReplaceUsesWith(load);
-  flow_graph()->InsertAfter(instr, load, NULL, FlowGraph::kValue);
-}
-
-
 void FlowGraphOptimizer::AppendExtractNthOutputForMerged(Definition* instr,
                                                          intptr_t index,
                                                          Representation rep,
@@ -595,12 +558,13 @@
   ASSERT(current_iterator_ == NULL);
   GrowableArray<BinarySmiOpInstr*> div_mod_merge;
   GrowableArray<MathUnaryInstr*> sin_cos_merge;
-  for (intptr_t i = 0; i < block_order_.length(); ++i) {
+  for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
+       !block_it.Done();
+       block_it.Advance()) {
     // Merging only per basic-block.
     div_mod_merge.Clear();
     sin_cos_merge.Clear();
-    BlockEntryInstr* entry = block_order_[i];
-    ForwardInstructionIterator it(entry);
+    ForwardInstructionIterator it(block_it.Current());
     current_iterator_ = &it;
     for (; !it.Done(); it.Advance()) {
       if (it.Current()->IsBinarySmiOp()) {
@@ -641,9 +605,13 @@
 
 bool FlowGraphOptimizer::Canonicalize() {
   bool changed = false;
-  for (intptr_t i = 0; i < block_order_.length(); ++i) {
-    BlockEntryInstr* entry = block_order_[i];
-    for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
+
+  for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
+       !block_it.Done();
+       block_it.Advance()) {
+    for (ForwardInstructionIterator it(block_it.Current());
+         !it.Done();
+         it.Advance()) {
       Instruction* current = it.Current();
       if (current->HasUnmatchedInputRepresentations()) {
         // Can't canonicalize this instruction until all conversions for its
@@ -875,8 +843,10 @@
 void FlowGraphOptimizer::SelectRepresentations() {
   // Conservatively unbox all phis that were proven to be of Double,
   // Float32x4, or Int32x4 type.
-  for (intptr_t i = 0; i < block_order_.length(); ++i) {
-    JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry();
+  for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
+       !block_it.Done();
+       block_it.Advance()) {
+    JoinEntryInstr* join_entry = block_it.Current()->AsJoinEntry();
     if (join_entry != NULL) {
       for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
         PhiInstr* phi = it.Current();
@@ -886,15 +856,17 @@
   }
 
   // Process all instructions and insert conversions where needed.
-  GraphEntryInstr* graph_entry = block_order_[0]->AsGraphEntry();
+  GraphEntryInstr* graph_entry = flow_graph_->graph_entry();
 
   // Visit incoming parameters and constants.
   for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) {
     InsertConversionsFor((*graph_entry->initial_definitions())[i]);
   }
 
-  for (intptr_t i = 0; i < block_order_.length(); ++i) {
-    BlockEntryInstr* entry = block_order_[i];
+  for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
+       !block_it.Done();
+       block_it.Advance()) {
+    BlockEntryInstr* entry = block_it.Current();
     JoinEntryInstr* join_entry = entry->AsJoinEntry();
     if (join_entry != NULL) {
       for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
@@ -1138,93 +1110,6 @@
 }
 
 
-static bool CanUnboxInt32() {
-  // Int32/Uint32 can be unboxed if it fits into a smi or the platform
-  // supports unboxed mints.
-  return (kSmiBits >= 32) || FlowGraphCompiler::SupportsUnboxedMints();
-}
-
-
-static intptr_t MethodKindToCid(MethodRecognizer::Kind kind) {
-  switch (kind) {
-    case MethodRecognizer::kImmutableArrayGetIndexed:
-      return kImmutableArrayCid;
-
-    case MethodRecognizer::kObjectArrayGetIndexed:
-    case MethodRecognizer::kObjectArraySetIndexed:
-      return kArrayCid;
-
-    case MethodRecognizer::kGrowableArrayGetIndexed:
-    case MethodRecognizer::kGrowableArraySetIndexed:
-      return kGrowableObjectArrayCid;
-
-    case MethodRecognizer::kFloat32ArrayGetIndexed:
-    case MethodRecognizer::kFloat32ArraySetIndexed:
-      return kTypedDataFloat32ArrayCid;
-
-    case MethodRecognizer::kFloat64ArrayGetIndexed:
-    case MethodRecognizer::kFloat64ArraySetIndexed:
-      return kTypedDataFloat64ArrayCid;
-
-    case MethodRecognizer::kInt8ArrayGetIndexed:
-    case MethodRecognizer::kInt8ArraySetIndexed:
-      return kTypedDataInt8ArrayCid;
-
-    case MethodRecognizer::kUint8ArrayGetIndexed:
-    case MethodRecognizer::kUint8ArraySetIndexed:
-      return kTypedDataUint8ArrayCid;
-
-    case MethodRecognizer::kUint8ClampedArrayGetIndexed:
-    case MethodRecognizer::kUint8ClampedArraySetIndexed:
-      return kTypedDataUint8ClampedArrayCid;
-
-    case MethodRecognizer::kExternalUint8ArrayGetIndexed:
-    case MethodRecognizer::kExternalUint8ArraySetIndexed:
-      return kExternalTypedDataUint8ArrayCid;
-
-    case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
-    case MethodRecognizer::kExternalUint8ClampedArraySetIndexed:
-      return kExternalTypedDataUint8ClampedArrayCid;
-
-    case MethodRecognizer::kInt16ArrayGetIndexed:
-    case MethodRecognizer::kInt16ArraySetIndexed:
-      return kTypedDataInt16ArrayCid;
-
-    case MethodRecognizer::kUint16ArrayGetIndexed:
-    case MethodRecognizer::kUint16ArraySetIndexed:
-      return kTypedDataUint16ArrayCid;
-
-    case MethodRecognizer::kInt32ArrayGetIndexed:
-    case MethodRecognizer::kInt32ArraySetIndexed:
-      return kTypedDataInt32ArrayCid;
-
-    case MethodRecognizer::kUint32ArrayGetIndexed:
-    case MethodRecognizer::kUint32ArraySetIndexed:
-      return kTypedDataUint32ArrayCid;
-
-    case MethodRecognizer::kInt64ArrayGetIndexed:
-    case MethodRecognizer::kInt64ArraySetIndexed:
-      return kTypedDataInt64ArrayCid;
-
-    case MethodRecognizer::kFloat32x4ArrayGetIndexed:
-    case MethodRecognizer::kFloat32x4ArraySetIndexed:
-      return kTypedDataFloat32x4ArrayCid;
-
-    case MethodRecognizer::kInt32x4ArrayGetIndexed:
-    case MethodRecognizer::kInt32x4ArraySetIndexed:
-      return kTypedDataInt32x4ArrayCid;
-
-    case MethodRecognizer::kFloat64x2ArrayGetIndexed:
-    case MethodRecognizer::kFloat64x2ArraySetIndexed:
-      return kTypedDataFloat64x2ArrayCid;
-
-    default:
-      break;
-  }
-  return kIllegalCid;
-}
-
-
 bool FlowGraphOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) {
   // Check for monomorphic IC data.
   if (!call->HasICData()) return false;
@@ -1237,530 +1122,6 @@
 }
 
 
-bool FlowGraphOptimizer::InlineSetIndexed(
-    MethodRecognizer::Kind kind,
-    const Function& target,
-    Instruction* call,
-    Definition* receiver,
-    TokenPosition token_pos,
-    const ICData& value_check,
-    TargetEntryInstr** entry,
-    Definition** last) {
-  intptr_t array_cid = MethodKindToCid(kind);
-  ASSERT(array_cid != kIllegalCid);
-
-  Definition* array = receiver;
-  Definition* index = call->ArgumentAt(1);
-  Definition* stored_value = call->ArgumentAt(2);
-
-  *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
-                                   call->GetBlock()->try_index());
-  (*entry)->InheritDeoptTarget(Z, call);
-  Instruction* cursor = *entry;
-  if (I->flags().type_checks()) {
-    // Only type check for the value. A type check for the index is not
-    // needed here because we insert a deoptimizing smi-check for the case
-    // the index is not a smi.
-    const AbstractType& value_type =
-        AbstractType::ZoneHandle(Z, target.ParameterTypeAt(2));
-    Definition* type_args = NULL;
-    switch (array_cid) {
-      case kArrayCid:
-      case kGrowableObjectArrayCid: {
-        const Class& instantiator_class =  Class::Handle(Z, target.Owner());
-        intptr_t type_arguments_field_offset =
-            instantiator_class.type_arguments_field_offset();
-        LoadFieldInstr* load_type_args =
-            new(Z) LoadFieldInstr(new(Z) Value(array),
-                                  type_arguments_field_offset,
-                                  Type::ZoneHandle(Z),  // No type.
-                                  call->token_pos());
-        cursor = flow_graph()->AppendTo(cursor,
-                                        load_type_args,
-                                        NULL,
-                                        FlowGraph::kValue);
-
-        type_args = load_type_args;
-        break;
-      }
-      case kTypedDataInt8ArrayCid:
-      case kTypedDataUint8ArrayCid:
-      case kTypedDataUint8ClampedArrayCid:
-      case kExternalTypedDataUint8ArrayCid:
-      case kExternalTypedDataUint8ClampedArrayCid:
-      case kTypedDataInt16ArrayCid:
-      case kTypedDataUint16ArrayCid:
-      case kTypedDataInt32ArrayCid:
-      case kTypedDataUint32ArrayCid:
-      case kTypedDataInt64ArrayCid:
-        ASSERT(value_type.IsIntType());
-        // Fall through.
-      case kTypedDataFloat32ArrayCid:
-      case kTypedDataFloat64ArrayCid: {
-        type_args = flow_graph_->constant_null();
-        ASSERT((array_cid != kTypedDataFloat32ArrayCid &&
-                array_cid != kTypedDataFloat64ArrayCid) ||
-               value_type.IsDoubleType());
-        ASSERT(value_type.IsInstantiated());
-        break;
-      }
-      case kTypedDataFloat32x4ArrayCid: {
-        type_args = flow_graph_->constant_null();
-        ASSERT((array_cid != kTypedDataFloat32x4ArrayCid) ||
-               value_type.IsFloat32x4Type());
-        ASSERT(value_type.IsInstantiated());
-        break;
-      }
-      case kTypedDataFloat64x2ArrayCid: {
-        type_args = flow_graph_->constant_null();
-        ASSERT((array_cid != kTypedDataFloat64x2ArrayCid) ||
-               value_type.IsFloat64x2Type());
-        ASSERT(value_type.IsInstantiated());
-        break;
-      }
-      default:
-        // TODO(fschneider): Add support for other array types.
-        UNREACHABLE();
-    }
-    AssertAssignableInstr* assert_value =
-        new(Z) AssertAssignableInstr(token_pos,
-                                     new(Z) Value(stored_value),
-                                     new(Z) Value(type_args),
-                                     value_type,
-                                     Symbols::Value(),
-                                     call->deopt_id());
-    cursor = flow_graph()->AppendTo(cursor,
-                                    assert_value,
-                                    call->env(),
-                                    FlowGraph::kValue);
-  }
-
-  array_cid = PrepareInlineIndexedOp(call,
-                                     array_cid,
-                                     &array,
-                                     index,
-                                     &cursor);
-
-  // Check if store barrier is needed. Byte arrays don't need a store barrier.
-  StoreBarrierType needs_store_barrier =
-      (RawObject::IsTypedDataClassId(array_cid) ||
-       RawObject::IsTypedDataViewClassId(array_cid) ||
-       RawObject::IsExternalTypedDataClassId(array_cid)) ? kNoStoreBarrier
-                                                         : kEmitStoreBarrier;
-
-  // No need to class check stores to Int32 and Uint32 arrays because
-  // we insert unboxing instructions below which include a class check.
-  if ((array_cid != kTypedDataUint32ArrayCid) &&
-      (array_cid != kTypedDataInt32ArrayCid) &&
-      !value_check.IsNull()) {
-    // No store barrier needed because checked value is a smi, an unboxed mint,
-    // an unboxed double, an unboxed Float32x4, or unboxed Int32x4.
-    needs_store_barrier = kNoStoreBarrier;
-    Instruction* check = GetCheckClass(
-        stored_value, value_check, call->deopt_id(), call->token_pos());
-    cursor = flow_graph()->AppendTo(cursor,
-                                    check,
-                                    call->env(),
-                                    FlowGraph::kEffect);
-  }
-
-  if (array_cid == kTypedDataFloat32ArrayCid) {
-    stored_value =
-        new(Z) DoubleToFloatInstr(
-            new(Z) Value(stored_value), call->deopt_id());
-    cursor = flow_graph()->AppendTo(cursor,
-                                    stored_value,
-                                    NULL,
-                                    FlowGraph::kValue);
-  } else if (array_cid == kTypedDataInt32ArrayCid) {
-    stored_value = new(Z) UnboxInt32Instr(
-        UnboxInt32Instr::kTruncate,
-        new(Z) Value(stored_value),
-        call->deopt_id());
-    cursor = flow_graph()->AppendTo(cursor,
-                                    stored_value,
-                                    call->env(),
-                                    FlowGraph::kValue);
-  } else if (array_cid == kTypedDataUint32ArrayCid) {
-    stored_value = new(Z) UnboxUint32Instr(
-        new(Z) Value(stored_value),
-        call->deopt_id());
-    ASSERT(stored_value->AsUnboxInteger()->is_truncating());
-    cursor = flow_graph()->AppendTo(cursor,
-                                    stored_value,
-                                    call->env(),
-                                    FlowGraph::kValue);
-  }
-
-  const intptr_t index_scale = Instance::ElementSizeFor(array_cid);
-  *last = new(Z) StoreIndexedInstr(new(Z) Value(array),
-                                   new(Z) Value(index),
-                                   new(Z) Value(stored_value),
-                                   needs_store_barrier,
-                                   index_scale,
-                                   array_cid,
-                                   call->deopt_id(),
-                                   call->token_pos());
-  flow_graph()->AppendTo(cursor,
-                         *last,
-                         call->env(),
-                         FlowGraph::kEffect);
-  return true;
-}
-
-
-bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid,
-                                                   const Function& target,
-                                                   Instruction* call,
-                                                   Definition* receiver,
-                                                   TokenPosition token_pos,
-                                                   const ICData& ic_data,
-                                                   TargetEntryInstr** entry,
-                                                   Definition** last) {
-  ICData& value_check = ICData::ZoneHandle(Z);
-  MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target);
-  switch (kind) {
-    // Recognized [] operators.
-    case MethodRecognizer::kImmutableArrayGetIndexed:
-    case MethodRecognizer::kObjectArrayGetIndexed:
-    case MethodRecognizer::kGrowableArrayGetIndexed:
-    case MethodRecognizer::kInt8ArrayGetIndexed:
-    case MethodRecognizer::kUint8ArrayGetIndexed:
-    case MethodRecognizer::kUint8ClampedArrayGetIndexed:
-    case MethodRecognizer::kExternalUint8ArrayGetIndexed:
-    case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
-    case MethodRecognizer::kInt16ArrayGetIndexed:
-    case MethodRecognizer::kUint16ArrayGetIndexed:
-      return InlineGetIndexed(kind, call, receiver, entry, last);
-    case MethodRecognizer::kFloat32ArrayGetIndexed:
-    case MethodRecognizer::kFloat64ArrayGetIndexed:
-      if (!CanUnboxDouble()) {
-        return false;
-      }
-      return InlineGetIndexed(kind, call, receiver, entry, last);
-    case MethodRecognizer::kFloat32x4ArrayGetIndexed:
-    case MethodRecognizer::kFloat64x2ArrayGetIndexed:
-      if (!ShouldInlineSimd()) {
-        return false;
-      }
-      return InlineGetIndexed(kind, call, receiver, entry, last);
-    case MethodRecognizer::kInt32ArrayGetIndexed:
-    case MethodRecognizer::kUint32ArrayGetIndexed:
-      if (!CanUnboxInt32()) return false;
-      return InlineGetIndexed(kind, call, receiver, entry, last);
-
-    case MethodRecognizer::kInt64ArrayGetIndexed:
-      if (!ShouldInlineInt64ArrayOps()) {
-        return false;
-      }
-      return InlineGetIndexed(kind, call, receiver, entry, last);
-    // Recognized []= operators.
-    case MethodRecognizer::kObjectArraySetIndexed:
-    case MethodRecognizer::kGrowableArraySetIndexed:
-      return InlineSetIndexed(kind, target, call, receiver, token_pos,
-                              value_check, entry, last);
-    case MethodRecognizer::kInt8ArraySetIndexed:
-    case MethodRecognizer::kUint8ArraySetIndexed:
-    case MethodRecognizer::kUint8ClampedArraySetIndexed:
-    case MethodRecognizer::kExternalUint8ArraySetIndexed:
-    case MethodRecognizer::kExternalUint8ClampedArraySetIndexed:
-    case MethodRecognizer::kInt16ArraySetIndexed:
-    case MethodRecognizer::kUint16ArraySetIndexed:
-      // Optimistically assume Smi.
-      if (ic_data.HasDeoptReason(ICData::kDeoptCheckSmi)) {
-        // Optimistic assumption failed at least once.
-        return false;
-      }
-      value_check = ic_data.AsUnaryClassChecksForCid(kSmiCid, target);
-      return InlineSetIndexed(kind, target, call, receiver, token_pos,
-                              value_check, entry, last);
-    case MethodRecognizer::kInt32ArraySetIndexed:
-    case MethodRecognizer::kUint32ArraySetIndexed: {
-      // Value check not needed for Int32 and Uint32 arrays because they
-      // implicitly contain unboxing instructions which check for right type.
-      ICData& value_check = ICData::Handle();
-      return InlineSetIndexed(kind, target, call, receiver, token_pos,
-                              value_check, entry, last);
-    }
-    case MethodRecognizer::kInt64ArraySetIndexed:
-      if (!ShouldInlineInt64ArrayOps()) {
-        return false;
-      }
-      return InlineSetIndexed(kind, target, call, receiver, token_pos,
-                              value_check, entry, last);
-    case MethodRecognizer::kFloat32ArraySetIndexed:
-    case MethodRecognizer::kFloat64ArraySetIndexed:
-      if (!CanUnboxDouble()) {
-        return false;
-      }
-      value_check = ic_data.AsUnaryClassChecksForCid(kDoubleCid, target);
-      return InlineSetIndexed(kind, target, call, receiver, token_pos,
-                              value_check, entry, last);
-    case MethodRecognizer::kFloat32x4ArraySetIndexed:
-      if (!ShouldInlineSimd()) {
-        return false;
-      }
-      value_check = ic_data.AsUnaryClassChecksForCid(kFloat32x4Cid, target);
-
-      return InlineSetIndexed(kind, target, call, receiver, token_pos,
-                              value_check, entry, last);
-    case MethodRecognizer::kFloat64x2ArraySetIndexed:
-      if (!ShouldInlineSimd()) {
-        return false;
-      }
-      value_check = ic_data.AsUnaryClassChecksForCid(kFloat64x2Cid, target);
-      return InlineSetIndexed(kind, target, call, receiver, token_pos,
-                              value_check, entry, last);
-    case MethodRecognizer::kByteArrayBaseGetInt8:
-      return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
-                                     kTypedDataInt8ArrayCid,
-                                     ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseGetUint8:
-      return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
-                                     kTypedDataUint8ArrayCid,
-                                     ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseGetInt16:
-      return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
-                                     kTypedDataInt16ArrayCid,
-                                     ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseGetUint16:
-      return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
-                                     kTypedDataUint16ArrayCid,
-                                     ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseGetInt32:
-      if (!CanUnboxInt32()) {
-        return false;
-      }
-      return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
-                                     kTypedDataInt32ArrayCid,
-                                     ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseGetUint32:
-      if (!CanUnboxInt32()) {
-        return false;
-      }
-      return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
-                                     kTypedDataUint32ArrayCid,
-                                     ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseGetFloat32:
-      if (!CanUnboxDouble()) {
-        return false;
-      }
-      return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
-                                     kTypedDataFloat32ArrayCid,
-                                     ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseGetFloat64:
-      if (!CanUnboxDouble()) {
-        return false;
-      }
-      return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
-                                     kTypedDataFloat64ArrayCid,
-                                     ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseGetFloat32x4:
-      if (!ShouldInlineSimd()) {
-        return false;
-      }
-      return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
-                                     kTypedDataFloat32x4ArrayCid,
-                                     ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseGetInt32x4:
-      if (!ShouldInlineSimd()) {
-        return false;
-      }
-      return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
-                                     kTypedDataInt32x4ArrayCid,
-                                     ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseSetInt8:
-      return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
-                                      kTypedDataInt8ArrayCid,
-                                      ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseSetUint8:
-      return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
-                                      kTypedDataUint8ArrayCid,
-                                      ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseSetInt16:
-      return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
-                                      kTypedDataInt16ArrayCid,
-                                      ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseSetUint16:
-      return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
-                                      kTypedDataUint16ArrayCid,
-                                      ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseSetInt32:
-      return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
-                                      kTypedDataInt32ArrayCid,
-                                      ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseSetUint32:
-      return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
-                                      kTypedDataUint32ArrayCid,
-                                      ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseSetFloat32:
-      if (!CanUnboxDouble()) {
-        return false;
-      }
-      return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
-                                      kTypedDataFloat32ArrayCid,
-                                      ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseSetFloat64:
-      if (!CanUnboxDouble()) {
-        return false;
-      }
-      return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
-                                      kTypedDataFloat64ArrayCid,
-                                      ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseSetFloat32x4:
-      if (!ShouldInlineSimd()) {
-        return false;
-      }
-      return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
-                                      kTypedDataFloat32x4ArrayCid,
-                                      ic_data, entry, last);
-    case MethodRecognizer::kByteArrayBaseSetInt32x4:
-      if (!ShouldInlineSimd()) {
-        return false;
-      }
-      return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
-                                      kTypedDataInt32x4ArrayCid,
-                                      ic_data, entry, last);
-    case MethodRecognizer::kStringBaseCodeUnitAt:
-      return InlineStringCodeUnitAt(call, receiver_cid, entry, last);
-    case MethodRecognizer::kStringBaseCharAt:
-      return InlineStringBaseCharAt(call, receiver_cid, entry, last);
-    case MethodRecognizer::kDoubleAdd:
-      return InlineDoubleOp(Token::kADD, call, entry, last);
-    case MethodRecognizer::kDoubleSub:
-      return InlineDoubleOp(Token::kSUB, call, entry, last);
-    case MethodRecognizer::kDoubleMul:
-      return InlineDoubleOp(Token::kMUL, call, entry, last);
-    case MethodRecognizer::kDoubleDiv:
-      return InlineDoubleOp(Token::kDIV, call, entry, last);
-    default:
-      return false;
-  }
-}
-
-
-intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call,
-                                                    intptr_t array_cid,
-                                                    Definition** array,
-                                                    Definition* index,
-                                                    Instruction** cursor) {
-  // Insert index smi check.
-  *cursor = flow_graph()->AppendTo(
-      *cursor,
-      new(Z) CheckSmiInstr(new(Z) Value(index),
-                           call->deopt_id(),
-                           call->token_pos()),
-      call->env(),
-      FlowGraph::kEffect);
-
-  // Insert array length load and bounds check.
-  LoadFieldInstr* length =
-      new(Z) LoadFieldInstr(
-          new(Z) Value(*array),
-          CheckArrayBoundInstr::LengthOffsetFor(array_cid),
-          Type::ZoneHandle(Z, Type::SmiType()),
-          call->token_pos());
-  length->set_is_immutable(
-      CheckArrayBoundInstr::IsFixedLengthArrayType(array_cid));
-  length->set_result_cid(kSmiCid);
-  length->set_recognized_kind(
-      LoadFieldInstr::RecognizedKindFromArrayCid(array_cid));
-  *cursor = flow_graph()->AppendTo(*cursor,
-                                   length,
-                                   NULL,
-                                   FlowGraph::kValue);
-
-  *cursor = flow_graph()->AppendTo(*cursor,
-                                   new(Z) CheckArrayBoundInstr(
-                                       new(Z) Value(length),
-                                       new(Z) Value(index),
-                                       call->deopt_id()),
-                                   call->env(),
-                                   FlowGraph::kEffect);
-
-  if (array_cid == kGrowableObjectArrayCid) {
-    // Insert data elements load.
-    LoadFieldInstr* elements =
-        new(Z) LoadFieldInstr(
-            new(Z) Value(*array),
-            GrowableObjectArray::data_offset(),
-            Object::dynamic_type(),
-            call->token_pos());
-    elements->set_result_cid(kArrayCid);
-    *cursor = flow_graph()->AppendTo(*cursor,
-                                     elements,
-                                     NULL,
-                                     FlowGraph::kValue);
-    // Load from the data from backing store which is a fixed-length array.
-    *array = elements;
-    array_cid = kArrayCid;
-  } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
-    LoadUntaggedInstr* elements =
-        new(Z) LoadUntaggedInstr(new(Z) Value(*array),
-                                 ExternalTypedData::data_offset());
-    *cursor = flow_graph()->AppendTo(*cursor,
-                                     elements,
-                                     NULL,
-                                     FlowGraph::kValue);
-    *array = elements;
-  }
-  return array_cid;
-}
-
-
-bool FlowGraphOptimizer::InlineGetIndexed(MethodRecognizer::Kind kind,
-                                          Instruction* call,
-                                          Definition* receiver,
-                                          TargetEntryInstr** entry,
-                                          Definition** last) {
-  intptr_t array_cid = MethodKindToCid(kind);
-  ASSERT(array_cid != kIllegalCid);
-
-  Definition* array = receiver;
-  Definition* index = call->ArgumentAt(1);
-  *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
-                                   call->GetBlock()->try_index());
-  (*entry)->InheritDeoptTarget(Z, call);
-  Instruction* cursor = *entry;
-
-  array_cid = PrepareInlineIndexedOp(call,
-                                     array_cid,
-                                     &array,
-                                     index,
-                                     &cursor);
-
-  intptr_t deopt_id = Thread::kNoDeoptId;
-  if ((array_cid == kTypedDataInt32ArrayCid) ||
-      (array_cid == kTypedDataUint32ArrayCid)) {
-    // Deoptimization may be needed if result does not always fit in a Smi.
-    deopt_id = (kSmiBits >= 32) ? Thread::kNoDeoptId : call->deopt_id();
-  }
-
-  // Array load and return.
-  intptr_t index_scale = Instance::ElementSizeFor(array_cid);
-  *last = new(Z) LoadIndexedInstr(new(Z) Value(array),
-                                  new(Z) Value(index),
-                                  index_scale,
-                                  array_cid,
-                                  deopt_id,
-                                  call->token_pos());
-  cursor = flow_graph()->AppendTo(
-      cursor,
-      *last,
-      deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
-      FlowGraph::kValue);
-
-  if (array_cid == kTypedDataFloat32ArrayCid) {
-    *last = new(Z) FloatToDoubleInstr(new(Z) Value(*last), deopt_id);
-    flow_graph()->AppendTo(cursor,
-                           *last,
-                           deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
-                           FlowGraph::kValue);
-  }
-  return true;
-}
-
-
 // Return true if d is a string of length one (a constant or result from
 // from string-from-char-code instruction.
 static bool IsLengthOneString(Definition* d) {
@@ -2692,13 +2053,14 @@
 
   TargetEntryInstr* entry;
   Definition* last;
-  if (!TryInlineRecognizedMethod(receiver_cid,
-                                 target,
-                                 call,
-                                 call->ArgumentAt(0),
-                                 call->token_pos(),
-                                 *call->ic_data(),
-                                 &entry, &last)) {
+  if (!FlowGraphInliner::TryInlineRecognizedMethod(flow_graph_,
+                                                   receiver_cid,
+                                                   target,
+                                                   call,
+                                                   call->ArgumentAt(0),
+                                                   call->token_pos(),
+                                                   *call->ic_data(),
+                                                   &entry, &last)) {
     return false;
   }
 
@@ -2726,136 +2088,6 @@
 }
 
 
-// Returns the LoadIndexedInstr.
-Definition* FlowGraphOptimizer::PrepareInlineStringIndexOp(
-    Instruction* call,
-    intptr_t cid,
-    Definition* str,
-    Definition* index,
-    Instruction* cursor) {
-
-  cursor = flow_graph()->AppendTo(cursor,
-                                  new(Z) CheckSmiInstr(
-                                      new(Z) Value(index),
-                                      call->deopt_id(),
-                                      call->token_pos()),
-                                  call->env(),
-                                  FlowGraph::kEffect);
-
-  // Load the length of the string.
-  // Treat length loads as mutable (i.e. affected by side effects) to avoid
-  // hoisting them since we can't hoist the preceding class-check. This
-  // is because of externalization of strings that affects their class-id.
-  LoadFieldInstr* length = new(Z) LoadFieldInstr(
-      new(Z) Value(str),
-      String::length_offset(),
-      Type::ZoneHandle(Z, Type::SmiType()),
-      str->token_pos());
-  length->set_result_cid(kSmiCid);
-  length->set_recognized_kind(MethodRecognizer::kStringBaseLength);
-
-  cursor = flow_graph()->AppendTo(cursor, length, NULL, FlowGraph::kValue);
-  // Bounds check.
-  cursor = flow_graph()->AppendTo(cursor,
-                                   new(Z) CheckArrayBoundInstr(
-                                       new(Z) Value(length),
-                                       new(Z) Value(index),
-                                       call->deopt_id()),
-                                   call->env(),
-                                   FlowGraph::kEffect);
-
-  LoadIndexedInstr* load_indexed = new(Z) LoadIndexedInstr(
-      new(Z) Value(str),
-      new(Z) Value(index),
-      Instance::ElementSizeFor(cid),
-      cid,
-      Thread::kNoDeoptId,
-      call->token_pos());
-
-  cursor = flow_graph()->AppendTo(cursor,
-                                  load_indexed,
-                                  NULL,
-                                  FlowGraph::kValue);
-  ASSERT(cursor == load_indexed);
-  return load_indexed;
-}
-
-
-bool FlowGraphOptimizer::InlineStringCodeUnitAt(
-    Instruction* call,
-    intptr_t cid,
-    TargetEntryInstr** entry,
-    Definition** last) {
-  // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp.
-  if (RawObject::IsExternalStringClassId(cid)) {
-    return false;
-  }
-
-  Definition* str = call->ArgumentAt(0);
-  Definition* index = call->ArgumentAt(1);
-
-  *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
-                                   call->GetBlock()->try_index());
-  (*entry)->InheritDeoptTarget(Z, call);
-
-  *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry);
-
-  return true;
-}
-
-
-bool FlowGraphOptimizer::InlineStringBaseCharAt(
-    Instruction* call,
-    intptr_t cid,
-    TargetEntryInstr** entry,
-    Definition** last) {
-  // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp.
-  if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) {
-    return false;
-  }
-  Definition* str = call->ArgumentAt(0);
-  Definition* index = call->ArgumentAt(1);
-
-  *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
-                                   call->GetBlock()->try_index());
-  (*entry)->InheritDeoptTarget(Z, call);
-
-  *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry);
-
-  StringFromCharCodeInstr* char_at = new(Z) StringFromCharCodeInstr(
-      new(Z) Value(*last), cid);
-
-  flow_graph()->AppendTo(*last, char_at, NULL, FlowGraph::kValue);
-  *last = char_at;
-
-  return true;
-}
-
-
-bool FlowGraphOptimizer::InlineDoubleOp(
-    Token::Kind op_kind,
-    Instruction* call,
-    TargetEntryInstr** entry,
-    Definition** last) {
-  Definition* left = call->ArgumentAt(0);
-  Definition* right = call->ArgumentAt(1);
-
-  *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
-                                   call->GetBlock()->try_index());
-  (*entry)->InheritDeoptTarget(Z, call);
-  // Arguments are checked. No need for class check.
-  BinaryDoubleOpInstr* double_bin_op =
-      new(Z) BinaryDoubleOpInstr(op_kind,
-                                 new(Z) Value(left),
-                                 new(Z) Value(right),
-                                 call->deopt_id(), call->token_pos());
-  flow_graph()->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue);
-  *last = double_bin_op;
-
-  return true;
-}
-
-
 void FlowGraphOptimizer::ReplaceWithMathCFunction(
     InstanceCallInstr* call,
     MethodRecognizer::Kind recognized_kind) {
@@ -3545,300 +2777,6 @@
 }
 
 
-bool FlowGraphOptimizer::InlineByteArrayBaseLoad(Instruction* call,
-                                                 Definition* receiver,
-                                                 intptr_t array_cid,
-                                                 intptr_t view_cid,
-                                                 const ICData& ic_data,
-                                                 TargetEntryInstr** entry,
-                                                 Definition** last) {
-  ASSERT(array_cid != kIllegalCid);
-  Definition* array = receiver;
-  Definition* index = call->ArgumentAt(1);
-  *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
-                                   call->GetBlock()->try_index());
-  (*entry)->InheritDeoptTarget(Z, call);
-  Instruction* cursor = *entry;
-
-  array_cid = PrepareInlineByteArrayBaseOp(call,
-                                           array_cid,
-                                           view_cid,
-                                           &array,
-                                           index,
-                                           &cursor);
-
-  intptr_t deopt_id = Thread::kNoDeoptId;
-  if ((array_cid == kTypedDataInt32ArrayCid) ||
-      (array_cid == kTypedDataUint32ArrayCid)) {
-    // Deoptimization may be needed if result does not always fit in a Smi.
-    deopt_id = (kSmiBits >= 32) ? Thread::kNoDeoptId : call->deopt_id();
-  }
-
-  *last = new(Z) LoadIndexedInstr(new(Z) Value(array),
-                                  new(Z) Value(index),
-                                  1,
-                                  view_cid,
-                                  deopt_id,
-                                  call->token_pos());
-  cursor = flow_graph()->AppendTo(
-      cursor,
-      *last,
-      deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
-      FlowGraph::kValue);
-
-  if (view_cid == kTypedDataFloat32ArrayCid) {
-    *last = new(Z) FloatToDoubleInstr(new(Z) Value(*last), deopt_id);
-    flow_graph()->AppendTo(cursor,
-                           *last,
-                           deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
-                           FlowGraph::kValue);
-  }
-  return true;
-}
-
-
-bool FlowGraphOptimizer::InlineByteArrayBaseStore(const Function& target,
-                                                  Instruction* call,
-                                                  Definition* receiver,
-                                                  intptr_t array_cid,
-                                                  intptr_t view_cid,
-                                                  const ICData& ic_data,
-                                                  TargetEntryInstr** entry,
-                                                  Definition** last) {
-  ASSERT(array_cid != kIllegalCid);
-  Definition* array = receiver;
-  Definition* index = call->ArgumentAt(1);
-  *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
-                                   call->GetBlock()->try_index());
-  (*entry)->InheritDeoptTarget(Z, call);
-  Instruction* cursor = *entry;
-
-  array_cid = PrepareInlineByteArrayBaseOp(call,
-                                           array_cid,
-                                           view_cid,
-                                           &array,
-                                           index,
-                                           &cursor);
-
-  // Extract the instance call so we can use the function_name in the stored
-  // value check ICData.
-  InstanceCallInstr* i_call = NULL;
-  if (call->IsPolymorphicInstanceCall()) {
-    i_call = call->AsPolymorphicInstanceCall()->instance_call();
-  } else {
-    ASSERT(call->IsInstanceCall());
-    i_call = call->AsInstanceCall();
-  }
-  ASSERT(i_call != NULL);
-  ICData& value_check = ICData::ZoneHandle(Z);
-  switch (view_cid) {
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint16ArrayCid: {
-      // Check that value is always smi.
-      value_check = ICData::New(flow_graph_->function(),
-                                i_call->function_name(),
-                                Object::empty_array(),  // Dummy args. descr.
-                                Thread::kNoDeoptId,
-                                1);
-      value_check.AddReceiverCheck(kSmiCid, target);
-      break;
-    }
-    case kTypedDataInt32ArrayCid:
-    case kTypedDataUint32ArrayCid:
-      // On 64-bit platforms assume that stored value is always a smi.
-      if (kSmiBits >= 32) {
-        value_check = ICData::New(flow_graph_->function(),
-                                  i_call->function_name(),
-                                  Object::empty_array(),  // Dummy args. descr.
-                                  Thread::kNoDeoptId,
-                                  1);
-        value_check.AddReceiverCheck(kSmiCid, target);
-      }
-      break;
-    case kTypedDataFloat32ArrayCid:
-    case kTypedDataFloat64ArrayCid: {
-      // Check that value is always double.
-      value_check = ICData::New(flow_graph_->function(),
-                                i_call->function_name(),
-                                Object::empty_array(),  // Dummy args. descr.
-                                Thread::kNoDeoptId,
-                                1);
-      value_check.AddReceiverCheck(kDoubleCid, target);
-      break;
-    }
-    case kTypedDataInt32x4ArrayCid: {
-      // Check that value is always Int32x4.
-      value_check = ICData::New(flow_graph_->function(),
-                                i_call->function_name(),
-                                Object::empty_array(),  // Dummy args. descr.
-                                Thread::kNoDeoptId,
-                                1);
-      value_check.AddReceiverCheck(kInt32x4Cid, target);
-      break;
-    }
-    case kTypedDataFloat32x4ArrayCid: {
-      // Check that value is always Float32x4.
-      value_check = ICData::New(flow_graph_->function(),
-                                i_call->function_name(),
-                                Object::empty_array(),  // Dummy args. descr.
-                                Thread::kNoDeoptId,
-                                1);
-      value_check.AddReceiverCheck(kFloat32x4Cid, target);
-      break;
-    }
-    default:
-      // Array cids are already checked in the caller.
-      UNREACHABLE();
-  }
-
-  Definition* stored_value = call->ArgumentAt(2);
-  if (!value_check.IsNull()) {
-    AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(),
-                  call);
-  }
-
-  if (view_cid == kTypedDataFloat32ArrayCid) {
-    stored_value = new(Z) DoubleToFloatInstr(
-        new(Z) Value(stored_value), call->deopt_id());
-    cursor = flow_graph()->AppendTo(cursor,
-                                    stored_value,
-                                    NULL,
-                                    FlowGraph::kValue);
-  } else if (view_cid == kTypedDataInt32ArrayCid) {
-    stored_value = new(Z) UnboxInt32Instr(
-        UnboxInt32Instr::kTruncate,
-        new(Z) Value(stored_value),
-        call->deopt_id());
-    cursor = flow_graph()->AppendTo(cursor,
-                                    stored_value,
-                                    call->env(),
-                                    FlowGraph::kValue);
-  } else if (view_cid == kTypedDataUint32ArrayCid) {
-    stored_value = new(Z) UnboxUint32Instr(
-        new(Z) Value(stored_value),
-        call->deopt_id());
-    ASSERT(stored_value->AsUnboxInteger()->is_truncating());
-    cursor = flow_graph()->AppendTo(cursor,
-                                    stored_value,
-                                    call->env(),
-                                    FlowGraph::kValue);
-  }
-
-  StoreBarrierType needs_store_barrier = kNoStoreBarrier;
-  *last = new(Z) StoreIndexedInstr(new(Z) Value(array),
-                                   new(Z) Value(index),
-                                   new(Z) Value(stored_value),
-                                   needs_store_barrier,
-                                   1,  // Index scale
-                                   view_cid,
-                                   call->deopt_id(),
-                                   call->token_pos());
-
-  flow_graph()->AppendTo(cursor,
-                         *last,
-                         call->deopt_id() != Thread::kNoDeoptId ?
-                            call->env() : NULL,
-                         FlowGraph::kEffect);
-  return true;
-}
-
-
-
-intptr_t FlowGraphOptimizer::PrepareInlineByteArrayBaseOp(
-    Instruction* call,
-    intptr_t array_cid,
-    intptr_t view_cid,
-    Definition** array,
-    Definition* byte_index,
-    Instruction** cursor) {
-  // Insert byte_index smi check.
-  *cursor = flow_graph()->AppendTo(*cursor,
-                                   new(Z) CheckSmiInstr(
-                                       new(Z) Value(byte_index),
-                                       call->deopt_id(),
-                                       call->token_pos()),
-                                   call->env(),
-                                   FlowGraph::kEffect);
-
-  LoadFieldInstr* length =
-      new(Z) LoadFieldInstr(
-          new(Z) Value(*array),
-          CheckArrayBoundInstr::LengthOffsetFor(array_cid),
-          Type::ZoneHandle(Z, Type::SmiType()),
-          call->token_pos());
-  length->set_is_immutable(true);
-  length->set_result_cid(kSmiCid);
-  length->set_recognized_kind(
-      LoadFieldInstr::RecognizedKindFromArrayCid(array_cid));
-  *cursor = flow_graph()->AppendTo(*cursor,
-                                   length,
-                                   NULL,
-                                   FlowGraph::kValue);
-
-  intptr_t element_size = Instance::ElementSizeFor(array_cid);
-  ConstantInstr* bytes_per_element =
-      flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(element_size)));
-  BinarySmiOpInstr* len_in_bytes =
-      new(Z) BinarySmiOpInstr(Token::kMUL,
-                              new(Z) Value(length),
-                              new(Z) Value(bytes_per_element),
-                              call->deopt_id());
-  *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(),
-                                   FlowGraph::kValue);
-
-  // adjusted_length = len_in_bytes - (element_size - 1).
-  Definition* adjusted_length = len_in_bytes;
-  intptr_t adjustment = Instance::ElementSizeFor(view_cid) - 1;
-  if (adjustment > 0) {
-    ConstantInstr* length_adjustment =
-        flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(adjustment)));
-    adjusted_length =
-        new(Z) BinarySmiOpInstr(Token::kSUB,
-                                new(Z) Value(len_in_bytes),
-                                new(Z) Value(length_adjustment),
-                                call->deopt_id());
-    *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(),
-                                     FlowGraph::kValue);
-  }
-
-  // Check adjusted_length > 0.
-  ConstantInstr* zero =
-      flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(0)));
-  *cursor = flow_graph()->AppendTo(*cursor,
-                                   new(Z) CheckArrayBoundInstr(
-                                       new(Z) Value(adjusted_length),
-                                       new(Z) Value(zero),
-                                       call->deopt_id()),
-                                   call->env(),
-                                   FlowGraph::kEffect);
-  // Check 0 <= byte_index < adjusted_length.
-  *cursor = flow_graph()->AppendTo(*cursor,
-                                   new(Z) CheckArrayBoundInstr(
-                                       new(Z) Value(adjusted_length),
-                                       new(Z) Value(byte_index),
-                                       call->deopt_id()),
-                                   call->env(),
-                                   FlowGraph::kEffect);
-
-  if (RawObject::IsExternalTypedDataClassId(array_cid)) {
-    LoadUntaggedInstr* elements =
-        new(Z) LoadUntaggedInstr(new(Z) Value(*array),
-                                 ExternalTypedData::data_offset());
-    *cursor = flow_graph()->AppendTo(*cursor,
-                                     elements,
-                                     NULL,
-                                     FlowGraph::kValue);
-    *array = elements;
-  }
-  return array_cid;
-}
-
-
 // If type tests specified by 'ic_data' do not depend on type arguments,
 // return mapping cid->result in 'results' (i : cid; i + 1: result).
 // If all tests yield the same result, return it otherwise return Bool::null.
@@ -4044,15 +2982,6 @@
   }
   const ICData& unary_checks =
       ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
-  if (FLAG_warn_on_javascript_compatibility &&
-      !unary_checks.IssuedJSWarning() &&
-      (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) {
-    // No warning was reported yet for this type check, either because it has
-    // not been executed yet, or because no problematic combinations of instance
-    // type and test type have been encountered so far. A warning may still be
-    // reported, so do not replace the instance call.
-    return;
-  }
   if ((unary_checks.NumberOfChecks() > 0) &&
       (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
     ZoneGrowableArray<intptr_t>* results =
@@ -4134,15 +3063,6 @@
   ASSERT(!type.IsMalformedOrMalbounded());
   const ICData& unary_checks =
       ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
-  if (FLAG_warn_on_javascript_compatibility &&
-      !unary_checks.IssuedJSWarning() &&
-      (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) {
-    // No warning was reported yet for this type check, either because it has
-    // not been executed yet, or because no problematic combinations of instance
-    // type and test type have been encountered so far. A warning may still be
-    // reported, so do not replace the instance call.
-    return;
-  }
   if ((unary_checks.NumberOfChecks() > 0) &&
       (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
     ZoneGrowableArray<intptr_t>* results =
@@ -4643,6 +3563,15 @@
       }
     }
     if (!unboxed_field) {
+      // TODO(srdjan): Instead of aborting pass this field to the mutator thread
+      // so that it can:
+      // - set it to unboxed
+      // - deoptimize dependent code.
+      if (Compiler::IsBackgroundCompilation()) {
+        isolate()->AddDeoptimizingBoxedField(field);
+        Compiler::AbortBackgroundCompilation(Thread::kNoDeoptId);
+        UNREACHABLE();
+      }
       if (FLAG_trace_optimization || FLAG_trace_field_guards) {
         THR_Print("Disabling unboxing of %s\n", field.ToCString());
         if (!setter.IsNull()) {
@@ -4653,14 +3582,7 @@
         }
       }
       field.set_is_unboxing_candidate(false);
-      if (Compiler::IsBackgroundCompilation()) {
-        // Delay deoptimization of dependent code to the code installation time.
-        // The invalidation of the background compilation result occurs only
-        // when the deoptimization is triggered at code installation.
-        flow_graph()->deoptimize_dependent_code().Add(&field);
-      } else {
-        field.DeoptimizeDependentCode();
-      }
+      field.DeoptimizeDependentCode();
     } else {
       FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field);
     }
@@ -4890,7 +3812,7 @@
       continue;
     }
 
-    if (FLAG_trace_smi_widening) {
+    if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
       THR_Print("analysing candidate: %s\n", op->ToCString());
     }
     worklist.Clear();
@@ -4902,14 +3824,14 @@
     for (intptr_t j = 0; j < worklist.definitions().length(); j++) {
       Definition* defn = worklist.definitions()[j];
 
-      if (FLAG_trace_smi_widening) {
+      if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
         THR_Print("> %s\n", defn->ToCString());
       }
 
       if (defn->IsBinarySmiOp() &&
           BenefitsFromWidening(defn->AsBinarySmiOp())) {
         gain++;
-        if (FLAG_trace_smi_widening) {
+        if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
           THR_Print("^ [%" Pd "] (o) %s\n", gain, defn->ToCString());
         }
       }
@@ -4927,7 +3849,7 @@
         } else if (input->IsBinaryMintOp()) {
           // Mint operation produces untagged result. We avoid tagging.
           gain++;
-          if (FLAG_trace_smi_widening) {
+          if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
             THR_Print("^ [%" Pd "] (i) %s\n", gain, input->ToCString());
           }
         } else if (defn_loop == loops[input->GetBlock()->preorder_number()] &&
@@ -4938,7 +3860,7 @@
           // known to be smi have to be checked and this check can be
           // coalesced with untagging. Start coalescing them.
           gain--;
-          if (FLAG_trace_smi_widening) {
+          if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
             THR_Print("v [%" Pd "] (i) %s\n", gain, input->ToCString());
           }
         }
@@ -4955,7 +3877,7 @@
           // very little compared to the cost of the return/call itself.
           if (!instr->IsReturn() && !instr->IsPushArgument()) {
             gain--;
-            if (FLAG_trace_smi_widening) {
+            if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
               THR_Print("v [%" Pd "] (u) %s\n",
                         gain,
                         use->instruction()->ToCString());
@@ -4973,14 +3895,14 @@
           // Converting kUnboxedInt32 to kUnboxedMint is essentially zero cost
           // sign extension operation.
           gain++;
-          if (FLAG_trace_smi_widening) {
+          if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
             THR_Print("^ [%" Pd "] (u) %s\n",
                       gain,
                       use->instruction()->ToCString());
           }
         } else if (defn_loop == loops[instr->GetBlock()->preorder_number()]) {
           gain--;
-          if (FLAG_trace_smi_widening) {
+          if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
             THR_Print("v [%" Pd "] (u) %s\n",
                       gain,
                       use->instruction()->ToCString());
@@ -4991,7 +3913,7 @@
 
     processed->AddAll(worklist.contains_vector());
 
-    if (FLAG_trace_smi_widening) {
+    if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
       THR_Print("~ %s gain %" Pd "\n", op->ToCString(), gain);
     }
 
@@ -5028,19 +3950,16 @@
 }
 #endif
 
-void FlowGraphOptimizer::InferIntRanges() {
-  RangeAnalysis range_analysis(flow_graph_);
-  range_analysis.Analyze();
-}
-
 
 void FlowGraphOptimizer::EliminateEnvironments() {
   // After this pass we can no longer perform LICM and hoist instructions
   // that can deoptimize.
 
   flow_graph_->disallow_licm();
-  for (intptr_t i = 0; i < block_order_.length(); ++i) {
-    BlockEntryInstr* block = block_order_[i];
+  for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
+       !block_it.Done();
+       block_it.Advance()) {
+    BlockEntryInstr* block = block_it.Current();
     block->RemoveEnvironment();
     for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
       Instruction* current = it.Current();
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index 9bbcbdf..79abf12 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -54,21 +54,6 @@
 
   void WidenSmiToInt32();
 
-  void InferIntRanges();
-
-  void SelectIntegerInstructions();
-
-  void AnalyzeTryCatch();
-
-  bool TryInlineRecognizedMethod(intptr_t receiver_cid,
-                                 const Function& target,
-                                 Instruction* call,
-                                 Definition* receiver,
-                                 TokenPosition token_pos,
-                                 const ICData& ic_data,
-                                 TargetEntryInstr** entry,
-                                 Definition** last);
-
   // Remove environments from the instructions which do not deoptimize.
   void EliminateEnvironments();
 
@@ -93,24 +78,6 @@
   void SpecializePolymorphicInstanceCall(PolymorphicInstanceCallInstr* call);
 
   bool TryReplaceWithIndexedOp(InstanceCallInstr* call);
-  bool InlineSetIndexed(MethodRecognizer::Kind kind,
-                        const Function& target,
-                        Instruction* call,
-                        Definition* receiver,
-                        TokenPosition token_pos,
-                        const ICData& value_check,
-                        TargetEntryInstr** entry,
-                        Definition** last);
-  bool InlineGetIndexed(MethodRecognizer::Kind kind,
-                        Instruction* call,
-                        Definition* receiver,
-                        TargetEntryInstr** entry,
-                        Definition** last);
-  intptr_t PrepareInlineIndexedOp(Instruction* call,
-                                  intptr_t array_cid,
-                                  Definition** array,
-                                  Definition* index,
-                                  Instruction** cursor);
 
 
   bool TryReplaceWithBinaryOp(InstanceCallInstr* call, Token::Kind op_kind);
@@ -144,51 +111,6 @@
 
   bool TryReplaceInstanceCallWithInline(InstanceCallInstr* call);
 
-  Definition* PrepareInlineStringIndexOp(Instruction* call,
-                                         intptr_t cid,
-                                         Definition* str,
-                                         Definition* index,
-                                         Instruction* cursor);
-
-  bool InlineStringCodeUnitAt(Instruction* call,
-                              intptr_t cid,
-                              TargetEntryInstr** entry,
-                              Definition** last);
-
-  bool InlineStringBaseCharAt(Instruction* call,
-                              intptr_t cid,
-                              TargetEntryInstr** entry,
-                              Definition** last);
-
-  bool InlineDoubleOp(Token::Kind op_kind,
-                      Instruction* call,
-                      TargetEntryInstr** entry,
-                      Definition** last);
-
-  bool InlineByteArrayBaseLoad(Instruction* call,
-                               Definition* receiver,
-                               intptr_t array_cid,
-                               intptr_t view_cid,
-                               const ICData& ic_data,
-                               TargetEntryInstr** entry,
-                               Definition** last);
-
-  bool InlineByteArrayBaseStore(const Function& target,
-                                Instruction* call,
-                                Definition* receiver,
-                                intptr_t array_cid,
-                                intptr_t view_cid,
-                                const ICData& ic_data,
-                                TargetEntryInstr** entry,
-                                Definition** last);
-
-  intptr_t PrepareInlineByteArrayBaseOp(Instruction* call,
-                                        intptr_t array_cid,
-                                        intptr_t view_cid,
-                                        Definition** array,
-                                        Definition* index,
-                                        Instruction** cursor);
-
   // Insert a check of 'to_check' determined by 'unary_checks'.  If the
   // check fails it will deoptimize to 'deopt_id' using the deoptimization
   // environment 'deopt_environment'.  The check is inserted immediately
@@ -256,7 +178,6 @@
   void TryMergeTruncDivMod(GrowableArray<BinarySmiOpInstr*>* merge_candidates);
   void TryMergeMathUnary(GrowableArray<MathUnaryInstr*>* merge_candidates);
 
-  void AppendLoadIndexedForMerged(Definition* instr, intptr_t ix, intptr_t cid);
   void AppendExtractNthOutputForMerged(Definition* instr, intptr_t ix,
                                        Representation rep, intptr_t cid);
   bool TryStringLengthOneEquality(InstanceCallInstr* call, Token::Kind op_kind);
diff --git a/runtime/vm/heap.h b/runtime/vm/heap.h
index 950223c..cfc1b54 100644
--- a/runtime/vm/heap.h
+++ b/runtime/vm/heap.h
@@ -246,8 +246,8 @@
 
   bool ShouldPretenure(intptr_t class_id) const;
 
-  void SetupInstructionsSnapshotPage(void* pointer, uword size) {
-    old_space_.SetupInstructionsSnapshotPage(pointer, size);
+  void SetupExternalPage(void* pointer, uword size, bool is_executable) {
+    old_space_.SetupExternalPage(pointer, size, is_executable);
   }
 
  private:
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index be7171a..20b1e09 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -43,7 +43,6 @@
             "Don't optimize away static field initialization");
 DECLARE_FLAG(bool, eliminate_type_checks);
 DECLARE_FLAG(bool, trace_optimization);
-DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
 
 Definition::Definition(intptr_t deopt_id)
     : Instruction(deopt_id),
@@ -1323,11 +1322,6 @@
 
 
 bool BinarySmiOpInstr::CanDeoptimize() const {
-  if (FLAG_throw_on_javascript_int_overflow && (Smi::kBits > 32)) {
-    // If Smi's are bigger than 32-bits, then the instruction could deoptimize
-    // if the result is too big.
-    return true;
-  }
   switch (op_kind()) {
     case Token::kBIT_AND:
     case Token::kBIT_OR:
@@ -2055,19 +2049,25 @@
     const TypeArguments& instantiator_type_args =
         TypeArguments::Cast(constant_type_args->value());
     Error& bound_error = Error::Handle();
-    const AbstractType& new_dst_type = AbstractType::Handle(
+    AbstractType& new_dst_type = AbstractType::Handle(
         dst_type().InstantiateFrom(
             instantiator_type_args, &bound_error, NULL, NULL, Heap::kOld));
-    // If dst_type is instantiated to dynamic or Object, skip the test.
-    if (!new_dst_type.IsMalformedOrMalbounded() && bound_error.IsNull() &&
-        (new_dst_type.IsDynamicType() || new_dst_type.IsObjectType())) {
+    if (new_dst_type.IsMalformedOrMalbounded() || !bound_error.IsNull()) {
+      return this;
+    }
+    if (new_dst_type.IsTypeRef()) {
+      new_dst_type = TypeRef::Cast(new_dst_type).type();
+    }
+    new_dst_type = new_dst_type.Canonicalize();
+    set_dst_type(new_dst_type);
+
+    if (new_dst_type.IsDynamicType() ||
+        new_dst_type.IsObjectType() ||
+        (FLAG_eliminate_type_checks &&
+         value()->Type()->IsAssignableTo(new_dst_type))) {
       return value()->definition();
     }
-    set_dst_type(AbstractType::ZoneHandle(new_dst_type.Canonicalize()));
-    if (FLAG_eliminate_type_checks &&
-        value()->Type()->IsAssignableTo(dst_type())) {
-      return value()->definition();
-    }
+
     ConstantInstr* null_constant = flow_graph->constant_null();
     instantiator_type_arguments()->BindTo(null_constant);
   }
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index f4664dc..8677ac9 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -17,8 +17,6 @@
 
 namespace dart {
 
-DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
-
 class BitVector;
 class BlockEntryInstr;
 class BoxIntegerInstr;
@@ -2643,6 +2641,7 @@
         dst_type_(AbstractType::ZoneHandle(dst_type.raw())),
         dst_name_(dst_name) {
     ASSERT(!dst_type.IsNull());
+    ASSERT(!dst_type.IsTypeRef());
     ASSERT(!dst_name.IsNull());
     SetInputAt(0, value);
     SetInputAt(1, instantiator_type_arguments);
@@ -2658,6 +2657,7 @@
   virtual TokenPosition token_pos() const { return token_pos_; }
   const AbstractType& dst_type() const { return dst_type_; }
   void set_dst_type(const AbstractType& dst_type) {
+    ASSERT(!dst_type.IsTypeRef());
     dst_type_ = dst_type.raw();
   }
   const String& dst_name() const { return dst_name_; }
@@ -6829,7 +6829,7 @@
   }
 
   virtual bool CanDeoptimize() const {
-    return FLAG_throw_on_javascript_int_overflow;
+    return false;
   }
 
   virtual CompileType ComputeType() const;
@@ -7089,8 +7089,7 @@
   }
 
   virtual bool CanDeoptimize() const {
-    return FLAG_throw_on_javascript_int_overflow
-        || (can_overflow() && ((op_kind() == Token::kADD) ||
+    return (can_overflow() && ((op_kind() == Token::kADD) ||
                                (op_kind() == Token::kSUB)))
         || (op_kind() == Token::kMUL);  // Deopt if inputs are not int32.
   }
@@ -7125,8 +7124,7 @@
   }
 
   virtual bool CanDeoptimize() const {
-    return FLAG_throw_on_javascript_int_overflow
-        || has_shift_count_check()
+    return  has_shift_count_check()
         || (can_overflow() && (op_kind() == Token::kSHL));
   }
 
@@ -8177,7 +8175,7 @@
 class FlowGraphVisitor : public ValueObject {
  public:
   explicit FlowGraphVisitor(const GrowableArray<BlockEntryInstr*>& block_order)
-      : block_order_(block_order), current_iterator_(NULL) { }
+      : current_iterator_(NULL), block_order_(block_order) { }
   virtual ~FlowGraphVisitor() { }
 
   ForwardInstructionIterator* current_iterator() const {
@@ -8198,10 +8196,10 @@
 #undef DECLARE_VISIT_INSTRUCTION
 
  protected:
-  const GrowableArray<BlockEntryInstr*>& block_order_;
   ForwardInstructionIterator* current_iterator_;
 
  private:
+  const GrowableArray<BlockEntryInstr*>& block_order_;
   DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor);
 };
 
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index a86906a..93619bc 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -2883,10 +2883,15 @@
       const Register value = instruction_->locs()->temp(0).reg();
       __ Comment("CheckStackOverflowSlowPathOsr");
       __ Bind(osr_entry_label());
-      ASSERT(FLAG_allow_absolute_addresses);
-      __ LoadImmediate(IP, flags_address);
-      __ LoadImmediate(value, Isolate::kOsrRequest);
-      __ str(value, Address(IP));
+      if (FLAG_allow_absolute_addresses) {
+        __ LoadImmediate(IP, flags_address);
+        __ LoadImmediate(value, Isolate::kOsrRequest);
+        __ str(value, Address(IP));
+      } else {
+        __ LoadIsolate(IP);
+        __ LoadImmediate(value, Isolate::kOsrRequest);
+        __ str(value, Address(IP, Isolate::stack_overflow_flags_offset()));
+      }
     }
     __ Comment("CheckStackOverflowSlowPath");
     __ Bind(entry_label());
@@ -6069,27 +6074,6 @@
 }
 
 
-static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
-                                           Label* overflow,
-                                           Register result_lo,
-                                           Register result_hi) {
-  // Compare upper half.
-  Label check_lower;
-  __ CompareImmediate(result_hi, 0x00200000);
-  __ b(overflow, GT);
-  __ b(&check_lower, NE);
-
-  __ CompareImmediate(result_lo, 0);
-  __ b(overflow, HI);
-
-  __ Bind(&check_lower);
-  __ CompareImmediate(result_hi, -0x00200000);
-  __ b(overflow, LT);
-  // Anything in the lower part would make the number bigger than the lower
-  // bound, so we are done.
-}
-
-
 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone,
                                                         bool opt) const {
   const intptr_t kNumInputs = 2;
@@ -6167,9 +6151,6 @@
     default:
       UNREACHABLE();
   }
-  if (FLAG_throw_on_javascript_int_overflow) {
-    EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
-  }
 }
 
 
@@ -6315,10 +6296,6 @@
         UNREACHABLE();
     }
   }
-
-  if (FLAG_throw_on_javascript_int_overflow) {
-    EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
-  }
 }
 
 
@@ -6345,17 +6322,8 @@
   PairLocation* out_pair = locs()->out(0).AsPairLocation();
   Register out_lo = out_pair->At(0).reg();
   Register out_hi = out_pair->At(1).reg();
-
-  Label* deopt = NULL;
-
-  if (FLAG_throw_on_javascript_int_overflow) {
-    deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
-  }
   __ mvn(out_lo, Operand(left_lo));
   __ mvn(out_hi, Operand(left_hi));
-  if (FLAG_throw_on_javascript_int_overflow) {
-    EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
-  }
 }
 
 
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index e8bd759..0627f74 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -2593,10 +2593,15 @@
       const Register value = instruction_->locs()->temp(0).reg();
       __ Comment("CheckStackOverflowSlowPathOsr");
       __ Bind(osr_entry_label());
-      ASSERT(FLAG_allow_absolute_addresses);
-      __ LoadImmediate(TMP, flags_address);
-      __ LoadImmediate(value, Isolate::kOsrRequest);
-      __ str(value, Address(TMP));
+      if (FLAG_allow_absolute_addresses) {
+        __ LoadImmediate(TMP, flags_address);
+        __ LoadImmediate(value, Isolate::kOsrRequest);
+        __ str(value, Address(TMP));
+      } else {
+        __ LoadIsolate(TMP);
+        __ LoadImmediate(value, Isolate::kOsrRequest);
+        __ str(value, Address(TMP, Isolate::stack_overflow_flags_offset()));
+      }
     }
     __ Comment("CheckStackOverflowSlowPath");
     __ Bind(entry_label());
@@ -2667,20 +2672,6 @@
 }
 
 
-static void EmitJavascriptOverflowCheck(FlowGraphCompiler* compiler,
-                                        Range* range,
-                                        Label* overflow,
-                                        Register result) {
-  if (!RangeUtils::IsWithin(range, -0x20000000000000LL, 0x20000000000000LL)) {
-    ASSERT(overflow != NULL);
-    __ LoadImmediate(TMP, 0x20000000000000LL);
-    __ add(TMP2, result, Operand(TMP));
-    __ cmp(TMP2, Operand(TMP, LSL, 1));
-    __ b(overflow, HI);
-  }
-}
-
-
 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
                              BinarySmiOpInstr* shift_left) {
   const LocationSummary& locs = *shift_left->locs();
@@ -2704,9 +2695,6 @@
     }
     // Shift for result now we know there is no overflow.
     __ LslImmediate(result, left, value);
-    if (FLAG_throw_on_javascript_int_overflow) {
-      EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
-    }
     return;
   }
 
@@ -2736,9 +2724,6 @@
       __ SmiUntag(TMP, right);
       __ lslv(result, left, TMP);
     }
-    if (FLAG_throw_on_javascript_int_overflow) {
-      EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
-    }
     return;
   }
 
@@ -2783,9 +2768,6 @@
     // Shift for result now we know there is no overflow.
     __ lslv(result, left, TMP);
   }
-  if (FLAG_throw_on_javascript_int_overflow) {
-    EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
-  }
 }
 
 
@@ -2921,9 +2903,6 @@
         UNREACHABLE();
         break;
     }
-    if (FLAG_throw_on_javascript_int_overflow) {
-      EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
-    }
     return;
   }
 
@@ -3066,9 +3045,6 @@
       UNREACHABLE();
       break;
   }
-  if (FLAG_throw_on_javascript_int_overflow) {
-    EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
-  }
 }
 
 
@@ -4527,9 +4503,6 @@
       Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
       __ subs(result, ZR, Operand(value));
       __ b(deopt, VS);
-      if (FLAG_throw_on_javascript_int_overflow) {
-        EmitJavascriptOverflowCheck(compiler, range(), deopt, value);
-      }
       break;
     }
     case Token::kBIT_NOT:
@@ -4645,9 +4618,6 @@
   __ CompareImmediate(result, 0xC000000000000000);
   __ b(&do_call, MI);
   __ SmiTag(result);
-  if (FLAG_throw_on_javascript_int_overflow) {
-    EmitJavascriptOverflowCheck(compiler, range(), &do_call, result);
-  }
   __ b(&done);
   __ Bind(&do_call);
   __ Push(value_obj);
@@ -4695,9 +4665,6 @@
   __ CompareImmediate(result, 0xC000000000000000);
   __ b(deopt, MI);
   __ SmiTag(result);
-  if (FLAG_throw_on_javascript_int_overflow) {
-    EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
-  }
 }
 
 
@@ -5011,9 +4978,6 @@
     __ add(TMP, result_mod, Operand(right));
     __ csel(result_mod, TMP, TMP2, GE);
     __ Bind(&done);
-    // FLAG_throw_on_javascript_int_overflow: not needed.
-    // Note that the result of an integer division/modulo of two
-    // in-range arguments, cannot create out-of-range result.
     return;
   }
   if (kind() == MergedMathInstr::kSinCos) {
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index f067afe..8933848 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -25,7 +25,6 @@
 
 DECLARE_FLAG(bool, emit_edge_counters);
 DECLARE_FLAG(int, optimization_counter_threshold);
-DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
 DECLARE_FLAG(bool, use_osr);
 
 // Generic summary for call instructions that have all arguments pushed
@@ -441,27 +440,6 @@
 }
 
 
-static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
-                                           Label* overflow,
-                                           Register result_lo,
-                                           Register result_hi) {
-  // Compare upper half.
-  Label check_lower;
-  __ cmpl(result_hi, Immediate(0x00200000));
-  __ j(GREATER, overflow);
-  __ j(NOT_EQUAL, &check_lower);
-
-  __ cmpl(result_lo, Immediate(0));
-  __ j(ABOVE, overflow);
-
-  __ Bind(&check_lower);
-  __ cmpl(result_hi, Immediate(-0x00200000));
-  __ j(LESS, overflow);
-  // Anything in the lower part would make the number bigger than the lower
-  // bound, so we are done.
-}
-
-
 static Condition TokenKindToMintCondition(Token::Kind kind) {
   switch (kind) {
     case Token::kEQ: return EQUAL;
@@ -6035,9 +6013,6 @@
     default:
       UNREACHABLE();
   }
-  if (FLAG_throw_on_javascript_int_overflow) {
-    EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
-  }
 }
 
 
@@ -6237,9 +6212,6 @@
     }
     __ Bind(&done);
   }
-  if (FLAG_throw_on_javascript_int_overflow) {
-    EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
-  }
 }
 
 
@@ -6252,9 +6224,6 @@
   summary->set_in(0, Location::Pair(Location::RequiresRegister(),
                                     Location::RequiresRegister()));
   summary->set_out(0, Location::SameAsFirstInput());
-  if (FLAG_throw_on_javascript_int_overflow) {
-    summary->set_temp(0, Location::RequiresRegister());
-  }
   return summary;
 }
 
@@ -6269,18 +6238,8 @@
   Register out_hi = out_pair->At(1).reg();
   ASSERT(out_lo == left_lo);
   ASSERT(out_hi == left_hi);
-
-  Label* deopt = NULL;
-  if (FLAG_throw_on_javascript_int_overflow) {
-    deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
-  }
-
   __ notl(left_lo);
   __ notl(left_hi);
-
-  if (FLAG_throw_on_javascript_int_overflow) {
-    EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
-  }
 }
 
 
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 064bd6e..93e720c 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -2711,10 +2711,15 @@
       Register value = instruction_->locs()->temp(0).reg();
       __ Comment("CheckStackOverflowSlowPathOsr");
       __ Bind(osr_entry_label());
-      ASSERT(FLAG_allow_absolute_addresses);
-      __ LoadImmediate(TMP, flags_address);
-      __ LoadImmediate(value, Isolate::kOsrRequest);
-      __ sw(value, Address(TMP));
+      if (FLAG_allow_absolute_addresses) {
+        __ LoadImmediate(TMP, flags_address);
+        __ LoadImmediate(value, Isolate::kOsrRequest);
+        __ sw(value, Address(TMP));
+      } else {
+        __ LoadIsolate(TMP);
+        __ LoadImmediate(value, Isolate::kOsrRequest);
+        __ sw(value, Address(TMP, Isolate::stack_overflow_flags_offset()));
+      }
     }
     __ Comment("CheckStackOverflowSlowPath");
     __ Bind(entry_label());
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 1f840fd..2fdf93e 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -26,7 +26,6 @@
 DECLARE_FLAG(bool, allow_absolute_addresses);
 DECLARE_FLAG(bool, emit_edge_counters);
 DECLARE_FLAG(int, optimization_counter_threshold);
-DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
 DECLARE_FLAG(bool, use_osr);
 DECLARE_FLAG(bool, precompilation);
 
@@ -2613,9 +2612,14 @@
       Register temp = instruction_->locs()->temp(0).reg();
       __ Comment("CheckStackOverflowSlowPathOsr");
       __ Bind(osr_entry_label());
-      ASSERT(FLAG_allow_absolute_addresses);
-      __ LoadImmediate(temp, Immediate(flags_address));
-      __ movq(Address(temp, 0), Immediate(Isolate::kOsrRequest));
+      if (FLAG_allow_absolute_addresses) {
+        __ LoadImmediate(temp, Immediate(flags_address));
+        __ movq(Address(temp, 0), Immediate(Isolate::kOsrRequest));
+      } else {
+        __ LoadIsolate(TMP);
+        __ movq(Address(TMP, Isolate::stack_overflow_flags_offset()),
+                Immediate(Isolate::kOsrRequest));
+      }
     }
     __ Comment("CheckStackOverflowSlowPath");
     __ Bind(entry_label());
@@ -2687,22 +2691,6 @@
 }
 
 
-static void EmitJavascriptOverflowCheck(FlowGraphCompiler* compiler,
-                                        Range* range,
-                                        Label* overflow,
-                                        Register result) {
-  if (!RangeUtils::IsWithin(range, -0x20000000000000LL, 0x20000000000000LL)) {
-    ASSERT(overflow != NULL);
-    // TODO(zra): This can be tightened to one compare/branch using:
-    // overflow = (result + 2^52) > 2^53 with an unsigned comparison.
-    __ CompareImmediate(result, Immediate(-0x20000000000000LL));
-    __ j(LESS, overflow);
-    __ CompareImmediate(result, Immediate(0x20000000000000LL));
-    __ j(GREATER, overflow);
-  }
-}
-
-
 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
                              BinarySmiOpInstr* shift_left) {
   const LocationSummary& locs = *shift_left->locs();
@@ -2730,9 +2718,6 @@
     }
     // Shift for result now we know there is no overflow.
     __ shlq(left, Immediate(value));
-    if (FLAG_throw_on_javascript_int_overflow) {
-      EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
-    }
     return;
   }
 
@@ -2761,9 +2746,6 @@
       __ SmiUntag(right);
       __ shlq(left, right);
     }
-    if (FLAG_throw_on_javascript_int_overflow) {
-      EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
-    }
     return;
   }
 
@@ -2813,9 +2795,6 @@
     // Shift for result now we know there is no overflow.
     __ shlq(left, right);
   }
-  if (FLAG_throw_on_javascript_int_overflow) {
-    EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
-  }
 }
 
 
@@ -2996,9 +2975,6 @@
         UNREACHABLE();
         break;
     }
-    if (FLAG_throw_on_javascript_int_overflow) {
-      EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
-    }
     return;
   }  // locs()->in(1).IsConstant().
 
@@ -3041,9 +3017,6 @@
         UNREACHABLE();
         break;
     }
-    if (FLAG_throw_on_javascript_int_overflow) {
-      EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
-    }
     return;
   }  // locs()->in(1).IsStackSlot().
 
@@ -3240,9 +3213,6 @@
       UNREACHABLE();
       break;
   }
-  if (FLAG_throw_on_javascript_int_overflow) {
-    EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
-  }
 }
 
 
@@ -4732,9 +4702,6 @@
       Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
       __ negq(value);
       __ j(OVERFLOW, deopt);
-      if (FLAG_throw_on_javascript_int_overflow) {
-        EmitJavascriptOverflowCheck(compiler, range(), deopt, value);
-      }
       break;
     }
     case Token::kBIT_NOT:
@@ -4938,9 +4905,6 @@
   __ shlq(temp, Immediate(1));
   __ j(OVERFLOW, &do_call, Assembler::kNearJump);
   __ SmiTag(result);
-  if (FLAG_throw_on_javascript_int_overflow) {
-    EmitJavascriptOverflowCheck(compiler, range(), &do_call, result);
-  }
   __ jmp(&done);
   __ Bind(&do_call);
   ASSERT(instance_call()->HasICData());
@@ -4988,9 +4952,6 @@
   __ shlq(temp, Immediate(1));
   __ j(OVERFLOW, deopt);
   __ SmiTag(result);
-  if (FLAG_throw_on_javascript_int_overflow) {
-    EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
-  }
 }
 
 
@@ -5423,7 +5384,6 @@
 
     __ SmiTag(RAX);
     __ SmiTag(RDX);
-    // FLAG_throw_on_javascript_int_overflow: not needed.
     // Note that the result of an integer division/modulo of two
     // in-range arguments, cannot create out-of-range result.
     return;
@@ -5728,10 +5688,6 @@
   }
 
   EmitInt64Arithmetic(compiler, op_kind(), left, right, deopt);
-
-  if (FLAG_throw_on_javascript_int_overflow) {
-    EmitJavascriptOverflowCheck(compiler, range(), deopt, out);
-  }
 }
 
 
@@ -5752,17 +5708,7 @@
   const Register left = locs()->in(0).reg();
   const Register out = locs()->out(0).reg();
   ASSERT(out == left);
-
-  Label* deopt = NULL;
-  if (FLAG_throw_on_javascript_int_overflow) {
-    deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
-  }
-
   __ notq(left);
-
-  if (FLAG_throw_on_javascript_int_overflow) {
-    EmitJavascriptOverflowCheck(compiler, range(), deopt, out);
-  }
 }
 
 
@@ -5859,9 +5805,6 @@
         UNREACHABLE();
     }
   }
-  if (FLAG_throw_on_javascript_int_overflow) {
-    EmitJavascriptOverflowCheck(compiler, range(), deopt, out);
-  }
 }
 
 
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
index 69c723d..193dba4 100644
--- a/runtime/vm/intrinsifier.cc
+++ b/runtime/vm/intrinsifier.cc
@@ -21,7 +21,6 @@
 namespace dart {
 
 DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible");
-DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
 DECLARE_FLAG(bool, code_comments);
 DECLARE_FLAG(bool, print_flow_graph);
 DECLARE_FLAG(bool, print_flow_graph_optimized);
@@ -201,15 +200,10 @@
     default:
       break;
   }
-  // Integer intrinsics are in the core library, but we don't want to
-  // intrinsify when Smi > 32 bits if we are looking for javascript integer
-  // overflow.
-  if (!(FLAG_throw_on_javascript_int_overflow && (Smi::kBits >= 32))) {
-    switch (function.recognized_kind()) {
-      CORE_INTEGER_LIB_INTRINSIC_LIST(EMIT_CASE)
-      default:
-        break;
-    }
+  switch (function.recognized_kind()) {
+    CORE_INTEGER_LIB_INTRINSIC_LIST(EMIT_CASE)
+    default:
+      break;
   }
 #undef EMIT_INTRINSIC
 }
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 3214d5f..32b50e8 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -52,6 +52,7 @@
 DECLARE_FLAG(bool, print_metrics);
 DECLARE_FLAG(bool, timing);
 DECLARE_FLAG(bool, trace_service);
+DECLARE_FLAG(bool, trace_service_verbose);
 
 DEFINE_FLAG(bool, trace_isolates, false,
             "Trace isolate creation and shut down.");
@@ -764,6 +765,8 @@
 #define REUSABLE_HANDLE_INITIALIZERS(object)                                   \
   object##_handle_(NULL),
 
+// TODO(srdjan): Some Isolate monitors can be shared. Replace their usage with
+// that shared monitor.
 Isolate::Isolate(const Dart_IsolateFlags& api_flags)
   :   stack_limit_(0),
       store_buffer_(new StoreBuffer()),
@@ -831,6 +834,8 @@
       cha_invalidation_gen_(kInvalidGen),
       field_invalidation_gen_(kInvalidGen),
       prefix_invalidation_gen_(kInvalidGen),
+      boxed_field_list_monitor_(new Monitor()),
+      boxed_field_list_(GrowableObjectArray::null()),
       spawn_count_monitor_(new Monitor()),
       spawn_count_(0) {
   flags_.CopyFrom(api_flags);
@@ -868,6 +873,8 @@
   object_id_ring_ = NULL;
   delete pause_loop_monitor_;
   pause_loop_monitor_ = NULL;
+  delete boxed_field_list_monitor_;
+  boxed_field_list_monitor_ = NULL;
   ASSERT(spawn_count_ == 0);
   delete spawn_count_monitor_;
   if (compiler_stats_ != NULL) {
@@ -901,12 +908,7 @@
 
 #ifndef PRODUCT
   // Initialize Timeline streams.
-#define ISOLATE_TIMELINE_STREAM_INIT(name, enabled_by_default)                 \
-  result->stream_##name##_.Init(#name,                                         \
-                                enabled_by_default,                            \
-                                Timeline::Stream##name##EnabledFlag());
-  ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_INIT);
-#undef ISOLATE_TIMELINE_STREAM_INIT
+  Timeline::SetupIsolateStreams(result);
 #endif  // !PRODUCT
 
   Heap::Init(result,
@@ -1011,11 +1013,29 @@
               snapshot.instructions_size());
   }
 #endif
-  heap_->SetupInstructionsSnapshotPage(snapshot.instructions_start(),
-                                       snapshot.instructions_size());
+  heap_->SetupExternalPage(snapshot.instructions_start(),
+                           snapshot.instructions_size(),
+                           /* is_executable = */ true);
 }
 
 
+void Isolate::SetupDataSnapshotPage(const uint8_t* data_snapshot_buffer) {
+  DataSnapshot snapshot(data_snapshot_buffer);
+#if defined(DEBUG)
+  if (FLAG_trace_isolates) {
+    OS::Print("Precompiled rodata are at [0x%" Px ", 0x%" Px ")\n",
+              reinterpret_cast<uword>(snapshot.data_start()),
+              reinterpret_cast<uword>(snapshot.data_start()) +
+              snapshot.data_size());
+  }
+#endif
+  heap_->SetupExternalPage(snapshot.data_start(),
+                           snapshot.data_size(),
+                           /* is_executable = */ false);
+}
+
+
+
 void Isolate::set_debugger_name(const char* name) {
   free(debugger_name_);
   debugger_name_ = strdup(name);
@@ -1518,6 +1538,10 @@
       stack_limit_ = saved_stack_limit_;
     }
   }
+  if (FLAG_trace_service && FLAG_trace_service_verbose) {
+    OS::Print("[+%" Pd64 "ms] Isolate %s deferring OOB interrupts\n",
+              Dart::timestamp(), name());
+  }
 }
 
 
@@ -1532,6 +1556,10 @@
     stack_limit_ |= deferred_interrupts_;
     deferred_interrupts_ = 0;
   }
+  if (FLAG_trace_service && FLAG_trace_service_verbose) {
+    OS::Print("[+%" Pd64 "ms] Isolate %s restoring OOB interrupts\n",
+              Dart::timestamp(), name());
+  }
 }
 
 
@@ -1846,6 +1874,12 @@
   visitor->VisitPointer(
       reinterpret_cast<RawObject**>(&registered_service_extension_handlers_));
 
+  // Visit the boxed_field_list.
+  // 'boxed_field_list_' access via mutator and background compilation threads
+  // is guarded with a monitor. This means that we can visit it only
+  // when at safepoint or the boxed_field_list_monitor_ lock has been taken.
+  visitor->VisitPointer(reinterpret_cast<RawObject**>(&boxed_field_list_));
+
   // Visit objects in the debugger.
   if (FLAG_support_debugger) {
     debugger()->VisitObjectPointers(visitor);
@@ -2050,6 +2084,31 @@
 }
 
 
+void Isolate::AddDeoptimizingBoxedField(const Field& field) {
+  MonitorLocker ml(boxed_field_list_monitor_);
+  if (boxed_field_list_ == GrowableObjectArray::null()) {
+    boxed_field_list_ = GrowableObjectArray::New(Heap::kOld);
+  }
+  const GrowableObjectArray& array =
+      GrowableObjectArray::Handle(boxed_field_list_);
+  array.Add(field, Heap::kOld);
+}
+
+
+RawField* Isolate::GetDeoptimizingBoxedField() {
+  MonitorLocker ml(boxed_field_list_monitor_);
+  if (boxed_field_list_ == GrowableObjectArray::null()) {
+    return Field::null();
+  }
+  const GrowableObjectArray& array =
+      GrowableObjectArray::Handle(boxed_field_list_);
+  if (array.Length() == 0) {
+    return Field::null();
+  }
+  return Field::RawCast(array.RemoveLast());
+}
+
+
 RawObject* Isolate::InvokePendingServiceExtensionCalls() {
   if (!FLAG_support_service) {
     return Object::null();
@@ -2067,7 +2126,7 @@
   ASSERT(!run_extension.IsNull());
 
   const Array& arguments =
-      Array::Handle(Array::New(kPendingEntrySize, Heap::kNew));
+      Array::Handle(Array::New(kPendingEntrySize + 1, Heap::kNew));
   Object& result = Object::Handle();
   String& method_name = String::Handle();
   Instance& closure = Instance::Handle();
@@ -2094,8 +2153,19 @@
     arguments.SetAt(kPendingReplyPortIndex, reply_port);
     id ^= calls.At(i + kPendingIdIndex);
     arguments.SetAt(kPendingIdIndex, id);
+    arguments.SetAt(kPendingEntrySize, Bool::Get(FLAG_trace_service));
 
+    if (FLAG_trace_service) {
+      OS::Print(
+          "[+%" Pd64 "ms] Isolate %s invoking _runExtension for %s\n",
+          Dart::timestamp(), name(), method_name.ToCString());
+    }
     result = DartEntry::InvokeFunction(run_extension, arguments);
+    if (FLAG_trace_service) {
+      OS::Print(
+          "[+%" Pd64 "ms] Isolate %s : _runExtension complete for %s\n",
+          Dart::timestamp(), name(), method_name.ToCString());
+    }
     if (result.IsError()) {
       if (result.IsUnwindError()) {
         // Propagate the unwind error. Remaining service extension calls
@@ -2133,6 +2203,11 @@
                                          const Array& parameter_values,
                                          const Instance& reply_port,
                                          const Instance& id) {
+  if (FLAG_trace_service) {
+    OS::Print(
+        "[+%" Pd64 "ms] Isolate %s ENQUEUING request for extension %s\n",
+        Dart::timestamp(), name(), method_name.ToCString());
+  }
   GrowableObjectArray& calls =
       GrowableObjectArray::Handle(pending_service_extension_calls());
   if (calls.IsNull()) {
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index f2a0cc3..15c2562 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -53,6 +53,7 @@
 class RawObject;
 class RawInteger;
 class RawError;
+class RawField;
 class RawFloat32x4;
 class RawInt32x4;
 class RawUserTag;
@@ -239,6 +240,8 @@
 
   void SetupInstructionsSnapshotPage(
       const uint8_t* instructions_snapshot_buffer);
+  void SetupDataSnapshotPage(
+      const uint8_t* instructions_snapshot_buffer);
 
   // Returns true if any of the interrupts specified by 'interrupt_bits' are
   // currently scheduled for this isolate, but leaves them unchanged.
@@ -274,6 +277,9 @@
   uword stack_overflow_flags_address() const {
     return reinterpret_cast<uword>(&stack_overflow_flags_);
   }
+  static intptr_t stack_overflow_flags_offset() {
+    return OFFSET_OF(Isolate, stack_overflow_flags_);
+  }
 
   int32_t IncrementAndGetStackOverflowCount() {
     return ++stack_overflow_count_;
@@ -642,6 +648,12 @@
   void ResetPrefixInvalidationGen() { prefix_invalidation_gen_ = kInvalidGen; }
   uint32_t prefix_invalidation_gen() const { return prefix_invalidation_gen_; }
 
+  // Used by background compiler which field became boxed and must trigger
+  // deoptimization in the mutator thread.
+  void AddDeoptimizingBoxedField(const Field& field);
+  // Returns Field::null() if none available in the list.
+  RawField* GetDeoptimizingBoxedField();
+
   RawObject* InvokePendingServiceExtensionCalls();
   void AppendServiceExtensionCall(const Instance& closure,
                            const String& method_name,
@@ -844,6 +856,11 @@
   uint32_t field_invalidation_gen_;
   uint32_t prefix_invalidation_gen_;
 
+  // Protect access to boxed_field_list_.
+  Monitor* boxed_field_list_monitor_;
+  // List of fields that became boxed and that trigger deoptimization.
+  RawGrowableObjectArray* boxed_field_list_;
+
   // This guards spawn_count_. An isolate cannot complete shutdown and be
   // destroyed while there are child isolates in the midst of a spawn.
   Monitor* spawn_count_monitor_;
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index b64d6e6..94928ab 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -79,9 +79,9 @@
     Isolate* isolate = Isolate::Current();
     ASSERT(isolate != NULL);
     const char* isolate_name = isolate->name();
-    OS::Print("Isolate %s processing service request %s\n",
-              isolate_name, method_);
     setup_time_micros_ = OS::GetCurrentTimeMicros();
+    OS::Print("[+%" Pd64 "ms] Isolate %s processing service request %s\n",
+              Dart::timestamp(), isolate_name, method_);
   }
   buffer_.Printf("{\"jsonrpc\":\"2.0\", \"result\":");
 }
@@ -172,10 +172,6 @@
   Dart_Port port = reply_port();
   ASSERT(port != ILLEGAL_PORT);
   set_reply_port(ILLEGAL_PORT);  // Prevent double replies.
-  int64_t process_delta_micros = 0;
-  if (FLAG_trace_service) {
-    process_delta_micros = OS::GetCurrentTimeMicros() - setup_time_micros_;
-  }
   ASSERT(seq_ != NULL);
   if (seq_->IsString()) {
     const String& str = String::Cast(*seq_);
@@ -206,12 +202,15 @@
     Isolate* isolate = Isolate::Current();
     ASSERT(isolate != NULL);
     const char* isolate_name = isolate->name();
+    int64_t total_time = OS::GetCurrentTimeMicros() - setup_time_micros_;
     if (result) {
-      OS::Print("Isolate %s processed service request %s in %" Pd64" us.\n",
-                isolate_name, method_, process_delta_micros);
+      OS::Print("[+%" Pd64 "ms] Isolate %s processed service request %s "
+                "(%" Pd64 "us)\n",
+                Dart::timestamp(), isolate_name, method_, total_time);
     } else {
-      OS::Print("Isolate %s FAILED to post response for service request %s.\n",
-                isolate_name, method_);
+      OS::Print("[+%" Pd64 "ms] Isolate %s processed service request %s "
+                "(%" Pd64 "us) FAILED\n",
+                Dart::timestamp(), isolate_name, method_, total_time);
     }
   }
 }
diff --git a/runtime/vm/log.cc b/runtime/vm/log.cc
index b7f6589..91be51d 100644
--- a/runtime/vm/log.cc
+++ b/runtime/vm/log.cc
@@ -141,16 +141,26 @@
 
 
 void Log::TerminateString() {
+  if (this == NoOpLog()) {
+    return;
+  }
   buffer_.Add('\0');
 }
 
 
 void Log::EnableManualFlush() {
+  if (this == NoOpLog()) {
+    return;
+  }
   manual_flush_++;
 }
 
 
 void Log::DisableManualFlush() {
+  if (this == NoOpLog()) {
+    return;
+  }
+
   manual_flush_--;
   ASSERT(manual_flush_ >= 0);
   if (manual_flush_ == 0) {
diff --git a/runtime/vm/longjump.cc b/runtime/vm/longjump.cc
index ef141c9..13e0133 100644
--- a/runtime/vm/longjump.cc
+++ b/runtime/vm/longjump.cc
@@ -29,7 +29,10 @@
   uword jumpbuf_addr = Isolate::GetCurrentStackPointer();
 #if defined(USING_SIMULATOR)
   Simulator* sim = Simulator::Current();
-  uword top_exit_frame_info = sim->top_exit_frame_info();
+  // When using simulator, only mutator thread should refer to Simulator
+  // since there can be only one per isolate.
+  uword top_exit_frame_info = thread->IsMutatorThread() ?
+      sim->top_exit_frame_info() : 0;
 #else
   uword top_exit_frame_info = thread->top_exit_frame_info();
 #endif
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index febf565..c85afa2 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -56,9 +56,6 @@
 DEFINE_FLAG(bool, show_internal_names, false,
     "Show names of internal classes (e.g. \"OneByteString\") in error messages "
     "instead of showing the corresponding interface names (e.g. \"String\")");
-DEFINE_FLAG(bool, throw_on_javascript_int_overflow, false,
-    "Throw an exception when the result of an integer calculation will not "
-    "fit into a javascript integer.");
 DEFINE_FLAG(bool, trace_cha, false, "Trace CHA operations");
 DEFINE_FLAG(bool, use_field_guards, true, "Guard field cids.");
 DEFINE_FLAG(bool, use_lib_cache, true, "Use library name cache");
@@ -915,9 +912,12 @@
     if (!obj->IsFreeListElement()) {
       ASSERT(obj->IsVMHeapObject());
       if (obj->IsMarked()) {
-        // Precompiled instructions are loaded pre-marked.
+        // Precompiled objects are loaded pre-marked.
         ASSERT(Dart::IsRunningPrecompiledCode());
-        ASSERT(obj->IsInstructions());
+        ASSERT(obj->IsInstructions() ||
+               obj->IsPcDescriptors() ||
+               obj->IsStackmap() ||
+               obj->IsOneByteString());
       } else {
         obj->SetMarkBitUnsynchronized();
       }
@@ -3690,13 +3690,13 @@
     }
     if (other.IsFunctionClass()) {
       // Check if type S has a call() method.
-      Function& function =
-          Function::Handle(zone, thsi.LookupDynamicFunction(Symbols::Call()));
+      Function& function = Function::Handle(zone,
+          thsi.LookupDynamicFunctionAllowAbstract(Symbols::Call()));
       if (function.IsNull()) {
         // Walk up the super_class chain.
         Class& cls = Class::Handle(zone, thsi.SuperClass());
         while (!cls.IsNull() && function.IsNull()) {
-          function = cls.LookupDynamicFunction(Symbols::Call());
+          function = cls.LookupDynamicFunctionAllowAbstract(Symbols::Call());
           cls = cls.SuperClass();
         }
       }
@@ -3819,6 +3819,12 @@
 }
 
 
+RawFunction* Class::LookupDynamicFunctionAllowAbstract(
+    const String& name) const {
+  return LookupFunction(name, kInstanceAllowAbstract);
+}
+
+
 RawFunction* Class::LookupDynamicFunctionAllowPrivate(
     const String& name) const {
   return LookupFunctionAllowPrivate(name, kInstance);
@@ -3891,8 +3897,8 @@
 
 
 RawFunction* Class::CheckFunctionType(const Function& func, MemberKind kind) {
-  if (kind == kInstance) {
-    if (func.IsDynamicFunction()) {
+  if ((kind == kInstance) || (kind == kInstanceAllowAbstract)) {
+    if (func.IsDynamicFunction(kind == kInstanceAllowAbstract)) {
       return func.raw();
     }
   } else if (kind == kStatic) {
@@ -6030,26 +6036,29 @@
   AbstractType& other_res_type = AbstractType::Handle(other.result_type());
   if (!other_res_type.IsInstantiated()) {
     other_res_type = other_res_type.InstantiateFrom(other_type_arguments,
-                                                    bound_error);
+                                                    bound_error,
+                                                    NULL, NULL, space);
     ASSERT((bound_error == NULL) || bound_error->IsNull());
   }
   if (!other_res_type.IsDynamicType() && !other_res_type.IsVoidType()) {
     AbstractType& res_type = AbstractType::Handle(result_type());
     if (!res_type.IsInstantiated()) {
-      res_type = res_type.InstantiateFrom(type_arguments, bound_error);
+      res_type = res_type.InstantiateFrom(type_arguments, bound_error,
+                                          NULL, NULL, space);
       ASSERT((bound_error == NULL) || bound_error->IsNull());
     }
     if (res_type.IsVoidType()) {
       return false;
     }
     if (test_kind == kIsSubtypeOf) {
-      if (!res_type.IsSubtypeOf(other_res_type, bound_error) &&
-          !other_res_type.IsSubtypeOf(res_type, bound_error)) {
+      if (!res_type.IsSubtypeOf(other_res_type, bound_error, NULL, space) &&
+          !other_res_type.IsSubtypeOf(res_type, bound_error, NULL, space)) {
         return false;
       }
     } else {
       ASSERT(test_kind == kIsMoreSpecificThan);
-      if (!res_type.IsMoreSpecificThan(other_res_type, bound_error)) {
+      if (!res_type.IsMoreSpecificThan(other_res_type, bound_error,
+                                       NULL, space)) {
         return false;
       }
     }
@@ -6418,7 +6427,8 @@
     if (instantiate &&
         param_type.IsFinalized() &&
         !param_type.IsInstantiated()) {
-      param_type = param_type.InstantiateFrom(instantiator, NULL);
+      param_type = param_type.InstantiateFrom(instantiator, NULL,
+                                              NULL, NULL, Heap::kNew);
     }
     name = param_type.BuildName(name_visibility);
     pieces->Add(name);
@@ -6445,7 +6455,8 @@
       if (instantiate &&
           param_type.IsFinalized() &&
           !param_type.IsInstantiated()) {
-        param_type = param_type.InstantiateFrom(instantiator, NULL);
+        param_type = param_type.InstantiateFrom(instantiator, NULL,
+                                                NULL, NULL, Heap::kNew);
       }
       ASSERT(!param_type.IsNull());
       name = param_type.BuildName(name_visibility);
@@ -6543,7 +6554,8 @@
   pieces.Add(Symbols::RParenArrow());
   AbstractType& res_type = AbstractType::Handle(zone, result_type());
   if (instantiate && res_type.IsFinalized() && !res_type.IsInstantiated()) {
-    res_type = res_type.InstantiateFrom(instantiator, NULL);
+    res_type = res_type.InstantiateFrom(instantiator, NULL,
+                                        NULL, NULL, Heap::kNew);
   }
   name = res_type.BuildName(name_visibility);
   pieces.Add(name);
@@ -6775,7 +6787,7 @@
 
 void Function::RestoreICDataMap(
     ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data,
-    bool clone_descriptors) const {
+    bool clone_ic_data) const {
   ASSERT(deopt_id_to_ic_data->is_empty());
   Zone* zone = Thread::Current()->zone();
   const Array& saved_ic_data = Array::Handle(zone, ic_data_array());
@@ -6795,9 +6807,9 @@
     for (intptr_t i = 1; i < saved_length; i++) {
       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);
+      if (clone_ic_data) {
+        const ICData& original_ic_data = ICData::Handle(zone, ic_data.raw());
+        ic_data = ICData::Clone(ic_data);
         ic_data.SetOriginal(original_ic_data);
       }
       (*deopt_id_to_ic_data)[ic_data.deopt_id()] = &ic_data;
@@ -11675,7 +11687,6 @@
 
 
 void ICData::set_owner(const Function& value) const {
-  ASSERT(!value.IsNull());
   StorePointer(&raw_ptr()->owner_, reinterpret_cast<RawObject*>(value.raw()));
 }
 
@@ -11739,35 +11750,6 @@
 }
 
 
-bool ICData::IssuedJSWarning() const {
-  return IssuedJSWarningBit::decode(raw_ptr()->state_bits_);
-}
-
-
-void ICData::SetIssuedJSWarning() const {
-  StoreNonPointer(&raw_ptr()->state_bits_,
-                  IssuedJSWarningBit::update(true, raw_ptr()->state_bits_));
-}
-
-
-bool ICData::MayCheckForJSWarning() const {
-  const String& name = String::Handle(target_name());
-  // Warning issued from native code.
-  // Calling sequence is decoded to obtain ic data in order to check if a
-  // warning has already been issued.
-  if (name.Equals(Library::PrivateCoreLibName(Symbols::_instanceOf())) ||
-      name.Equals(Library::PrivateCoreLibName(Symbols::_as()))) {
-    return true;
-  }
-  // Warning issued in ic miss handler.
-  // No decoding necessary, so allow optimization if warning already issued.
-  if (name.Equals(Symbols::toString()) && !IssuedJSWarning()) {
-    return true;
-  }
-  return false;
-}
-
-
 void ICData::set_state_bits(uint32_t bits) const {
   StoreNonPointer(&raw_ptr()->state_bits_, bits);
 }
@@ -12326,7 +12308,7 @@
 }
 
 
-RawICData* ICData::CloneDescriptor(const ICData& from) {
+RawICData* ICData::Clone(const ICData& from) {
   Zone* zone = Thread::Current()->zone();
   const ICData& result = ICData::Handle(ICData::NewDescriptor(
       zone,
@@ -12335,8 +12317,17 @@
       Array::Handle(zone, from.arguments_descriptor()),
       from.deopt_id(),
       from.NumArgsTested()));
-  // Preserve entry array.
-  result.set_ic_data_array(Array::Handle(zone, from.ic_data()));
+  // Clone entry array.
+  const Array& from_array = Array::Handle(zone, from.ic_data());
+  const intptr_t len = from_array.Length();
+  const Array& cloned_array =
+      Array::Handle(zone, Array::New(len, Heap::kOld));
+  Object& obj = Object::Handle(zone);
+  for (intptr_t i = 0; i < len; i++) {
+    obj = from_array.At(i);
+    cloned_array.SetAt(i, obj);
+  }
+  result.set_ic_data_array(cloned_array);
   // Copy deoptimization reasons.
   result.SetDeoptReasons(from.DeoptReasons());
   return result.raw();
@@ -14205,6 +14196,7 @@
                             Error* bound_error) const {
   ASSERT(other.IsFinalized());
   ASSERT(!other.IsDynamicType());
+  ASSERT(!other.IsTypeRef());  // Must be dereferenced at compile time.
   ASSERT(!other.IsMalformed());
   ASSERT(!other.IsMalbounded());
   if (other.IsVoidType()) {
@@ -14220,12 +14212,16 @@
     TypeArguments& other_type_arguments = TypeArguments::Handle(zone);
     // Note that we may encounter a bound error in checked mode.
     if (!other.IsInstantiated()) {
-      const AbstractType& instantiated_other = AbstractType::Handle(
-          zone, other.InstantiateFrom(other_instantiator, bound_error));
+      AbstractType& instantiated_other = AbstractType::Handle(
+          zone, other.InstantiateFrom(other_instantiator, bound_error,
+                                      NULL, NULL, Heap::kOld));
       if ((bound_error != NULL) && !bound_error->IsNull()) {
         ASSERT(Isolate::Current()->flags().type_checks());
         return false;
       }
+      if (instantiated_other.IsTypeRef()) {
+        instantiated_other = TypeRef::Cast(instantiated_other).type();
+      }
       if (instantiated_other.IsDynamicType() ||
           instantiated_other.IsObjectType() ||
           instantiated_other.IsDartFunctionType()) {
@@ -14273,7 +14269,8 @@
   AbstractType& instantiated_other = AbstractType::Handle(zone, other.raw());
   // Note that we may encounter a bound error in checked mode.
   if (!other.IsInstantiated()) {
-    instantiated_other = other.InstantiateFrom(other_instantiator, bound_error);
+    instantiated_other = other.InstantiateFrom(other_instantiator, bound_error,
+                                               NULL, NULL, Heap::kOld);
     if ((bound_error != NULL) && !bound_error->IsNull()) {
       ASSERT(Isolate::Current()->flags().type_checks());
       return false;
@@ -14289,13 +14286,13 @@
   const bool other_is_dart_function = instantiated_other.IsDartFunctionType();
   if (other_is_dart_function || instantiated_other.IsFunctionType()) {
     // Check if this instance understands a call() method of a compatible type.
-    Function& call =
-        Function::Handle(zone, cls.LookupDynamicFunction(Symbols::Call()));
+    Function& call = Function::Handle(zone,
+        cls.LookupDynamicFunctionAllowAbstract(Symbols::Call()));
     if (call.IsNull()) {
       // Walk up the super_class chain.
       Class& super_cls = Class::Handle(zone, cls.SuperClass());
       while (!super_cls.IsNull() && call.IsNull()) {
-        call = super_cls.LookupDynamicFunction(Symbols::Call());
+        call = super_cls.LookupDynamicFunctionAllowAbstract(Symbols::Call());
         super_cls = super_cls.SuperClass();
       }
     }
@@ -15027,7 +15024,7 @@
     }
     // The current bound_trail cannot be used, because operands are swapped and
     // the test is different anyway (more specific vs. subtype).
-    if (bound.IsMoreSpecificThan(other, bound_error, NULL)) {
+    if (bound.IsMoreSpecificThan(other, bound_error, NULL, space)) {
       return true;
     }
     return false;  // TODO(regis): We should return "maybe after instantiation".
@@ -15056,13 +15053,13 @@
                           space);
     }
     // Check if type S has a call() method of function type T.
-    Function& function =
-        Function::Handle(zone, type_cls.LookupDynamicFunction(Symbols::Call()));
+    Function& function = Function::Handle(zone,
+        type_cls.LookupDynamicFunctionAllowAbstract(Symbols::Call()));
     if (function.IsNull()) {
       // Walk up the super_class chain.
       Class& cls = Class::Handle(zone, type_cls.SuperClass());
       while (!cls.IsNull() && function.IsNull()) {
-        function = cls.LookupDynamicFunction(Symbols::Call());
+        function = cls.LookupDynamicFunctionAllowAbstract(Symbols::Call());
         cls = cls.SuperClass();
       }
     }
@@ -16728,7 +16725,8 @@
           (!type_param.CheckBound(instantiated_bounded_type,
                                   instantiated_upper_bound,
                                   bound_error,
-                                  bound_trail) &&
+                                  bound_trail,
+                                  space) &&
            bound_error->IsNull())) {
         // We cannot determine yet whether the bounded_type is below the
         // upper_bound, because one or both of them is still being finalized or
@@ -16905,16 +16903,6 @@
 }
 
 
-// Throw JavascriptIntegerOverflow exception.
-static void ThrowJavascriptIntegerOverflow(const Integer& i) {
-  const Array& exc_args = Array::Handle(Array::New(1));
-  const String& i_str = String::Handle(String::New(i.ToCString()));
-  exc_args.SetAt(0, i_str);
-  Exceptions::ThrowByType(Exceptions::kJavascriptIntegerOverflowError,
-      exc_args);
-}
-
-
 RawInteger* Integer::New(const String& str, Heap::Space space) {
   // We are not supposed to have integers represented as two byte strings.
   ASSERT(str.IsOneByteString());
@@ -16924,19 +16912,12 @@
         Bigint::NewFromCString(str.ToCString(), space));
     ASSERT(!big.FitsIntoSmi());
     ASSERT(!big.FitsIntoInt64());
-    if (FLAG_throw_on_javascript_int_overflow) {
-      ThrowJavascriptIntegerOverflow(big);
-    }
     return big.raw();
   }
   return Integer::New(value, space);
 }
 
 
-// This is called from LiteralToken::New() in the parser, so we can't
-// raise an exception for javascript overflow here. Instead we do it in
-// Parser::CurrentIntegerLiteral(), which is the point in the parser where
-// integer literals escape, so we can call Parser::ErrorMsg().
 RawInteger* Integer::NewCanonical(const String& str) {
   // We are not supposed to have integers represented as two byte strings.
   ASSERT(str.IsOneByteString());
@@ -16954,16 +16935,8 @@
 }
 
 
-RawInteger* Integer::New(int64_t value, Heap::Space space, const bool silent) {
+RawInteger* Integer::New(int64_t value, Heap::Space space) {
   const bool is_smi = Smi::IsValid(value);
-  if (!silent &&
-      FLAG_throw_on_javascript_int_overflow &&
-      !Utils::IsJavascriptInt(value)) {
-    const Integer& i = is_smi ?
-        Integer::Handle(Smi::New(static_cast<intptr_t>(value))) :
-        Integer::Handle(Mint::New(value, space));
-    ThrowJavascriptIntegerOverflow(i);
-  }
   if (is_smi) {
     return Smi::New(static_cast<intptr_t>(value));
   }
@@ -16973,10 +16946,6 @@
 
 RawInteger* Integer::NewFromUint64(uint64_t value, Heap::Space space) {
   if (value > static_cast<uint64_t>(Mint::kMaxValue)) {
-    if (FLAG_throw_on_javascript_int_overflow) {
-      const Integer &i = Integer::Handle(Bigint::NewFromUint64(value, space));
-      ThrowJavascriptIntegerOverflow(i);
-    }
     return Bigint::NewFromUint64(value, space);
   } else {
     return Integer::New(value, space);
@@ -17040,31 +17009,7 @@
 }
 
 
-// Returns true if the signed Integer does not fit into a
-// Javascript integer.
-bool Integer::CheckJavascriptIntegerOverflow() const {
-  // Always overflow if the value doesn't fit into an int64_t.
-  int64_t value = 1ULL << 63;
-  if (IsSmi()) {
-    value = AsInt64Value();
-  } else if (IsMint()) {
-    Mint& mint = Mint::Handle();
-    mint ^= raw();
-    value = mint.value();
-  } else {
-    if (Bigint::Cast(*this).FitsIntoInt64()) {
-      value = AsInt64Value();
-    }
-  }
-  return !Utils::IsJavascriptInt(value);
-}
-
-
 RawInteger* Integer::AsValidInteger() const {
-  if (FLAG_throw_on_javascript_int_overflow &&
-      CheckJavascriptIntegerOverflow()) {
-    ThrowJavascriptIntegerOverflow(*this);
-  }
   if (IsSmi()) return raw();
   if (IsMint()) {
     Mint& mint = Mint::Handle();
@@ -17234,8 +17179,7 @@
 // TODO(srdjan): Clarify handling of negative right operand in a shift op.
 RawInteger* Smi::ShiftOp(Token::Kind kind,
                          const Smi& other,
-                         Heap::Space space,
-                         const bool silent) const {
+                         Heap::Space space) const {
   intptr_t result = 0;
   const intptr_t left_value = Value();
   const intptr_t right_value = other.Value();
@@ -17252,7 +17196,7 @@
             return Bigint::NewFromShiftedInt64(left_value, right_value, space);
           } else {
             int64_t left_64 = left_value;
-            return Integer::New(left_64 << right_value, space, silent);
+            return Integer::New(left_64 << right_value, space);
           }
         }
       }
@@ -17709,8 +17653,10 @@
     --used;
   }
   if (used > 0) {
-    if ((used & 1) != 0) {
-      // Set leading zero for 64-bit processing of digit pairs.
+    if (((used & 1) != 0) && (digits.GetUint32(used << 2) != 0)) {
+      // Set leading zero for 64-bit processing of digit pairs if not set.
+      // The check above ensures that we avoid a write access to a possibly
+      // reused digits array that could be marked read only.
       digits.SetUint32(used << 2, 0);
     }
     result.set_digits(digits);
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 34440a1..ebd93ae 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1132,8 +1132,8 @@
                    const Class& other,
                    const TypeArguments& other_type_arguments,
                    Error* bound_error,
-                   TrailPtr bound_trail = NULL,
-                   Heap::Space space = Heap::kNew) const {
+                   TrailPtr bound_trail,
+                   Heap::Space space) const {
     return TypeTest(kIsSubtypeOf,
                     type_arguments,
                     other,
@@ -1148,8 +1148,8 @@
                           const Class& other,
                           const TypeArguments& other_type_arguments,
                           Error* bound_error,
-                          TrailPtr bound_trail = NULL,
-                          Heap::Space space = Heap::kNew) const {
+                          TrailPtr bound_trail,
+                          Heap::Space space) const {
     return TypeTest(kIsMoreSpecificThan,
                     type_arguments,
                     other,
@@ -1186,6 +1186,7 @@
   RawFunction* ImplicitClosureFunctionFromIndex(intptr_t idx) const;
 
   RawFunction* LookupDynamicFunction(const String& name) const;
+  RawFunction* LookupDynamicFunctionAllowAbstract(const String& name) const;
   RawFunction* LookupDynamicFunctionAllowPrivate(const String& name) const;
   RawFunction* LookupStaticFunction(const String& name) const;
   RawFunction* LookupStaticFunctionAllowPrivate(const String& name) const;
@@ -1373,6 +1374,7 @@
     kAny = 0,
     kStatic,
     kInstance,
+    kInstanceAllowAbstract,
     kConstructor,
     kFactory,
   };
@@ -1582,8 +1584,8 @@
                    intptr_t from_index,
                    intptr_t len,
                    Error* bound_error,
-                   TrailPtr bound_trail = NULL,
-                   Heap::Space space = Heap::kNew) const {
+                   TrailPtr bound_trail,
+                   Heap::Space space) const {
     return TypeTest(kIsSubtypeOf, other, from_index, len,
                     bound_error, bound_trail, space);
   }
@@ -1594,8 +1596,8 @@
                           intptr_t from_index,
                           intptr_t len,
                           Error* bound_error,
-                          TrailPtr bound_trail = NULL,
-                          Heap::Space space = Heap::kNew) const {
+                          TrailPtr bound_trail,
+                          Heap::Space space) const {
     return TypeTest(kIsMoreSpecificThan, other, from_index, len,
                     bound_error, bound_trail, space);
   }
@@ -1653,9 +1655,9 @@
   RawTypeArguments* InstantiateFrom(
       const TypeArguments& instantiator_type_arguments,
       Error* bound_error,
-      TrailPtr instantiation_trail = NULL,
-      TrailPtr bound_trail = NULL,
-      Heap::Space space = Heap::kNew) const;
+      TrailPtr instantiation_trail,
+      TrailPtr bound_trail,
+      Heap::Space space) const;
 
   // Runtime instantiation with canonicalization. Not to be used during type
   // finalization at compile time.
@@ -1839,13 +1841,6 @@
   bool HasDeoptReason(ICData::DeoptReasonId reason) const;
   void AddDeoptReason(ICData::DeoptReasonId reason) const;
 
-  bool IssuedJSWarning() const;
-  void SetIssuedJSWarning() const;
-
-  // Return true if the target function of this IC data may check for (and
-  // possibly issue) a Javascript compatibility warning.
-  bool MayCheckForJSWarning() const;
-
   intptr_t NumberOfChecks() const;
 
   // Discounts any checks with usage of zero.
@@ -1946,11 +1941,8 @@
                         intptr_t num_args_tested);
   static RawICData* NewFrom(const ICData& from, intptr_t num_args_tested);
 
-  // Generates a new ICData with descriptor data copied (shallow clone).
-  // Entry array of the result is the same as in 'from'. Once entry array is
-  // created, it can only change the 'count', all other properties are invariant
-  // (target, cids, number of checks).
-  static RawICData* CloneDescriptor(const ICData& from);
+  // Generates a new ICData with descriptor and data array copied (deep clone).
+  static RawICData* Clone(const ICData& from);
 
   static intptr_t TestEntryLengthFor(intptr_t num_args);
 
@@ -2034,7 +2026,7 @@
     }
   }
 
-  // It is only meaningful to interptret range feedback stored in the ICData
+  // It is only meaningful to interpret range feedback stored in the ICData
   // when all checks are Mint or Smi.
   bool HasRangeFeedback() const;
   RangeFeedback DecodeRangeFeedbackAt(intptr_t idx) const;
@@ -2073,8 +2065,7 @@
     kNumArgsTestedSize = 2,
     kDeoptReasonPos = kNumArgsTestedPos + kNumArgsTestedSize,
     kDeoptReasonSize = kLastRecordedDeoptReason + 1,
-    kIssuedJSWarningBit = kDeoptReasonPos + kDeoptReasonSize,
-    kRangeFeedbackPos = kIssuedJSWarningBit + 1,
+    kRangeFeedbackPos = kDeoptReasonPos + kDeoptReasonSize,
     kRangeFeedbackSize = kBitsPerRangeFeedback * kRangeFeedbackSlots
   };
 
@@ -2086,8 +2077,6 @@
                                           uint32_t,
                                           ICData::kDeoptReasonPos,
                                           ICData::kDeoptReasonSize> {};
-  class IssuedJSWarningBit :
-      public BitField<uint32_t, bool, kIssuedJSWarningBit, 1> {};
   class RangeFeedbackBits : public BitField<uint32_t,
                                             uint32_t,
                                             ICData::kRangeFeedbackPos,
@@ -2315,8 +2304,8 @@
   bool IsFactory() const {
     return (kind() == RawFunction::kConstructor) && is_static();
   }
-  bool IsDynamicFunction() const {
-    if (is_static() || is_abstract()) {
+  bool IsDynamicFunction(bool allow_abstract = false) const {
+    if (is_static() || (!allow_abstract && is_abstract())) {
       return false;
     }
     switch (kind()) {
@@ -2501,7 +2490,7 @@
                    const Function& other,
                    const TypeArguments& other_type_arguments,
                    Error* bound_error,
-                   Heap::Space space = Heap::kNew) const {
+                   Heap::Space space) const {
     return TypeTest(kIsSubtypeOf,
                     type_arguments,
                     other,
@@ -2516,7 +2505,7 @@
                           const Function& other,
                           const TypeArguments& other_type_arguments,
                           Error* bound_error,
-                          Heap::Space space = Heap::kNew) const {
+                          Heap::Space space) const {
     return TypeTest(kIsMoreSpecificThan,
                     type_arguments,
                     other,
@@ -2689,9 +2678,9 @@
       const ZoneGrowableArray<const ICData*>& deopt_id_to_ic_data,
       const Array& edge_counters_array) const;
   // Uses 'ic_data_array' to populate the table 'deopt_id_to_ic_data'. Clone
-  // descriptors if 'clone_descriptors' true.
+  // ic_data (array and descriptor) if 'clone_ic_data' is true.
   void RestoreICDataMap(ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data,
-                        bool clone_descriptors) const;
+                        bool clone_ic_data) const;
 
   RawArray* ic_data_array() const;
   void ClearICDataArray() const;
@@ -5283,9 +5272,9 @@
   virtual RawAbstractType* InstantiateFrom(
       const TypeArguments& instantiator_type_arguments,
       Error* bound_error,
-      TrailPtr instantiation_trail = NULL,
-      TrailPtr bound_trail = NULL,
-      Heap::Space space = Heap::kNew) const;
+      TrailPtr instantiation_trail,
+      TrailPtr bound_trail,
+      Heap::Space space) const;
 
   // Return a clone of this unfinalized type or the type itself if it is
   // already finalized. Apply recursively to type arguments, i.e. finalized
@@ -5398,16 +5387,16 @@
   // Check the subtype relationship.
   bool IsSubtypeOf(const AbstractType& other,
                    Error* bound_error,
-                   TrailPtr bound_trail = NULL,
-                   Heap::Space space = Heap::kNew) const {
+                   TrailPtr bound_trail,
+                   Heap::Space space) const {
     return TypeTest(kIsSubtypeOf, other, bound_error, bound_trail, space);
   }
 
   // Check the 'more specific' relationship.
   bool IsMoreSpecificThan(const AbstractType& other,
                           Error* bound_error,
-                          TrailPtr bound_trail = NULL,
-                          Heap::Space space = Heap::kNew) const {
+                          TrailPtr bound_trail,
+                          Heap::Space space) const {
     return TypeTest(kIsMoreSpecificThan, other,
                     bound_error, bound_trail, space);
   }
@@ -5476,9 +5465,9 @@
   virtual RawAbstractType* InstantiateFrom(
       const TypeArguments& instantiator_type_arguments,
       Error* bound_error,
-      TrailPtr instantiation_trail = NULL,
-      TrailPtr bound_trail = NULL,
-      Heap::Space space = Heap::kNew) const;
+      TrailPtr instantiation_trail,
+      TrailPtr bound_trail,
+      Heap::Space space) const;
   virtual RawAbstractType* CloneUnfinalized() const;
   virtual RawAbstractType* CloneUninstantiated(
       const Class& new_owner,
@@ -5624,9 +5613,9 @@
   virtual RawAbstractType* InstantiateFrom(
       const TypeArguments& instantiator_type_arguments,
       Error* malformed_error,
-      TrailPtr instantiation_trail = NULL,
-      TrailPtr bound_trail = NULL,
-      Heap::Space space = Heap::kNew) const;
+      TrailPtr instantiation_trail,
+      TrailPtr bound_trail,
+      Heap::Space space) const;
   virtual RawAbstractType* CloneUnfinalized() const;
   virtual RawAbstractType* CloneUninstantiated(
       const Class& new_owner,
@@ -5701,9 +5690,9 @@
   virtual RawTypeRef* InstantiateFrom(
       const TypeArguments& instantiator_type_arguments,
       Error* bound_error,
-      TrailPtr instantiation_trail = NULL,
-      TrailPtr bound_trail = NULL,
-      Heap::Space space = Heap::kNew) const;
+      TrailPtr instantiation_trail,
+      TrailPtr bound_trail,
+      Heap::Space space) const;
   virtual RawTypeRef* CloneUninstantiated(
       const Class& new_owner,
       TrailPtr trail = NULL) const;
@@ -5763,8 +5752,8 @@
   bool CheckBound(const AbstractType& bounded_type,
                   const AbstractType& upper_bound,
                   Error* bound_error,
-                  TrailPtr bound_trail = NULL,
-                  Heap::Space space = Heap::kNew) const;
+                  TrailPtr bound_trail,
+                  Heap::Space space) const;
   virtual TokenPosition token_pos() const { return raw_ptr()->token_pos_; }
   virtual bool IsInstantiated(TrailPtr trail = NULL) const {
     return false;
@@ -5774,9 +5763,9 @@
   virtual RawAbstractType* InstantiateFrom(
       const TypeArguments& instantiator_type_arguments,
       Error* bound_error,
-      TrailPtr instantiation_trail = NULL,
-      TrailPtr bound_trail = NULL,
-      Heap::Space space = Heap::kNew) const;
+      TrailPtr instantiation_trail,
+      TrailPtr bound_trail,
+      Heap::Space space) const;
   virtual RawAbstractType* CloneUnfinalized() const;
   virtual RawAbstractType* CloneUninstantiated(
       const Class& new_owner, TrailPtr trail = NULL) const;
@@ -5860,9 +5849,9 @@
   virtual RawAbstractType* InstantiateFrom(
       const TypeArguments& instantiator_type_arguments,
       Error* bound_error,
-      TrailPtr instantiation_trail = NULL,
-      TrailPtr bound_trail = NULL,
-      Heap::Space space = Heap::kNew) const;
+      TrailPtr instantiation_trail,
+      TrailPtr bound_trail,
+      Heap::Space space) const;
   virtual RawAbstractType* CloneUnfinalized() const;
   virtual RawAbstractType* CloneUninstantiated(
       const Class& new_owner, TrailPtr trail = NULL) const;
@@ -5965,10 +5954,7 @@
   // Returns a canonical Integer object allocated in the old gen space.
   static RawInteger* NewCanonical(const String& str);
 
-  // Do not throw JavascriptIntegerOverflow if 'silent' is true.
-  static RawInteger* New(int64_t value,
-                         Heap::Space space = Heap::kNew,
-                         const bool silent = false);
+  static RawInteger* New(int64_t value, Heap::Space space = Heap::kNew);
 
   virtual bool OperatorEquals(const Instance& other) const {
     return Equals(other);
@@ -6006,9 +5992,6 @@
                     const Integer& other,
                     Heap::Space space = Heap::kNew) const;
 
-  // Returns true if the Integer does not fit in a Javascript integer.
-  bool CheckJavascriptIntegerOverflow() const;
-
  private:
   OBJECT_IMPLEMENTATION(Integer, Number);
   friend class Class;
@@ -6065,8 +6048,7 @@
 
   RawInteger* ShiftOp(Token::Kind kind,
                       const Smi& other,
-                      Heap::Space space = Heap::kNew,
-                      const bool silent = false) const;
+                      Heap::Space space = Heap::kNew) const;
 
   void operator=(RawSmi* value) {
     raw_ = value;
@@ -6597,6 +6579,7 @@
   friend class ExternalTwoByteString;
   // So that SkippedCodeFunctions can print a debug string from a NoHandleScope.
   friend class SkippedCodeFunctions;
+  friend class RawOneByteString;
 };
 
 
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc
index caea245..ff0fa53 100644
--- a/runtime/vm/pages.cc
+++ b/runtime/vm/pages.cc
@@ -59,7 +59,7 @@
   ASSERT(result != NULL);
   result->memory_ = memory;
   result->next_ = NULL;
-  result->executable_ = is_executable;
+  result->type_ = type;
   return result;
 }
 
@@ -132,7 +132,7 @@
 void HeapPage::WriteProtect(bool read_only) {
   VirtualMemory::Protection prot;
   if (read_only) {
-    if (executable_) {
+    if (type_ == kExecutable) {
       prot = VirtualMemory::kReadExecute;
     } else {
       prot = VirtualMemory::kReadOnly;
@@ -665,7 +665,9 @@
     AbandonBumpAllocation();
   }
   for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) {
-    if ((it.page()->type() != HeapPage::kExecutable) || include_code_pages) {
+    HeapPage::PageType page_type = it.page()->type();
+    if ((page_type != HeapPage::kReadOnlyData) &&
+        ((page_type != HeapPage::kExecutable) || include_code_pages)) {
       it.page()->WriteProtect(read_only);
     }
   }
@@ -1071,7 +1073,9 @@
 }
 
 
-void PageSpace::SetupInstructionsSnapshotPage(void* pointer, uword size) {
+void PageSpace::SetupExternalPage(void* pointer,
+                                  uword size,
+                                  bool is_executable) {
   // Setup a HeapPage so precompiled Instructions can be traversed.
   // Instructions are contiguous at [pointer, pointer + size). HeapPage
   // expects to find objects at [memory->start() + ObjectStartOffset,
@@ -1080,23 +1084,31 @@
   pointer = reinterpret_cast<void*>(reinterpret_cast<uword>(pointer) - offset);
   size += offset;
 
-  ASSERT(Utils::IsAligned(pointer, OS::PreferredCodeAlignment()));
-
-  VirtualMemory* memory = VirtualMemory::ForInstructionsSnapshot(pointer, size);
+  VirtualMemory* memory = VirtualMemory::ForExternalPage(pointer, size);
   ASSERT(memory != NULL);
   HeapPage* page = reinterpret_cast<HeapPage*>(malloc(sizeof(HeapPage)));
   page->memory_ = memory;
   page->next_ = NULL;
   page->object_end_ = memory->end();
-  page->executable_ = true;
 
   MutexLocker ml(pages_lock_);
-  if (exec_pages_ == NULL) {
-    exec_pages_ = page;
+  HeapPage** first, **tail;
+  if (is_executable) {
+    ASSERT(Utils::IsAligned(pointer, OS::PreferredCodeAlignment()));
+    page->type_ = HeapPage::kExecutable;
+    first = &exec_pages_;
+    tail = &exec_pages_tail_;
   } else {
-    exec_pages_tail_->set_next(page);
+    page->type_ = HeapPage::kReadOnlyData;
+    first = &pages_;
+    tail = &pages_tail_;
   }
-  exec_pages_tail_ = page;
+  if (*first == NULL) {
+    *first = page;
+  } else {
+    (*tail)->set_next(page);
+  }
+  (*tail) = page;
 }
 
 
diff --git a/runtime/vm/pages.h b/runtime/vm/pages.h
index 17d1674..008b7cd 100644
--- a/runtime/vm/pages.h
+++ b/runtime/vm/pages.h
@@ -31,6 +31,7 @@
   enum PageType {
     kData = 0,
     kExecutable,
+    kReadOnlyData,
     kNumPageTypes
   };
 
@@ -49,7 +50,7 @@
   }
 
   PageType type() const {
-    return executable_ ? kExecutable : kData;
+    return type_;
   }
 
   void VisitObjects(ObjectVisitor* visitor) const;
@@ -80,7 +81,7 @@
   VirtualMemory* memory_;
   HeapPage* next_;
   uword object_end_;
-  bool executable_;
+  PageType type_;
 
   friend class PageSpace;
 
@@ -346,7 +347,7 @@
   static intptr_t top_offset() { return OFFSET_OF(PageSpace, bump_top_); }
   static intptr_t end_offset() { return OFFSET_OF(PageSpace, bump_end_); }
 
-  void SetupInstructionsSnapshotPage(void* pointer, uword size);
+  void SetupExternalPage(void* pointer, uword size, bool is_executable);
 
  private:
   // Ids for time and data records in Heap::GCStats.
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 2449f9d..048c184 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -59,8 +59,6 @@
 DECLARE_FLAG(bool, lazy_dispatchers);
 DECLARE_FLAG(bool, load_deferred_eagerly);
 DECLARE_FLAG(bool, profile_vm);
-DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
-DECLARE_FLAG(bool, warn_on_javascript_compatibility);
 
 // Quick access to the current thread, isolate and zone.
 #define T (thread())
@@ -423,6 +421,7 @@
   if (unregister_pending_function_) {
     const GrowableObjectArray& pending_functions =
         GrowableObjectArray::Handle(T->pending_functions());
+    ASSERT(!pending_functions.IsNull());
     ASSERT(pending_functions.Length() > 0);
     ASSERT(pending_functions.At(pending_functions.Length() - 1) ==
         current_function().raw());
@@ -537,14 +536,6 @@
   literal_token_ ^= tokens_iterator_.CurrentToken();
   ASSERT(literal_token_.kind() == Token::kINTEGER);
   RawInteger* ri = Integer::RawCast(literal_token_.value());
-  if (FLAG_throw_on_javascript_int_overflow) {
-    const Integer& i = Integer::Handle(Z, ri);
-    if (i.CheckJavascriptIntegerOverflow()) {
-      ReportError(TokenPos(),
-                  "Integer literal does not fit in a Javascript integer: %s.",
-                  i.ToCString());
-    }
-  }
   return ri;
 }
 
@@ -2961,6 +2952,7 @@
 void Parser::CheckRecursiveInvocation() {
   const GrowableObjectArray& pending_functions =
       GrowableObjectArray::Handle(Z, T->pending_functions());
+  ASSERT(!pending_functions.IsNull());
   for (int i = 0; i < pending_functions.Length(); i++) {
     if (pending_functions.At(i) == current_function().raw()) {
       const String& fname =
@@ -2969,7 +2961,7 @@
     }
   }
   ASSERT(!unregister_pending_function_);
-  pending_functions.Add(current_function());
+  pending_functions.Add(current_function(), Heap::kOld);
   unregister_pending_function_ = true;
 }
 
@@ -9803,7 +9795,8 @@
     AstNode* store_current =
         new(Z) InstanceSetterNode(TokenPosition::kNoSource,
                                   iterator,
-                                  String::ZoneHandle(Symbols::Current().raw()),
+                                  Library::PrivateCoreLibName(
+                                      Symbols::_current()),
                                   expr);
     yield->AddNode(store_current);
     if (is_yield_each) {
@@ -11114,36 +11107,32 @@
       (cls.library() == Library::CoreLibrary()) &&
       (func.name() == Symbols::Identical().raw())) {
     // This is the predefined toplevel function identical(a,b).
-    // Create a comparison node instead of a static call to the function, unless
-    // javascript warnings are desired and identical is not invoked from a patch
-    // source.
-    if (!FLAG_warn_on_javascript_compatibility || is_patch_source()) {
-      ASSERT(num_arguments == 2);
+    // Create a comparison node instead of a static call to the function.
+    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)));
-        }
+    // 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),
-                                   arguments->NodeAt(1));
     }
+    return new(Z) ComparisonNode(ident_pos,
+                                 Token::kEQ_STRICT,
+                                 arguments->NodeAt(0),
+                                 arguments->NodeAt(1));
   }
   return new(Z) StaticCallNode(ident_pos, func, arguments);
 }
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index 30fb890..65b6166 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -22,6 +22,7 @@
 #include "vm/flow_graph_compiler.h"
 #include "vm/flow_graph_inliner.h"
 #include "vm/flow_graph_optimizer.h"
+#include "vm/flow_graph_range_analysis.h"
 #include "vm/flow_graph_type_propagator.h"
 #include "vm/hash_table.h"
 #include "vm/il_printer.h"
@@ -347,10 +348,6 @@
     { "dart:core", "_CastError", "_CastError._create" },
     { "dart:core", "_InternalError", "_InternalError." },
     { "dart:core", "_InvocationMirror", "_allocateInvocationMirror" },
-    { "dart:core", "_JavascriptCompatibilityError",
-                   "_JavascriptCompatibilityError." },
-    { "dart:core", "_JavascriptIntegerOverflowError",
-                   "_JavascriptIntegerOverflowError." },
     { "dart:core", "_TypeError", "_TypeError._create" },
     { "dart:isolate", "IsolateSpawnException", "IsolateSpawnException." },
     { "dart:isolate", "::", "_getIsolateScheduleImmediateClosure" },
@@ -1917,7 +1914,8 @@
           // We have to perform range analysis after LICM because it
           // optimistically moves CheckSmi through phis into loop preheaders
           // making some phis smi.
-          optimizer.InferIntRanges();
+          RangeAnalysis range_analysis(flow_graph);
+          range_analysis.Analyze();
           DEBUG_ASSERT(flow_graph->VerifyUseLists());
         }
 
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index c7c44a2..a262edf 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -436,6 +436,15 @@
   bool IsString() {
     return IsStringClassId(GetClassId());
   }
+  bool IsStackmap() {
+    return ((GetClassId() == kStackmapCid));
+  }
+  bool IsPcDescriptors() {
+    return ((GetClassId() == kPcDescriptorsCid));
+  }
+  bool IsOneByteString() {
+    return ((GetClassId() == kOneByteStringCid));
+  }
 
   intptr_t Size() const {
     uword tags = ptr()->tags_;
@@ -1428,14 +1437,17 @@
   RAW_HEAP_OBJECT_IMPLEMENTATION(ICData);
 
   RawObject** from() {
-    return reinterpret_cast<RawObject**>(&ptr()->owner_);
+    return reinterpret_cast<RawObject**>(&ptr()->ic_data_);
   }
-  RawObject* owner_;  // Parent/calling function or original IC of cloned IC.
+  RawArray* ic_data_;  // Contains class-ids, target and count.
   RawString* target_name_;  // Name of target function.
   RawArray* args_descriptor_;  // Arguments descriptor.
-  RawArray* ic_data_;  // Contains class-ids, target and count.
+  RawObject** to_precompiled_snapshot() {
+    return reinterpret_cast<RawObject**>(&ptr()->args_descriptor_);
+  }
+  RawObject* owner_;  // Parent/calling function or original IC of cloned IC.
   RawObject** to() {
-    return reinterpret_cast<RawObject**>(&ptr()->ic_data_);
+    return reinterpret_cast<RawObject**>(&ptr()->owner_);
   }
   int32_t deopt_id_;     // Deoptimization id corresponding to this IC.
   uint32_t state_bits_;  // Number of arguments tested in IC, deopt reasons,
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 1a617ba..405c2e4 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -1477,7 +1477,11 @@
   ASSERT(reader->snapshot_code());
   ASSERT(kind == Snapshot::kFull);
 
+#ifdef DEBUG
   intptr_t full_tags = static_cast<uword>(reader->Read<intptr_t>());
+#else
+  intptr_t full_tags = 0;  // unused in release mode
+#endif
   intptr_t offset = reader->Read<int32_t>();
   Instructions& result =
       Instructions::ZoneHandle(reader->zone(),
@@ -1499,6 +1503,7 @@
   writer->WriteVMIsolateObject(kInstructionsCid);
   writer->WriteTags(writer->GetObjectTags(this));
 
+#ifdef DEBUG
   // Instructions will be written pre-marked and in the VM heap. Write out
   // the tags we expect to find when reading the snapshot for a sanity check
   // that our offsets/alignment didn't get out of sync.
@@ -1506,6 +1511,7 @@
   written_tags = RawObject::VMHeapObjectTag::update(true, written_tags);
   written_tags = RawObject::MarkBit::update(true, written_tags);
   writer->Write<intptr_t>(written_tags);
+#endif
 
   writer->Write<int32_t>(writer->GetInstructionsId(this));
 }
@@ -1643,19 +1649,11 @@
   ASSERT(reader->snapshot_code());
   ASSERT(kind == Snapshot::kFull);
 
-  const int32_t length = reader->Read<int32_t>();
-  PcDescriptors& result =
-      PcDescriptors::ZoneHandle(reader->zone(),
-                                NEW_OBJECT_WITH_LEN(PcDescriptors, length));
+  intptr_t offset = reader->Read<int32_t>();
+  PcDescriptors& result = PcDescriptors::ZoneHandle(reader->zone());
+  result ^= reader->GetObjectAt(offset);
   reader->AddBackRef(object_id, &result, kIsDeserialized);
 
-  if (result.Length() > 0) {
-    NoSafepointScope no_safepoint;
-    intptr_t len = result.Length();
-    uint8_t* data = result.UnsafeMutableNonPointer(result.raw_ptr()->data());
-    reader->ReadBytes(data, len);
-  }
-
   return result.raw();
 }
 
@@ -1671,12 +1669,8 @@
   writer->WriteInlinedObjectHeader(object_id);
   writer->WriteIndexedObject(kPcDescriptorsCid);
   writer->WriteTags(writer->GetObjectTags(this));
-  writer->Write<int32_t>(ptr()->length_);
-  if (ptr()->length_ > 0) {
-    intptr_t len = ptr()->length_;
-    uint8_t* data = reinterpret_cast<uint8_t*>(ptr()->data());
-    writer->WriteBytes(data, len);
-  }
+
+  writer->Write<int32_t>(writer->GetObjectId(this));
 }
 
 
@@ -1733,22 +1727,11 @@
   ASSERT(reader->snapshot_code());
   ASSERT(kind == Snapshot::kFull);
 
-  const int32_t length = reader->Read<int32_t>();
-  Stackmap& result =
-      Stackmap::ZoneHandle(reader->zone(),
-                           reader->NewStackmap(length));
+  intptr_t offset = reader->Read<int32_t>();
+  Stackmap& result = Stackmap::ZoneHandle(reader->zone());
+  result ^= reader->GetObjectAt(offset);
   reader->AddBackRef(object_id, &result, kIsDeserialized);
 
-  result.SetRegisterBitCount(reader->Read<int32_t>());
-  result.SetPcOffset(reader->Read<uint32_t>());
-
-  if (length > 0) {
-    NoSafepointScope no_safepoint;
-    intptr_t len = (result.Length() + 7) / 8;
-    uint8_t* data = result.UnsafeMutableNonPointer(result.raw_ptr()->data());
-    reader->ReadBytes(data, len);
-  }
-
   return result.raw();
 }
 
@@ -1765,14 +1748,7 @@
   writer->WriteIndexedObject(kStackmapCid);
   writer->WriteTags(writer->GetObjectTags(this));
 
-  writer->Write<int32_t>(ptr()->length_);
-  writer->Write<int32_t>(ptr()->register_bit_count_);
-  writer->Write<uint32_t>(ptr()->pc_offset_);
-  if (ptr()->length_ > 0) {
-    intptr_t len = (ptr()->length_ + 7) / 8;
-    uint8_t* data = reinterpret_cast<uint8_t*>(ptr()->data());
-    writer->WriteBytes(data, len);
-  }
+  writer->Write<int32_t>(writer->GetObjectId(this));
 }
 
 
@@ -2021,8 +1997,11 @@
   result.set_state_bits(reader->Read<uint32_t>());
 
   // Set all the object fields.
+  RawObject** toobj = reader->snapshot_code()
+      ? result.raw()->to_precompiled_snapshot()
+      : result.raw()->to();
   READ_OBJECT_FIELDS(result,
-                     result.raw()->from(), result.raw()->to(),
+                     result.raw()->from(), toobj,
                      kAsReference);
 
   return result.raw();
@@ -2047,8 +2026,12 @@
   writer->Write<uint32_t>(ptr()->state_bits_);
 
   // Write out all the object pointer fields.
+  // In precompiled snapshots, omit the owner field. The owner field may
+  // refer to a function which was always inlined and no longer needed.
   SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitPointers(from(), to());
+  RawObject** toobj = writer->snapshot_code() ? to_precompiled_snapshot()
+                                              : to();
+  visitor.VisitPointers(from(), toobj);
 }
 
 
@@ -2572,6 +2555,14 @@
                                           intptr_t tags,
                                           Snapshot::Kind kind,
                                           bool as_reference) {
+  if (reader->snapshot_code()) {
+    ASSERT(kind == Snapshot::kFull);
+    intptr_t offset = reader->Read<int32_t>();
+    String& result = String::ZoneHandle(reader->zone());
+    result ^= reader->GetObjectAt(offset);
+    reader->AddBackRef(object_id, &result, kIsDeserialized);
+    return raw(result);
+  }
   // Read the length so that we can determine instance size to allocate.
   ASSERT(reader != NULL);
   intptr_t len = reader->ReadSmiValue();
@@ -2679,6 +2670,22 @@
                                intptr_t object_id,
                                Snapshot::Kind kind,
                                bool as_reference) {
+  if (writer->snapshot_code()) {
+    ASSERT(writer->snapshot_code());
+    ASSERT(kind == Snapshot::kFull);
+    // Assert that hash is computed.
+    if (ptr()->hash_ == NULL) {
+      ptr()->hash_ = Smi::New(String::Hash(ptr()->data(),
+                                           Smi::Value(ptr()->length_)));
+    }
+    ASSERT(ptr()->hash_ != NULL);
+    // Write out the serialization header value for this object.
+    writer->WriteInlinedObjectHeader(object_id);
+    writer->WriteIndexedObject(kOneByteStringCid);
+    writer->WriteTags(writer->GetObjectTags(this));
+    writer->Write<int32_t>(writer->GetObjectId(this));
+    return;
+  }
   StringWriteTo(writer,
                 object_id,
                 kind,
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index 6ac5782..7cf9710 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -5272,9 +5272,9 @@
   // TODO(zerny): Share these arrays between all irregexp functions.
   fn.set_num_fixed_parameters(kParamCount);
   fn.set_parameter_types(Array::Handle(zone, Array::New(kParamCount,
-                                                           Heap::kOld)));
+                                                        Heap::kOld)));
   fn.set_parameter_names(Array::Handle(zone, Array::New(kParamCount,
-                                                           Heap::kOld)));
+                                                        Heap::kOld)));
   fn.SetParameterTypeAt(RegExpMacroAssembler::kParamRegExpIndex,
                         Object::dynamic_type());
   fn.SetParameterNameAt(RegExpMacroAssembler::kParamRegExpIndex,
diff --git a/runtime/vm/report.cc b/runtime/vm/report.cc
index 42a47d9..21bbdc8 100644
--- a/runtime/vm/report.cc
+++ b/runtime/vm/report.cc
@@ -14,15 +14,9 @@
 
 namespace dart {
 
-DEFINE_FLAG(int, stacktrace_depth_on_warning, 5,
-            "Maximal number of stack frames to print after a runtime warning.");
 DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings.");
-DEFINE_FLAG(bool, warn_on_javascript_compatibility, false,
-            "Warn on incompatibilities between vm and dart2js.");
 DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors.");
 
-DECLARE_FLAG(bool, always_megamorphic_calls);
-
 RawString* Report::PrependSnippet(Kind kind,
                                   const Script& script,
                                   TokenPosition token_pos,
@@ -31,7 +25,6 @@
   const char* message_header;
   switch (kind) {
     case kWarning: message_header = "warning"; break;
-    case kJSWarning: message_header = "javascript compatibility warning"; break;
     case kError: message_header = "error"; break;
     case kMalformedType: message_header = "malformed type"; break;
     case kMalboundedType: message_header = "malbounded type"; break;
@@ -159,17 +152,6 @@
       const String& snippet_msg = String::Handle(
           PrependSnippet(kind, script, token_pos, report_after_token, msg));
       OS::Print("%s", snippet_msg.ToCString());
-      if (kind == kJSWarning) {
-        TraceJSWarning(script, token_pos, msg);
-        // Do not print stacktrace if we have not executed Dart code yet.
-        if (Thread::Current()->top_exit_frame_info() != 0) {
-          const Stacktrace& stacktrace =
-              Stacktrace::Handle(Exceptions::CurrentStacktrace());
-          intptr_t idx = 0;
-          OS::Print("%s", stacktrace.ToCStringInternal(
-              &idx, FLAG_stacktrace_depth_on_warning));
-        }
-      }
       return;
     }
   }
@@ -179,96 +161,9 @@
                                    script, token_pos, report_after_token,
                                    kind, Heap::kNew,
                                    format, args));
-  if (kind == kJSWarning) {
-    Exceptions::ThrowJavascriptCompatibilityError(error.ToErrorCString());
-    UNREACHABLE();
-  }
   LongJump(error);
   UNREACHABLE();
 }
 
-
-void Report::JSWarningFromNative(bool is_static_native, const char* msg) {
-  DartFrameIterator iterator;
-  iterator.NextFrame();  // Skip native call.
-  StackFrame* caller_frame = iterator.NextFrame();
-  ASSERT(caller_frame != NULL);
-  const Code& caller_code = Code::Handle(caller_frame->LookupDartCode());
-  ASSERT(!caller_code.IsNull());
-  const uword caller_pc = caller_frame->pc();
-  ICData& ic_data = ICData::Handle();
-  if (is_static_native) {
-    // Assume an unoptimized static call. Optimization was prevented.
-    CodePatcher::GetUnoptimizedStaticCallAt(caller_pc, caller_code, &ic_data);
-  } else {
-    if (FLAG_always_megamorphic_calls) {
-      Report::JSWarningFromFrame(caller_frame, msg);
-      return;
-    } else {
-      // Assume an instance call.
-      CodePatcher::GetInstanceCallAt(caller_pc, caller_code, &ic_data);
-    }
-  }
-  ASSERT(!ic_data.IsNull());
-  // Report warning only if not already reported at this location.
-  if (!ic_data.IssuedJSWarning()) {
-    ic_data.SetIssuedJSWarning();
-    Report::JSWarningFromFrame(caller_frame, msg);
-  }
-}
-
-
-void Report::JSWarningFromIC(const ICData& ic_data, const char* msg) {
-  DartFrameIterator iterator;
-  StackFrame* caller_frame = iterator.NextFrame();
-  ASSERT(caller_frame != NULL);
-  // Report warning only if not already reported at this location.
-  if (!ic_data.IssuedJSWarning()) {
-    ic_data.SetIssuedJSWarning();
-    JSWarningFromFrame(caller_frame, msg);
-  }
-}
-
-
-void Report::JSWarningFromFrame(StackFrame* caller_frame, const char* msg) {
-  ASSERT(caller_frame != NULL);
-  ASSERT(FLAG_warn_on_javascript_compatibility);
-  if (FLAG_silent_warnings) return;
-  Zone* zone = Thread::Current()->zone();
-  const Code& caller_code = Code::Handle(zone,
-                                         caller_frame->LookupDartCode());
-  ASSERT(!caller_code.IsNull());
-  const uword caller_pc = caller_frame->pc();
-  const TokenPosition token_pos = caller_code.GetTokenIndexOfPC(caller_pc);
-  const Function& caller = Function::Handle(zone, caller_code.function());
-  const Script& script = Script::Handle(zone, caller.script());
-  MessageF(kJSWarning, script, token_pos, Report::AtLocation, "%s", msg);
-}
-
-
-void Report::TraceJSWarning(const Script& script,
-                            TokenPosition token_pos,
-                            const String& message) {
-  if (!FLAG_support_service) {
-    return;
-  }
-  const int64_t micros = OS::GetCurrentTimeMicros();
-  Isolate* isolate = Isolate::Current();
-  TraceBuffer* trace_buffer = isolate->trace_buffer();
-  if (trace_buffer == NULL) {
-    TraceBuffer::Init(isolate);
-    trace_buffer = isolate->trace_buffer();
-  }
-  JSONStream js;
-  {
-    JSONObject trace_warning(&js);
-    trace_warning.AddProperty("type", "JSCompatibilityWarning");
-    trace_warning.AddProperty("script", script);
-    trace_warning.AddProperty("tokenPos", token_pos);
-    trace_warning.AddProperty("message", message);
-  }
-  trace_buffer->Trace(micros, js.ToCString(), true);  // Already escaped.
-}
-
 }  // namespace dart
 
diff --git a/runtime/vm/report.h b/runtime/vm/report.h
index 3cf48ac..f95cb84 100644
--- a/runtime/vm/report.h
+++ b/runtime/vm/report.h
@@ -22,7 +22,6 @@
  public:
   enum Kind {
     kWarning,
-    kJSWarning,
     kError,
     kMalformedType,
     kMalboundedType,
@@ -55,23 +54,6 @@
                        bool report_after_token,
                        const char* format, va_list args);
 
-  // Support to report Javascript compatibility warnings. Note that a
-  // JavascriptCompatibilityError is thrown if --warning_as_error is specified.
-  // If a warning is issued by the various JSWarning calls, the warning is also
-  // emitted in the trace buffer of the current isolate.
-
-  // Report a Javascript compatibility warning at the call site given by
-  // ic_data, unless one has already been emitted at that location.
-  static void JSWarningFromIC(const ICData& ic_data, const char* msg);
-
-  // Report a Javascript compatibility warning at the current native call,
-  // unless one has already been emitted at that location.
-  static void JSWarningFromNative(bool is_static_native, const char* msg);
-
-  // Report a Javascript compatibility warning at the call site given by
-  // caller_frame.
-  static void JSWarningFromFrame(StackFrame* caller_frame, const char* msg);
-
   // Prepend a source snippet to the message.
   // A null script means no source and a negative token_pos means no position.
   static RawString* PrependSnippet(Kind kind,
@@ -81,11 +63,6 @@
                                    const String& message);
 
  private:
-  // Emit a Javascript compatibility warning to the current trace buffer.
-  static void TraceJSWarning(const Script& script,
-                             TokenPosition token_pos,
-                             const String& message);
-
   DISALLOW_COPY_AND_ASSIGN(Report);
 };
 
diff --git a/runtime/vm/report_test.cc b/runtime/vm/report_test.cc
deleted file mode 100644
index d939dd2..0000000
--- a/runtime/vm/report_test.cc
+++ /dev/null
@@ -1,84 +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.
-
-#include "platform/assert.h"
-#include "vm/report.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-
-#ifndef PRODUCT
-
-TEST_CASE(TraceJSWarning) {
-  Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-  TraceBuffer::Init(isolate, 3);
-  TraceBuffer* trace_buffer = isolate->trace_buffer();
-  const String& url = String::Handle(zone, String::New("Plug"));
-  const String& source = String::Handle(zone, String::New("240 100"));
-  const Script& script = Script::Handle(zone,
-      Script::New(url, source, RawScript::kEvaluateTag));
-  script.Tokenize(String::Handle(String::New("")));
-  {
-    const TokenPosition token_pos = TokenPosition(0);
-    const char* message = "High Voltage";
-    Report::MessageF(Report::kJSWarning,
-                     script, token_pos, Report::AtLocation, "%s", message);
-    {
-      JSONStream js;
-      trace_buffer->PrintToJSONStream(&js);
-      EXPECT_SUBSTRING("{\"type\":\"TraceBuffer\",\"members\":["
-                       "{\"type\":\"TraceBufferEntry\",\"time\":",
-                       js.ToCString());
-      // Skip time.
-      EXPECT_SUBSTRING("\"message\":{\"type\":\"JSCompatibilityWarning\","
-                       "\"script\":{\"type\":\"@Script\"",
-                       js.ToCString());
-      // Skip object ring id.
-      EXPECT_SUBSTRING("\"uri\":\"Plug\","
-                       "\"_kind\":\"evaluate\"},\"tokenPos\":0,"
-                       "\"message\":{\"type\":\"@Instance\"",
-                       js.ToCString());
-      // Skip private _OneByteString.
-      EXPECT_SUBSTRING("\"valueAsString\":\"High Voltage\"",
-                       js.ToCString());
-    }
-  }
-  {
-    const TokenPosition token_pos = TokenPosition(1);
-    const char* message = "Low Voltage";
-    Report::MessageF(Report::kJSWarning,
-                     script, token_pos, Report::AtLocation, "%s", message);
-  }
-  EXPECT_EQ(2, trace_buffer->Length());
-  EXPECT_SUBSTRING("{\"type\":\"JSCompatibilityWarning\",\"script\":{\"type\":"
-                   "\"@Script\"",
-                   trace_buffer->At(0)->message);
-  // Skip object ring id.
-  EXPECT_SUBSTRING("\"uri\":\"Plug\","
-                   "\"_kind\":\"evaluate\"},\"tokenPos\":0,"
-                   "\"message\":{\"type\":\"@Instance\"",
-                   trace_buffer->At(0)->message);
-  // Skip private _OneByteString.
-  EXPECT_SUBSTRING("\"valueAsString\":\"High Voltage\"",
-                   trace_buffer->At(0)->message);
-
-  EXPECT_SUBSTRING("{\"type\":\"JSCompatibilityWarning\",\"script\":{\"type\":"
-                   "\"@Script\"",
-                   trace_buffer->At(1)->message);
-  // Skip object ring id.
-  EXPECT_SUBSTRING("\"uri\":\"Plug\","
-                   "\"_kind\":\"evaluate\"},\"tokenPos\":1,"
-                   "\"message\":{\"type\":\"@Instance\"",
-                   trace_buffer->At(1)->message);
-  // Skip private _OneByteString.
-  EXPECT_SUBSTRING("\"valueAsString\":\"Low Voltage\"",
-                   trace_buffer->At(1)->message);
-
-  delete trace_buffer;
-}
-
-#endif  // !PRODUCT
-
-}  // namespace dart
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index cdfdd288..c8912eb 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -647,7 +647,6 @@
   // Returns number of elements in the list.  -1 on parse error.
   intptr_t ElementCount(const char* value) const {
     const char* kJsonWhitespaceChars = " \t\r\n";
-
     if (value == NULL) {
       return -1;
     }
@@ -2408,13 +2407,9 @@
 };
 
 
-static const EnumListParameter* reports_parameter =
-    new EnumListParameter("reports", true, report_enum_names);
-
-
 static const MethodParameter* get_source_report_params[] = {
   RUNNABLE_ISOLATE_PARAMETER,
-  reports_parameter,
+  new EnumListParameter("reports", true, report_enum_names),
   new IdParameter("scriptId", false),
   new UIntParameter("tokenPos", false),
   new UIntParameter("endTokenPos", false),
@@ -2425,6 +2420,8 @@
 
 static bool GetSourceReport(Thread* thread, JSONStream* js) {
   const char* reports_str = js->LookupParam("reports");
+  const EnumListParameter* reports_parameter =
+      static_cast<const EnumListParameter*>(get_source_report_params[1]);
   const char** reports = reports_parameter->Parse(thread->zone(), reports_str);
   intptr_t report_set = 0;
   while (*reports != NULL) {
@@ -2860,27 +2857,58 @@
   return false;
 }
 
+static const char* const timeline_streams_enum_names[] = {
+  "all",
+#define DEFINE_NAME(name, unused)                                              \
+  #name,
+ISOLATE_TIMELINE_STREAM_LIST(DEFINE_NAME)
+#undef DEFINE_NAME
+  "VM",
+  NULL
+};
 
-static const MethodParameter* set_vm_timeline_flag_params[] = {
+static const MethodParameter* set_vm_timeline_flags_params[] = {
   NO_ISOLATE_PARAMETER,
-  new MethodParameter("_record", true),
+  new EnumListParameter("recordedStreams",
+                        false,
+                        timeline_streams_enum_names),
   NULL,
 };
 
 
-static bool SetVMTimelineFlag(Thread* thread, JSONStream* js) {
+static bool HasStream(const char** recorded_streams, const char* stream) {
+  while (*recorded_streams != NULL) {
+    if ((strstr(*recorded_streams, "all") != NULL) ||
+        (strstr(*recorded_streams, stream) != NULL)) {
+      return true;
+    }
+    recorded_streams++;
+  }
+  return false;
+}
+
+
+static bool SetVMTimelineFlags(Thread* thread, JSONStream* js) {
+  if (!FLAG_support_timeline) {
+    PrintSuccess(js);
+    return true;
+  }
   Isolate* isolate = thread->isolate();
   ASSERT(isolate != NULL);
   StackZone zone(thread);
 
-  bool recording = strcmp(js->LookupParam("_record"), "all") == 0;
-  Timeline::SetStreamAPIEnabled(recording);
-  Timeline::SetStreamCompilerEnabled(recording);
-  Timeline::SetStreamDartEnabled(recording);
-  Timeline::SetStreamDebuggerEnabled(recording);
-  Timeline::SetStreamEmbedderEnabled(recording);
-  Timeline::SetStreamGCEnabled(recording);
-  Timeline::SetStreamIsolateEnabled(recording);
+  const EnumListParameter* recorded_streams_param =
+      static_cast<const EnumListParameter*>(set_vm_timeline_flags_params[1]);
+
+  const char* recorded_streams_str = js->LookupParam("recordedStreams");
+  const char** recorded_streams =
+      recorded_streams_param->Parse(thread->zone(), recorded_streams_str);
+
+#define SET_ENABLE_STREAM(name, unused)                                        \
+  Timeline::SetStream##name##Enabled(HasStream(recorded_streams, #name));
+ISOLATE_TIMELINE_STREAM_LIST(SET_ENABLE_STREAM);
+#undef SET_ENABLE_STREAM
+  Timeline::SetVMStreamEnabled(HasStream(recorded_streams, "VM"));
 
   PrintSuccess(js);
 
@@ -2888,19 +2916,22 @@
 }
 
 
-static const MethodParameter* get_vm_timeline_flag_params[] = {
+static const MethodParameter* get_vm_timeline_flags_params[] = {
   NO_ISOLATE_PARAMETER,
-  new MethodParameter("_record", false),
   NULL,
 };
 
 
-static bool GetVMTimelineFlag(Thread* thread, JSONStream* js) {
+static bool GetVMTimelineFlags(Thread* thread, JSONStream* js) {
+  if (!FLAG_support_timeline) {
+    JSONObject obj(js);
+    obj.AddProperty("type", "TimelineFlags");
+    return true;
+  }
   Isolate* isolate = thread->isolate();
   ASSERT(isolate != NULL);
   StackZone zone(thread);
-
-  js->PrintError(kFeatureDisabled, "TODO(johnmccutchan)");
+  Timeline::PrintFlagsToJSON(js);
   return true;
 }
 
@@ -3918,8 +3949,8 @@
     get_vm_metric_list_params },
   { "_getVMTimeline", GetVMTimeline,
     get_vm_timeline_params },
-  { "_getVMTimelineFlag", GetVMTimelineFlag,
-    get_vm_timeline_flag_params },
+  { "_getVMTimelineFlags", GetVMTimelineFlags,
+    get_vm_timeline_flags_params },
   { "pause", Pause,
     pause_params },
   { "removeBreakpoint", RemoveBreakpoint,
@@ -3942,8 +3973,8 @@
     set_trace_class_allocation_params },
   { "setVMName", SetVMName,
     set_vm_name_params },
-  { "_setVMTimelineFlag", SetVMTimelineFlag,
-    set_vm_timeline_flag_params },
+  { "_setVMTimelineFlags", SetVMTimelineFlags,
+    set_vm_timeline_flags_params },
 };
 
 
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 2103acd..0ab4ee2 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -2294,7 +2294,7 @@
   // sorted list of token positions.  Provided only when the when the
   // PossibleBreakpoint report has been requested and the range has been
   // compiled.
-  int possibleBreakpoints[] [optional];
+  int[] possibleBreakpoints [optional];
 }
 ```
 
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index d80364e..3d6207a 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -30,6 +30,8 @@
 DEFINE_FLAG(bool, trace_service, false, "Trace VM service requests.");
 DEFINE_FLAG(bool, trace_service_pause_events, false,
             "Trace VM service isolate pause events.");
+DEFINE_FLAG(bool, trace_service_verbose, false,
+            "Provide extra service tracing information.");
 
 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) {
   void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size);
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 76292c0..bbfa73b 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -407,7 +407,11 @@
       if (Simulator::IsIllegalAddress(last_pc)) {
         OS::Print("pc is out of bounds: 0x%" Px "\n", last_pc);
       } else {
-        Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
+        if (FLAG_support_disassembler) {
+          Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
+        } else {
+          OS::Print("Disassembler not supported in this mode.\n");
+        }
       }
     }
     char* line = ReadLine("sim> ");
@@ -546,7 +550,11 @@
           }
         }
         if ((start > 0) && (end > start)) {
-          Disassembler::Disassemble(start, end);
+          if (FLAG_support_disassembler) {
+            Disassembler::Disassemble(start, end);
+          } else {
+            OS::Print("Disassembler not supported in this mode.\n");
+          }
         } else {
           OS::Print("disasm [<address> [<number_of_instructions>]]\n");
         }
@@ -3603,7 +3611,11 @@
     OS::Print("%" Pu64 " ", icount_);
     const uword start = reinterpret_cast<uword>(instr);
     const uword end = start + Instr::kInstrSize;
-    Disassembler::Disassemble(start, end);
+    if (FLAG_support_disassembler) {
+      Disassembler::Disassemble(start, end);
+    } else {
+      OS::Print("Disassembler not supported in this mode.\n");
+    }
   }
   if (instr->ConditionField() == kSpecialCondition) {
     if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) {
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 8ab8455..7916d18 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -425,7 +425,11 @@
       if (Simulator::IsIllegalAddress(last_pc)) {
         OS::Print("pc is out of bounds: 0x%" Px "\n", last_pc);
       } else {
-        Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
+        if (FLAG_support_disassembler) {
+          Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
+        } else {
+          OS::Print("Disassembler not supported in this mode.\n");
+        }
       }
     }
     char* line = ReadLine("sim> ");
@@ -597,7 +601,11 @@
           }
         }
         if ((start > 0) && (end > start)) {
-          Disassembler::Disassemble(start, end);
+          if (FLAG_support_disassembler) {
+            Disassembler::Disassemble(start, end);
+          } else {
+            OS::Print("Disassembler not supported in this mode.\n");
+          }
         } else {
           OS::Print("disasm [<address> [<number_of_instructions>]]\n");
         }
@@ -3364,7 +3372,11 @@
     OS::Print("%" Pu64 " ", icount_);
     const uword start = reinterpret_cast<uword>(instr);
     const uword end = start + Instr::kInstrSize;
-    Disassembler::Disassemble(start, end);
+    if (FLAG_support_disassembler) {
+      Disassembler::Disassemble(start, end);
+    } else {
+      OS::Print("Disassembler not supported in this mode.\n");
+    }
   }
 
   if (instr->IsDPImmediateOp()) {
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index 5491c6b..2b03da8 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -418,7 +418,11 @@
       if (Simulator::IsIllegalAddress(last_pc)) {
         OS::Print("pc is out of bounds: 0x%" Px "\n", last_pc);
       } else {
-        Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
+        if (FLAG_support_disassembler) {
+          Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
+        } else {
+          OS::Print("Disassembler not supported in this mode.\n");
+        }
       }
     }
     char* line = ReadLine("sim> ");
@@ -556,7 +560,11 @@
           }
         }
         if ((start > 0) && (end > start)) {
-          Disassembler::Disassemble(start, end);
+          if (FLAG_support_disassembler) {
+            Disassembler::Disassemble(start, end);
+          } else {
+            OS::Print("Disassembler not supported in this mode.\n");
+          }
         } else {
           OS::Print("disasm [<address> [<number_of_instructions>]]\n");
         }
@@ -1996,7 +2004,11 @@
     OS::Print("%" Pu64 " ", icount_);
     const uword start = reinterpret_cast<uword>(instr);
     const uword end = start + Instr::kInstrSize;
-    Disassembler::Disassemble(start, end);
+    if (FLAG_support_disassembler) {
+      Disassembler::Disassemble(start, end);
+    } else {
+      OS::Print("Disassembler not supported in this mode.\n");
+    }
   }
 
   switch (instr->OpcodeField()) {
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index bbeef36..340351a 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -177,11 +177,13 @@
     const uint8_t* buffer,
     intptr_t size,
     const uint8_t* instructions_buffer,
+    const uint8_t* data_buffer,
     Snapshot::Kind kind,
     ZoneGrowableArray<BackRefNode>* backward_refs,
     Thread* thread)
     : BaseReader(buffer, size),
       instructions_buffer_(instructions_buffer),
+      data_buffer_(data_buffer),
       kind_(kind),
       snapshot_code_(instructions_buffer != NULL),
       thread_(thread),
@@ -211,7 +213,8 @@
       backward_references_(backward_refs),
       instructions_reader_(NULL) {
   if (instructions_buffer != NULL) {
-    instructions_reader_ = new InstructionsReader(instructions_buffer);
+    instructions_reader_ =
+        new InstructionsReader(instructions_buffer, data_buffer);
   }
 }
 
@@ -1133,6 +1136,15 @@
 }
 
 
+int32_t InstructionsWriter::GetObjectOffsetFor(RawObject* raw_object) {
+  intptr_t heap_size = raw_object->Size();
+  intptr_t offset = next_object_offset_;
+  next_object_offset_ += heap_size;
+  objects_.Add(ObjectData(raw_object));
+  return offset;
+}
+
+
 static void EnsureIdentifier(char* label) {
   for (char c = *label; c != '\0'; c = *++label) {
     if (((c >= 'a') && (c <= 'z')) ||
@@ -1156,10 +1168,16 @@
     ASSERT(data.raw_code_ != NULL);
     data.code_ = &Code::Handle(Z, data.raw_code_);
   }
+  for (intptr_t i = 0; i < objects_.length(); i++) {
+    ObjectData& data = objects_[i];
+    data.obj_ = &Object::Handle(Z, data.raw_obj_);
+  }
 
   stream_.Print(".text\n");
   stream_.Print(".globl _kInstructionsSnapshot\n");
-  stream_.Print(".balign %" Pd ", 0\n", OS::kMaxPreferredCodeAlignment);
+  // Start snapshot at page boundary.
+  ASSERT(VirtualMemory::PageSize() >= OS::kMaxPreferredCodeAlignment);
+  stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize());
   stream_.Print("_kInstructionsSnapshot:\n");
 
   // This head also provides the gap to make the instructions snapshot
@@ -1241,6 +1259,42 @@
       }
     }
   }
+#if defined(TARGET_OS_LINUX)
+  stream_.Print(".section .rodata\n");
+#elif defined(TARGET_OS_MACOS)
+  stream_.Print(".const\n");
+#else
+  // Unsupported platform.
+  UNREACHABLE();
+#endif
+  stream_.Print(".globl _kDataSnapshot\n");
+  // Start snapshot at page boundary.
+  stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize());
+  stream_.Print("_kDataSnapshot:\n");
+  WriteWordLiteral(next_object_offset_);  // Data length.
+  COMPILE_ASSERT(OS::kMaxPreferredCodeAlignment >= kObjectAlignment);
+  stream_.Print(".balign %" Pd ", 0\n", OS::kMaxPreferredCodeAlignment);
+
+  for (intptr_t i = 0; i < objects_.length(); i++) {
+    const Object& obj = *objects_[i].obj_;
+    stream_.Print("Precompiled_Obj_%d:\n", i);
+
+    NoSafepointScope no_safepoint;
+    uword start = reinterpret_cast<uword>(obj.raw()) - kHeapObjectTag;
+    uword end = start + obj.raw()->Size();
+
+    // Write object header with the mark and VM heap bits set.
+    uword marked_tags = obj.raw()->ptr()->tags_;
+    marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags);
+    marked_tags = RawObject::MarkBit::update(true, marked_tags);
+    WriteWordLiteral(marked_tags);
+    start += sizeof(uword);
+    for (uword* cursor = reinterpret_cast<uword*>(start);
+         cursor < reinterpret_cast<uword*>(end);
+         cursor++) {
+      WriteWordLiteral(*cursor);
+    }
+  }
 }
 
 
@@ -1250,14 +1304,17 @@
 
   RawInstructions* result =
       reinterpret_cast<RawInstructions*>(
-          reinterpret_cast<uword>(buffer_) + offset + kHeapObjectTag);
+          reinterpret_cast<uword>(instructions_buffer_) +
+          offset + kHeapObjectTag);
 
+#ifdef DEBUG
   uword actual_tags = result->ptr()->tags_;
   if (actual_tags != expected_tags) {
     FATAL2("Instructions tag mismatch: expected %" Pd ", saw %" Pd,
            expected_tags,
            actual_tags);
   }
+#endif
 
   ASSERT(result->IsMarked());
 
@@ -1265,6 +1322,18 @@
 }
 
 
+RawObject* InstructionsReader::GetObjectAt(int32_t offset) {
+  ASSERT(Utils::IsAligned(offset, kWordSize));
+
+  RawObject* result =
+      reinterpret_cast<RawObject*>(
+          reinterpret_cast<uword>(data_buffer_) + offset + kHeapObjectTag);
+  ASSERT(result->IsMarked());
+
+  return result;
+}
+
+
 intptr_t SnapshotReader::LookupInternalClass(intptr_t class_header) {
   // If the header is an object Id, lookup singleton VM classes or classes
   // stored in the object store.
@@ -1489,10 +1558,12 @@
     const uint8_t* buffer,
     intptr_t size,
     const uint8_t* instructions_buffer,
+    const uint8_t* data_buffer,
     Thread* thread)
       : SnapshotReader(buffer,
                        size,
                        instructions_buffer,
+                       data_buffer,
                        Snapshot::kFull,
                        new ZoneGrowableArray<BackRefNode>(
                            kNumVmIsolateSnapshotReferences),
@@ -1510,6 +1581,7 @@
   }
   ResetBackwardReferenceTable();
   Dart::set_instructions_snapshot_buffer(instructions_buffer_);
+  Dart::set_data_snapshot_buffer(data_buffer_);
 }
 
 
@@ -1561,10 +1633,12 @@
 IsolateSnapshotReader::IsolateSnapshotReader(const uint8_t* buffer,
                                              intptr_t size,
                                              const uint8_t* instructions_buffer,
+                                             const uint8_t* data_buffer,
                                              Thread* thread)
     : SnapshotReader(buffer,
                      size,
                      instructions_buffer,
+                     data_buffer,
                      Snapshot::kFull,
                      new ZoneGrowableArray<BackRefNode>(
                          kNumInitialReferencesInFullSnapshot),
@@ -1584,6 +1658,7 @@
     : SnapshotReader(buffer,
                      size,
                      NULL, /* instructions_buffer */
+                     NULL, /* data_buffer */
                      Snapshot::kScript,
                      new ZoneGrowableArray<BackRefNode>(kNumInitialReferences),
                      thread) {
@@ -1601,6 +1676,7 @@
     : SnapshotReader(buffer,
                      size,
                      NULL, /* instructions_buffer */
+                     NULL, /* data_buffer */
                      Snapshot::kMessage,
                      new ZoneGrowableArray<BackRefNode>(kNumInitialReferences),
                      thread) {
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index b1071d6..978dbd1 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -224,6 +224,34 @@
 };
 
 
+class DataSnapshot : ValueObject {
+ public:
+  explicit DataSnapshot(const void* raw_memory)
+    : raw_memory_(raw_memory) {
+    ASSERT(Utils::IsAligned(raw_memory, 2 * kWordSize));  // kObjectAlignment
+  }
+
+  void* data_start() {
+    return reinterpret_cast<void*>(
+        reinterpret_cast<uword>(raw_memory_) + kHeaderSize);
+  }
+
+  uword data_size() {
+    uword snapshot_size = *reinterpret_cast<const uword*>(raw_memory_);
+    return snapshot_size - kHeaderSize;
+  }
+
+  // Header: data length and padding for alignment. We use the same alignment
+  // as for code for now.
+  static const intptr_t kHeaderSize = OS::kMaxPreferredCodeAlignment;
+
+ private:
+  const void* raw_memory_;  // The symbol kDataSnapshot.
+
+  DISALLOW_COPY_AND_ASSIGN(DataSnapshot);
+};
+
+
 class BaseReader {
  public:
   BaseReader(const uint8_t* buffer, intptr_t size) : stream_(buffer, size) {}
@@ -333,17 +361,22 @@
 
 class InstructionsReader : public ZoneAllocated {
  public:
-  explicit InstructionsReader(const uint8_t* buffer)
-    : buffer_(buffer) {
-    ASSERT(buffer != NULL);
-    ASSERT(Utils::IsAligned(reinterpret_cast<uword>(buffer),
+  InstructionsReader(const uint8_t* instructions_buffer,
+                     const uint8_t* data_buffer)
+    : instructions_buffer_(instructions_buffer),
+      data_buffer_(data_buffer) {
+    ASSERT(instructions_buffer != NULL);
+    ASSERT(data_buffer != NULL);
+    ASSERT(Utils::IsAligned(reinterpret_cast<uword>(instructions_buffer),
                             OS::PreferredCodeAlignment()));
   }
 
   RawInstructions* GetInstructionsAt(int32_t offset, uword expected_tags);
+  RawObject* GetObjectAt(int32_t offset);
 
  private:
-  const uint8_t* buffer_;
+  const uint8_t* instructions_buffer_;
+  const uint8_t* data_buffer_;
 
   DISALLOW_COPY_AND_ASSIGN(InstructionsReader);
 };
@@ -456,12 +489,18 @@
     return instructions_reader_->GetInstructionsAt(offset, expected_tags);
   }
 
+  RawObject* GetObjectAt(int32_t offset) {
+    return instructions_reader_->GetObjectAt(offset);
+  }
+
   const uint8_t* instructions_buffer_;
+  const uint8_t* data_buffer_;
 
  protected:
   SnapshotReader(const uint8_t* buffer,
                  intptr_t size,
                  const uint8_t* instructions_buffer,
+                 const uint8_t* data_buffer,
                  Snapshot::Kind kind,
                  ZoneGrowableArray<BackRefNode>* backward_references,
                  Thread* thread);
@@ -608,6 +647,7 @@
   VmIsolateSnapshotReader(const uint8_t* buffer,
                           intptr_t size,
                           const uint8_t* instructions_buffer,
+                          const uint8_t* data_buffer,
                           Thread* thread);
   ~VmIsolateSnapshotReader();
 
@@ -623,6 +663,7 @@
   IsolateSnapshotReader(const uint8_t* buffer,
                         intptr_t size,
                         const uint8_t* instructions_buffer,
+                        const uint8_t* data_buffer,
                         Thread* thread);
   ~IsolateSnapshotReader();
 
@@ -811,8 +852,10 @@
                      intptr_t initial_size)
     : stream_(buffer, alloc, initial_size),
       next_offset_(InstructionsSnapshot::kHeaderSize),
+      next_object_offset_(DataSnapshot::kHeaderSize),
       binary_size_(0),
-      instructions_() {
+      instructions_(),
+      objects_() {
     ASSERT(buffer != NULL);
     ASSERT(alloc != NULL);
   }
@@ -824,6 +867,8 @@
 
   int32_t GetOffsetFor(RawInstructions* instructions);
 
+  int32_t GetObjectOffsetFor(RawObject* raw_object);
+
   void SetInstructionsCode(RawInstructions* insns, RawCode* code) {
     for (intptr_t i = 0; i < instructions_.length(); i++) {
       if (instructions_[i].raw_insns_ == insns) {
@@ -851,6 +896,16 @@
     };
   };
 
+  struct ObjectData {
+    explicit ObjectData(RawObject* raw_obj)
+        : raw_obj_(raw_obj) { }
+
+    union {
+      RawObject* raw_obj_;
+      const Object* obj_;
+    };
+  };
+
   void WriteWordLiteral(uword value) {
     // Padding is helpful for comparing the .S with --disassemble.
 #if defined(ARCH_IS_64_BIT)
@@ -863,8 +918,10 @@
 
   WriteStream stream_;
   intptr_t next_offset_;
+  intptr_t next_object_offset_;
   intptr_t binary_size_;
   GrowableArray<InstructionsData> instructions_;
+  GrowableArray<ObjectData> objects_;
 
   DISALLOW_COPY_AND_ASSIGN(InstructionsWriter);
 };
@@ -920,6 +977,10 @@
     return instructions_writer_->GetOffsetFor(instructions);
   }
 
+  int32_t GetObjectId(RawObject* raw) {
+    return instructions_writer_->GetObjectOffsetFor(raw);
+  }
+
   void SetInstructionsCode(RawInstructions* instructions, RawCode* code) {
     return instructions_writer_->SetInstructionsCode(instructions, code);
   }
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 210e43f..35d3728 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -1537,6 +1537,7 @@
     EXPECT(script_snapshot != NULL);
     result = Dart_LoadScriptFromSnapshot(script_snapshot, size);
     EXPECT_VALID(result);
+    Dart_ExitScope();
   }
 
   FLAG_load_deferred_eagerly = saved_load_deferred_eagerly_mode;
@@ -1657,6 +1658,7 @@
     // Invoke the test_b function.
     result = Dart_Invoke(lib, NewString("test_b"), 0, NULL);
     EXPECT(Dart_IsError(result) == saved_enable_type_checks_mode);
+    Dart_ExitScope();
   }
   Dart_ShutdownIsolate();
   free(full_snapshot);
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 3b9398f..bbd35ab 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -118,7 +118,7 @@
 
   ZoneGrowableArray<const ICData*>* ic_data_array =
       new(zone()) ZoneGrowableArray<const ICData*>();
-  function.RestoreICDataMap(ic_data_array, false /* clone descriptors */);
+  function.RestoreICDataMap(ic_data_array, false /* clone ic-data */);
   const PcDescriptors& descriptors = PcDescriptors::Handle(
       zone(), code.pc_descriptors());
 
@@ -150,7 +150,7 @@
 
   ZoneGrowableArray<const ICData*>* ic_data_array =
       new(zone()) ZoneGrowableArray<const ICData*>();
-  function.RestoreICDataMap(ic_data_array, false /* clone descriptors */);
+  function.RestoreICDataMap(ic_data_array, false /* clone ic-data */);
   const PcDescriptors& descriptors = PcDescriptors::Handle(
       zone(), code.pc_descriptors());
 
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index 6cbbd7a..ec83c5d 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -26,7 +26,6 @@
     "Set to true for debugging & verifying the slow paths.");
 DECLARE_FLAG(bool, trace_optimized_ic_calls);
 DECLARE_FLAG(int, optimization_counter_threshold);
-DECLARE_FLAG(bool, support_debugger);
 DECLARE_FLAG(bool, lazy_dispatchers);
 
 // Input parameters:
@@ -1294,10 +1293,6 @@
                           Label* not_smi_or_overflow,
                           bool should_update_result_range) {
   __ Comment("Fast Smi op");
-  if (FLAG_throw_on_javascript_int_overflow) {
-    // The overflow check is more complex than implemented below.
-    return;
-  }
   __ ldr(R0, Address(SP, + 0 * kWordSize));  // Right.
   __ ldr(R1, Address(SP, + 1 * kWordSize));  // Left.
   __ orr(TMP, R0, Operand(R1));
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 3f44fc0..3931825 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -1234,10 +1234,6 @@
                           Label* not_smi_or_overflow,
                           bool should_update_result_range) {
   __ Comment("Fast Smi op");
-  if (FLAG_throw_on_javascript_int_overflow) {
-    // The overflow check is more complex than implemented below.
-    return;
-  }
   ASSERT(num_args == 2);
   __ movq(RCX, Address(RSP, + 1 * kWordSize));  // Right
   __ movq(RAX, Address(RSP, + 2 * kWordSize));  // Left.
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index e9033d1..39d6b23 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -34,6 +34,7 @@
   V(Other, "other")                                                            \
   V(Call, "call")                                                              \
   V(Current, "current")                                                        \
+  V(_current, "_current")                                                      \
   V(MoveNext, "moveNext")                                                      \
   V(IsYieldEach, "isYieldEach")                                                \
   V(Value, "value")                                                            \
@@ -307,8 +308,6 @@
   V(OutOfMemoryError, "OutOfMemoryError")                                      \
   V(NullThrownError, "NullThrownError")                                        \
   V(IsolateSpawnException, "IsolateSpawnException")                            \
-  V(JavascriptIntegerOverflowError, "_JavascriptIntegerOverflowError")         \
-  V(JavascriptCompatibilityError, "_JavascriptCompatibilityError")             \
   V(BooleanExpression, "boolean expression")                                   \
   V(Malformed, "malformed")                                                    \
   V(Malbounded, "malbounded")                                                  \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 0fa2d40..c5c6e70 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -24,6 +24,15 @@
 Thread::~Thread() {
   // We should cleanly exit any isolate before destruction.
   ASSERT(isolate_ == NULL);
+  // There should be no top api scopes at this point.
+  ASSERT(api_top_scope() == NULL);
+  // Delete the resusable api scope if there is one.
+  if (api_reusable_scope_) {
+    delete api_reusable_scope_;
+    api_reusable_scope_ = NULL;
+  }
+  delete thread_lock_;
+  thread_lock_ = NULL;
 }
 
 
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index 8fb0768..be86154 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -27,6 +27,10 @@
 DEFINE_FLAG(charp, timeline_dir, NULL,
             "Enable all timeline trace streams and output VM global trace "
             "into specified directory.");
+DEFINE_FLAG(charp, timeline_streams, NULL,
+            "Comma separated list of timeline streams to record. "
+            "Valid values: all, API, Compiler, Dart, Debugger, Embedder, "
+            "GC, Isolate, and VM.");
 
 // Implementation notes:
 //
@@ -70,6 +74,56 @@
 //       |TimelineEventRecorder::lock_|
 //
 
+
+// Returns a caller freed array of stream names in FLAG_timeline_streams.
+static MallocGrowableArray<char*>* GetEnabledByDefaultTimelineStreams() {
+  MallocGrowableArray<char*>* result = new MallocGrowableArray<char*>();
+  if (FLAG_timeline_streams == NULL) {
+    // Nothing set.
+    return result;
+  }
+  char* save_ptr;  // Needed for strtok_r.
+  // strtok modifies arg 1 so we make a copy of it.
+  char* streams = strdup(FLAG_timeline_streams);
+  char* token = strtok_r(streams, ",", &save_ptr);
+  while (token != NULL) {
+    result->Add(strdup(token));
+    token = strtok_r(NULL, ",", &save_ptr);
+  }
+  free(streams);
+  return result;
+}
+
+
+// Frees the result of |GetEnabledByDefaultTimelineStreams|.
+static void FreeEnabledByDefaultTimelineStreams(
+    MallocGrowableArray<char*>* streams) {
+  if (streams == NULL) {
+    return;
+  }
+  for (intptr_t i = 0; i < streams->length(); i++) {
+    free((*streams)[i]);
+  }
+  delete streams;
+}
+
+
+// Returns true if |streams| contains |stream| or "all". Not case sensitive.
+static bool HasStream(MallocGrowableArray<char*>* streams, const char* stream) {
+  if ((FLAG_timeline_dir != NULL) || FLAG_timing || FLAG_complete_timeline) {
+    return true;
+  }
+  for (intptr_t i = 0; i < streams->length(); i++) {
+    const char* checked_stream = (*streams)[i];
+    if ((strstr(checked_stream, "all") != NULL) ||
+        (strstr(checked_stream, stream) != NULL)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+
 void Timeline::InitOnce() {
   ASSERT(recorder_ == NULL);
   // Default to ring recorder being enabled.
@@ -82,18 +136,24 @@
   } else if (use_ring_recorder) {
     recorder_ = new TimelineEventRingRecorder();
   }
-  vm_stream_.Init("VM", EnableStreamByDefault("VM"), NULL);
+  enabled_streams_ = GetEnabledByDefaultTimelineStreams();
+  vm_stream_.Init("VM", HasStream(enabled_streams_, "VM"), NULL);
   vm_api_stream_.Init("API",
-                      EnableStreamByDefault("API"),
+                      HasStream(enabled_streams_, "API"),
                       &stream_API_enabled_);
   // Global overrides.
 #define ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT(name, not_used)                   \
-  stream_##name##_enabled_ = EnableStreamByDefault(#name);
+  stream_##name##_enabled_ = HasStream(enabled_streams_, #name);
   ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT)
 #undef ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT
 }
 
 
+void Timeline::SetVMStreamEnabled(bool enabled) {
+  vm_stream_.set_enabled(enabled);
+}
+
+
 void Timeline::Shutdown() {
   ASSERT(recorder_ != NULL);
   if (FLAG_timeline_dir != NULL) {
@@ -108,6 +168,10 @@
 #undef ISOLATE_TIMELINE_STREAM_DISABLE
   delete recorder_;
   recorder_ = NULL;
+  if (enabled_streams_ != NULL) {
+    FreeEnabledByDefaultTimelineStreams(enabled_streams_);
+    enabled_streams_ = NULL;
+  }
 }
 
 
@@ -116,9 +180,17 @@
 }
 
 
-bool Timeline::EnableStreamByDefault(const char* stream_name) {
-  // TODO(johnmccutchan): Allow for command line control over streams.
-  return (FLAG_timeline_dir != NULL) || FLAG_timing || FLAG_complete_timeline;
+void Timeline::SetupIsolateStreams(Isolate* isolate) {
+  if (!FLAG_support_timeline) {
+    return;
+  }
+#define ISOLATE_TIMELINE_STREAM_INIT(name, enabled_by_default)                 \
+  isolate->Get##name##Stream()->Init(                                          \
+      #name,                                                                   \
+      (enabled_by_default || HasStream(enabled_streams_, #name)),              \
+      Timeline::Stream##name##EnabledFlag());
+  ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_INIT);
+#undef ISOLATE_TIMELINE_STREAM_INIT
 }
 
 
@@ -154,6 +226,38 @@
 }
 
 
+void Timeline::PrintFlagsToJSON(JSONStream* js) {
+  JSONObject obj(js);
+  obj.AddProperty("type", "TimelineFlags");
+  TimelineEventRecorder* recorder = Timeline::recorder();
+  if (recorder == NULL) {
+    obj.AddProperty("recorderName", "null");
+  } else {
+    obj.AddProperty("recorderName", recorder->name());
+  }
+  {
+    JSONArray availableStreams(&obj, "availableStreams");
+#define ADD_STREAM_NAME(name, not_used)                                        \
+    availableStreams.AddValue(#name);
+ISOLATE_TIMELINE_STREAM_LIST(ADD_STREAM_NAME);
+#undef ADD_STREAM_NAME
+    availableStreams.AddValue("VM");
+  }
+  {
+    JSONArray recordedStreams(&obj, "recordedStreams");
+#define ADD_RECORDED_STREAM_NAME(name, not_used)                               \
+    if (stream_##name##_enabled_) {                                            \
+      recordedStreams.AddValue(#name);                                         \
+    }
+ISOLATE_TIMELINE_STREAM_LIST(ADD_RECORDED_STREAM_NAME);
+#undef ADD_RECORDED_STREAM_NAME
+    if (vm_stream_.enabled()) {
+      recordedStreams.AddValue("VM");
+    }
+  }
+}
+
+
 void Timeline::Clear() {
   TimelineEventRecorder* recorder = Timeline::recorder();
   if (recorder == NULL) {
@@ -167,6 +271,7 @@
 TimelineEventRecorder* Timeline::recorder_ = NULL;
 TimelineStream Timeline::vm_stream_;
 TimelineStream Timeline::vm_api_stream_;
+MallocGrowableArray<char*>* Timeline::enabled_streams_ = NULL;
 
 #define ISOLATE_TIMELINE_STREAM_DEFINE_FLAG(name, enabled_by_default)          \
   bool Timeline::stream_##name##_enabled_ = enabled_by_default;
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
index cf77396..f44fb53 100644
--- a/runtime/vm/timeline.h
+++ b/runtime/vm/timeline.h
@@ -46,7 +46,7 @@
   // Access the global recorder. Not thread safe.
   static TimelineEventRecorder* recorder();
 
-  static bool EnableStreamByDefault(const char* stream_name);
+  static void SetupIsolateStreams(Isolate* isolate);
 
   static TimelineStream* GetVMStream();
 
@@ -57,6 +57,9 @@
 
   static void Clear();
 
+  // Print information about streams to JSON.
+  static void PrintFlagsToJSON(JSONStream* json);
+
 #define ISOLATE_TIMELINE_STREAM_FLAGS(name, not_used)                          \
   static const bool* Stream##name##EnabledFlag() {                             \
     return &stream_##name##_enabled_;                                          \
@@ -66,11 +69,13 @@
   }
   ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_FLAGS)
 #undef ISOLATE_TIMELINE_STREAM_FLAGS
+  static void SetVMStreamEnabled(bool enabled);
 
  private:
   static TimelineEventRecorder* recorder_;
   static TimelineStream vm_stream_;
   static TimelineStream vm_api_stream_;
+  static MallocGrowableArray<char*>* enabled_streams_;
 
 #define ISOLATE_TIMELINE_STREAM_DECLARE_FLAG(name, not_used)                   \
   static bool stream_##name##_enabled_;
@@ -618,7 +623,7 @@
   // Interface method(s) which must be implemented.
   virtual void PrintJSON(JSONStream* js, TimelineEventFilter* filter) = 0;
   virtual void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) = 0;
-
+  virtual const char* name() const = 0;
   int64_t GetNextAsyncId();
 
   void FinishBlock(TimelineEventBlock* block);
@@ -662,6 +667,9 @@
 
   void PrintJSON(JSONStream* js, TimelineEventFilter* filter);
   void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter);
+  const char* name() const {
+    return "ring";
+  }
 
  protected:
   TimelineEvent* StartEvent();
@@ -693,6 +701,10 @@
   // reference to |event| as it may be freed as soon as this function returns.
   virtual void StreamEvent(TimelineEvent* event) = 0;
 
+  const char* name() const {
+    return "streaming";
+  }
+
  protected:
   TimelineEventBlock* GetNewBlockLocked() {
     return NULL;
@@ -717,6 +729,10 @@
   void PrintJSON(JSONStream* js, TimelineEventFilter* filter);
   void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter);
 
+  const char* name() const {
+    return "endless";
+  }
+
  protected:
   TimelineEvent* StartEvent();
   void CompleteEvent(TimelineEvent* event);
diff --git a/runtime/vm/timeline_test.cc b/runtime/vm/timeline_test.cc
index 05c4abb..01d0c6a 100644
--- a/runtime/vm/timeline_test.cc
+++ b/runtime/vm/timeline_test.cc
@@ -345,12 +345,12 @@
   TimelineTestHelper::FakeThreadEvent(block_1_2, 1, "B2");
   TimelineTestHelper::FakeThreadEvent(block_1_2, 1, "B3");
   // Sleep to ensure timestamps differ.
-  OS::Sleep(1);
+  OS::Sleep(32);
   TimelineTestHelper::FakeThreadEvent(block_1_0, 1, "A1");
-  OS::Sleep(1);
+  OS::Sleep(32);
   TimelineTestHelper::FakeThreadEvent(block_1_1, 1, "C1");
   TimelineTestHelper::FakeThreadEvent(block_1_1, 1, "C2");
-  OS::Sleep(1);
+  OS::Sleep(32);
 
   // Add events to each block for thread 2.
   TimelineTestHelper::FakeThreadEvent(block_2_0, 2, "A");
@@ -455,7 +455,7 @@
 
   // Emit the earlier event into block_1.
   TimelineTestHelper::FakeThreadEvent(block_1, 2, "Alpha", &stream);
-  OS::Sleep(1);
+  OS::Sleep(32);
   // Emit the later event into block_0.
   TimelineTestHelper::FakeThreadEvent(block_0, 2, "Beta", &stream);
 
diff --git a/runtime/vm/virtual_memory.cc b/runtime/vm/virtual_memory.cc
index 1ad6c06..1372545 100644
--- a/runtime/vm/virtual_memory.cc
+++ b/runtime/vm/virtual_memory.cc
@@ -28,8 +28,7 @@
 }
 
 
-VirtualMemory* VirtualMemory::ForInstructionsSnapshot(void* pointer,
-                                                      uword size) {
+VirtualMemory* VirtualMemory::ForExternalPage(void* pointer, uword size) {
   // Memory for precompilated instructions was allocated by the embedder, so
   // create a VirtualMemory without allocating.
   MemoryRegion region(pointer, size);
diff --git a/runtime/vm/virtual_memory.h b/runtime/vm/virtual_memory.h
index 53ba57d..270d3cf 100644
--- a/runtime/vm/virtual_memory.h
+++ b/runtime/vm/virtual_memory.h
@@ -71,7 +71,7 @@
 
   bool embedder_allocated() const { return embedder_allocated_; }
 
-  static VirtualMemory* ForInstructionsSnapshot(void* pointer, uword size);
+  static VirtualMemory* ForExternalPage(void* pointer, uword size);
 
  private:
   static VirtualMemory* ReserveInternal(intptr_t size);
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index 30df00d..a3d0536 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -376,7 +376,6 @@
     'regexp_test.cc',
     'report.cc',
     'report.h',
-    'report_test.cc',
     'resolver.cc',
     'resolver.h',
     'resolver_test.cc',
diff --git a/sdk/lib/_internal/js_runtime/lib/async_patch.dart b/sdk/lib/_internal/js_runtime/lib/async_patch.dart
index 4d91d79..20cd748 100644
--- a/sdk/lib/_internal/js_runtime/lib/async_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/async_patch.dart
@@ -255,7 +255,7 @@
 /// is done, schedules [asyncBody] again.
 ///
 /// If the async* function wants to do an await it calls this function with
-/// [object] not and [IterationMarker].
+/// [object] not an [IterationMarker].
 ///
 /// If [object] is not a [Future], it is wrapped in a `Future.value`.
 /// The [asyncBody] is called on completion of the future (see [asyncHelper].
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 5dae802..b69c6fc 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -1495,7 +1495,7 @@
 class StreamView<T> extends Stream<T> {
   final Stream<T> _stream;
 
-  StreamView(this._stream);
+  const StreamView(Stream<T> stream) : _stream = stream, super._internal();
 
   bool get isBroadcast => _stream.isBroadcast;
 
diff --git a/sdk/lib/convert/line_splitter.dart b/sdk/lib/convert/line_splitter.dart
index 0af2f2f..b5ec32b 100644
--- a/sdk/lib/convert/line_splitter.dart
+++ b/sdk/lib/convert/line_splitter.dart
@@ -57,6 +57,9 @@
     }
     return new _LineSplitterSink(sink);
   }
+
+  // Override the base-class' bind, to provide a better type.
+  Stream<String> bind(Stream<String> stream) => super.bind(stream);
 }
 
 // TODO(floitsch): deal with utf8.
diff --git a/sdk/lib/developer/developer_sources.gypi b/sdk/lib/developer/developer_sources.gypi
index 0c4333a..5bdfe3d 100644
--- a/sdk/lib/developer/developer_sources.gypi
+++ b/sdk/lib/developer/developer_sources.gypi
@@ -5,9 +5,9 @@
 {
   'sources': [
     'developer.dart',
+    # The above file needs to be first if additional parts are added to the lib.
     'extension.dart',
     'profiler.dart',
     'timeline.dart',
-    # The above file needs to be first if additional parts are added to the lib.
   ],
 }
diff --git a/sdk/lib/developer/extension.dart b/sdk/lib/developer/extension.dart
index 309dca2..75737f6 100644
--- a/sdk/lib/developer/extension.dart
+++ b/sdk/lib/developer/extension.dart
@@ -4,21 +4,38 @@
 
 part of dart.developer;
 
+/// A response to a service protocol extension RPC.
+///
+/// If the RPC was successful, use [ServiceExtensionResponse.result], otherwise
+/// use [ServiceExtensionResponse.error].
 class ServiceExtensionResponse {
   final String _result;
   final int _errorCode;
   final String _errorDetail;
 
-  ServiceExtensionResponse.result(this._result)
-      : _errorCode = null,
+  /// Creates a successful to a service protocol extension RPC.
+  ///
+  /// Requires [result] to be a JSON object encoded as a string. When forming
+  /// the JSON-RPC message [result] will be inlined directly.
+  ServiceExtensionResponse.result(String result)
+      : _result = result,
+        _errorCode = null,
         _errorDetail = null {
     if (_result is! String) {
       throw new ArgumentError.value(_result, "result", "Must be a String");
     }
   }
 
-  ServiceExtensionResponse.error(this._errorCode, this._errorDetail)
-      : _result = null {
+  /// Creates an error response to a service protocol extension RPC.
+  ///
+  /// Requires [errorCode] to be [invalidParams] or between [extensionErrorMin]
+  /// and [extensionErrorMax]. Requires [errorDetail] to be a JSON object
+  /// encoded as a string. When forming the JSON-RPC message [errorDetail] will
+  /// be inlined directly.
+  ServiceExtensionResponse.error(int errorCode, String errorDetail)
+      : _result = null,
+        _errorCode = errorCode,
+        _errorDetail = errorDetail {
     _validateErrorCode(_errorCode);
     if (_errorDetail is! String) {
       throw new ArgumentError.value(_errorDetail,
@@ -28,13 +45,23 @@
   }
 
   /// Invalid method parameter(s) error code.
-  static const kInvalidParams = -32602;
+  @deprecated static const kInvalidParams = invalidParams;
   /// Generic extension error code.
-  static const kExtensionError = -32000;
+  @deprecated static const kExtensionError = extensionError;
   /// Maximum extension provided error code.
-  static const kExtensionErrorMax = -32000;
+  @deprecated static const kExtensionErrorMax = extensionErrorMax;
   /// Minimum extension provided error code.
-  static const kExtensionErrorMin = -32016;
+  @deprecated static const kExtensionErrorMin = extensionErrorMin;
+
+  /// Invalid method parameter(s) error code.
+  static const invalidParams = -32602;
+  /// Generic extension error code.
+  static const extensionError = -32000;
+  /// Maximum extension provided error code.
+  static const extensionErrorMax = -32000;
+  /// Minimum extension provided error code.
+  static const extensionErrorMin = -32016;
+
 
   static String _errorCodeMessage(int errorCode) {
     _validateErrorCode(errorCode);
@@ -48,11 +75,11 @@
     if (errorCode is! int) {
       throw new ArgumentError.value(errorCode, "errorCode", "Must be an int");
     }
-    if (errorCode == kInvalidParams) {
+    if (errorCode == invalidParams) {
       return;
     }
-    if ((errorCode >= kExtensionErrorMin) &&
-        (errorCode <= kExtensionErrorMax)) {
+    if ((errorCode >= extensionErrorMin) &&
+        (errorCode <= extensionErrorMax)) {
       return;
     }
     throw new ArgumentError.value(errorCode, "errorCode", "Out of range");
@@ -90,14 +117,27 @@
 
 /// Register a [ServiceExtensionHandler] that will be invoked in this isolate
 /// for [method]. *NOTE*: Service protocol extensions must be registered
-/// in each isolate and users of extensions must always specify a target
-/// isolate.
+/// in each isolate.
+///
+/// *NOTE*: [method] must begin with 'ext.' and you should use the following
+/// structure to avoid conflicts with other packages: 'ext.package.command'.
+/// That is, immediately following the 'ext.' prefix, should be the registering
+/// package name followed by another period ('.') and then the command name.
+/// For example: 'ext.dart.io.getOpenFiles'.
+///
+/// Because service extensions are isolate specific, clients using extensions
+/// must always include an 'isolateId' parameter with each RPC.
 void registerExtension(String method, ServiceExtensionHandler handler) {
   if (method is! String) {
     throw new ArgumentError.value(method,
                                   'method',
                                   'Must be a String');
   }
+  if (!method.startsWith('ext.')) {
+    throw new ArgumentError.value(method,
+                                  'method',
+                                  'Must begin with ext.');
+  }
   if (_lookupExtension(method) != null) {
     throw new ArgumentError('Extension already registered: $method');
   }
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 8d4c3de..c306d5b 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -26122,8 +26122,12 @@
 
   @DomName('MessageEvent.data')
   @DocsEditable()
-  Object get data => wrap_jso(_blink.BlinkMessageEvent.instance.data_Getter_(unwrap_jso(this)));
-  
+  // TODO(alanknight): This really should be generated by the
+  // _OutputConversion in the systemnative.py script, but that doesn't
+  // use those conversions right now, so do this as a one-off.
+  dynamic get data => convertNativeToDart_SerializedScriptValue(
+      _blink.BlinkMessageEvent.instance.data_Getter_(unwrap_jso(this)));
+
   @DomName('MessageEvent.lastEventId')
   @DocsEditable()
   @Unstable()
@@ -48429,8 +48433,7 @@
     return [
         "inspect",
         (o) {
-          host.callMethod("inspect", [o]);
-          return o;
+          return host.callMethod("_inspect", [unwrap_jso(o)]);
         },
         "dir",
         window().console.dir,
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index 5dd559c..0d0bc9e 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -595,9 +595,9 @@
       // We need to make sure that these are always awailable from the
       // observatory even if no files (or sockets for the socket ones) are
       // open.
-      registerExtension('__getOpenFiles',
+      registerExtension('ext.dart.io.getOpenFiles',
                         _FileResourceInfo.getOpenFiles);
-      registerExtension('__getFileByID',
+      registerExtension('ext.dart.io.getFileByID',
                         _FileResourceInfo.getFileInfoMapByID);
       _connectedResourceHandler = true;
     }
diff --git a/sdk/lib/io/io_resource_info.dart b/sdk/lib/io/io_resource_info.dart
index 1a18fc9..9267084 100644
--- a/sdk/lib/io/io_resource_info.dart
+++ b/sdk/lib/io/io_resource_info.dart
@@ -112,7 +112,7 @@
   }
 
   static Future<ServiceExtensionResponse> getOpenFiles(function, params) {
-    assert(function == '__getOpenFiles');
+    assert(function == 'ext.dart.io.getOpenFiles');
     var data = {'type': '_openfiles', 'data': getOpenFilesList()};
     var json = JSON.encode(data);
     return new Future.value(new ServiceExtensionResponse.result(json));
@@ -182,7 +182,7 @@
 
   static Future<ServiceExtensionResponse> getStartedProcesses(
       String function, Map<String, String> params) {
-    assert(function == '__getProcesses');
+    assert(function == 'ext.dart.io.getProcesses');
     var data = {'type': '_startedprocesses', 'data': getStartedProcessesList()};
     var json = JSON.encode(data);
     return new Future.value(new ServiceExtensionResponse.result(json));
@@ -264,7 +264,7 @@
   }
 
   static Future<ServiceExtensionResponse> getOpenSockets(function, params) {
-    assert(function == '__getOpenSockets');
+    assert(function == 'ext.dart.io.getOpenSockets');
     var data = {'type': '_opensockets', 'data': getOpenSocketsList()};
     var json = JSON.encode(data);
     return new Future.value(new ServiceExtensionResponse.result(json));
diff --git a/sdk/lib/io/iolib_sources.gypi b/sdk/lib/io/io_sources.gypi
similarity index 91%
rename from sdk/lib/io/iolib_sources.gypi
rename to sdk/lib/io/io_sources.gypi
index ad2110f..10a6bf4 100644
--- a/sdk/lib/io/iolib_sources.gypi
+++ b/sdk/lib/io/io_sources.gypi
@@ -4,6 +4,8 @@
 
 {
   'sources': [
+    'io.dart',
+    # The above file needs to be first if additional parts are added to the lib.
     'bytes_builder.dart',
     'common.dart',
     'crypto.dart',
diff --git a/sdk/lib/io/security_context.dart b/sdk/lib/io/security_context.dart
index 28351b2..7fc7287 100644
--- a/sdk/lib/io/security_context.dart
+++ b/sdk/lib/io/security_context.dart
@@ -46,7 +46,7 @@
    *
    * A secure connection using this SecurityContext will use this key with
    * the server or client certificate to sign and decrypt messages.
-   * [keyFile] is a PEM file containing an encrypted
+   * [keyFile] is a PEM or PKCS12 file containing an encrypted
    * private key, encrypted with [password].  An unencrypted file can be
    * used, but this is not usual.
    */
@@ -62,11 +62,7 @@
   /**
    * Sets the private key for a server certificate or client certificate.
    *
-   * A secure connection using this SecurityContext will use this key with
-   * the server or client certificate to sign and decrypt messages.
-   * [keyBytes] is the contents of a PEM file containing an encrypted
-   * private key, encrypted with [password].  An unencrypted file can be
-   * used, but this is not usual.
+   * Like [usePrivateKeyBytesSync], but takes the contents of the file.
    */
   void usePrivateKeyBytes(List<int> keyBytes, {String password});
 
@@ -74,8 +70,10 @@
    * Sets the set of trusted X509 certificates used by [SecureSocket]
    * client connections, when connecting to a secure server.
    *
-   * [file] is the path to a PEM file containing X509 certificates, usually
-   * root certificates from certificate authorities.
+   * [file] is the path to a PEM or PKCS12 file containing X509 certificates,
+   * usually root certificates from certificate authorities. When using a
+   * PKCS12 file, it should not contain a private key, and the password should
+   * be the empty string.
    */
   void setTrustedCertificatesSync(String file);
 
@@ -90,8 +88,7 @@
    * Sets the set of trusted X509 certificates used by [SecureSocket]
    * client connections, when connecting to a secure server.
    *
-   * [file] is the contents of a PEM file containing X509 certificates, usually
-   * root certificates from certificate authorities.
+   * Like [setTrustedCertificatesSync] but takes the contents of the file.
    */
   void setTrustedCertificatesBytes(List<int> certBytes);
 
@@ -99,10 +96,12 @@
    * Sets the chain of X509 certificates served by [SecureServer]
    * when making secure connections, including the server certificate.
    *
-   * [file] is a PEM file containing X509 certificates, starting with
+   * [file] is a PEM or PKCS12 file containing X509 certificates, starting with
    * the root authority and intermediate authorities forming the signed
    * chain to the server certificate, and ending with the server certificate.
-   * The private key for the server certificate is set by [usePrivateKey].
+   * The private key for the server certificate is set by [usePrivateKey]. When
+   * using a PKCS12 file, it should not contain a private key, and the password
+   * should be the empty string.
    */
   void useCertificateChainSync(String file);
 
@@ -117,19 +116,19 @@
    * Sets the chain of X509 certificates served by [SecureServer]
    * when making secure connections, including the server certificate.
    *
-   * [chainBytes] is the contents of a PEM file containing X509 certificates,
-   * starting with the root authority and intermediate authorities forming the
-   * signed chain to the server certificate, and ending with the server
-   * certificate. The private key for the server certificate is set by
-   * [usePrivateKey].
+   * Like [useCertificateChainSync] but takes the contents of the file.
    */
   void useCertificateChainBytes(List<int> chainBytes);
 
   /**
    * Sets the list of authority names that a [SecureServer] will advertise
-   * as accepted, when requesting a client certificate from a connecting
-   * client.  [file] is a PEM file containing the accepted signing authority
-   * certificates - the authority names are extracted from the certificates.
+   * as accepted when requesting a client certificate from a connecting
+   * client.
+   *
+   * [file] is a PEM or PKCS12 file containing the accepted signing
+   * authority certificates - the authority names are extracted from the
+   * certificates. When using a PKCS12 file, it should not contain a private
+   * key, and the password should be the empty string.
    */
   void setClientAuthoritiesSync(String file);
 
@@ -143,9 +142,9 @@
   /**
    * Sets the list of authority names that a [SecureServer] will advertise
    * as accepted, when requesting a client certificate from a connecting
-   * client.  [authCertBytes] is the contents of a PEM file containing the
-   * accepted signing authority certificates - the authority names are extracted
-   * from the certificates.
+   * client.
+   *
+   * Like [setClientAuthoritySync] but takes the contents of the file.
    */
   void setClientAuthoritiesBytes(List<int> authCertBytes);
 
diff --git a/sdk/lib/rules.gni b/sdk/lib/rules.gni
new file mode 100644
index 0000000..93ade221
--- /dev/null
+++ b/sdk/lib/rules.gni
@@ -0,0 +1,44 @@
+# 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.
+
+# This build rule will copy the source for one Dart SDK library.
+#
+# Required arguments:
+#   sdk_lib_name
+#       The name of a Dart SDK library.
+#
+# Optional arguments:
+#   dart_root
+#       Path to the Dart SDK source root. Default value is "//dart".
+#
+# The sources will be copied into $root_gen_dir/dart_sdk_libs/$sdk_lib_name/.
+#
+template("dart_sdk_lib_copy") {
+  assert(defined(invoker.sdk_lib_name))
+  if (defined(invoker.dart_root)) {
+    dart_root = rebase_path(invoker.dart_root)
+  } else {
+    dart_root = rebase_path("//dart")
+  }
+  dart_sdk_sdk_lib_path =
+      rebase_path("sdk/lib", "", dart_root)
+  dart_sdk_tools_gypi_to_gn_path =
+      rebase_path("tools/gypi_to_gn.py", "", dart_root)
+  # The name of the SDK library being copied.
+  lib_name = invoker.sdk_lib_name
+  # The path to the libraries source directory.
+  lib_path = rebase_path(lib_name, "", dart_sdk_sdk_lib_path)
+  # The path to the sources gypi.
+  lib_sources_gypi = lib_name + "_sources.gypi"
+  # Get the contents of the gypi file.
+  sdk_lib_sources_gypi =
+      exec_script(dart_sdk_tools_gypi_to_gn_path,
+                  [rebase_path(lib_sources_gypi, "", lib_path)],
+                  "scope",
+                  [rebase_path(lib_sources_gypi, "", lib_path)])
+  copy(target_name) {
+    sources = rebase_path(sdk_lib_sources_gypi.sources, "", lib_path)
+    outputs = [ "$root_gen_dir/dart_sdk_libs/$lib_name/{{source_file_part}}" ]
+  }
+}
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 7a3b561..8ee4e6d 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -9619,12 +9619,6 @@
 [ $compiler == dart2js && $cps_ir ]
 Language/Types/Interface_Types/subtype_t09: Crash # Pending static: JSArray
 LibTest/collection/ListBase/ListBase_class_A01_t02: Pass, Timeout
-LibTest/core/Invocation/isAccessor_A01_t01: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
 LibTest/core/Invocation/isGetter_A01_t01: RuntimeError # Please triage this failure.
-LibTest/core/Invocation/isGetter_A01_t02: RuntimeError # Please triage this failure.
-LibTest/core/Invocation/isMethod_A01_t02: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
-LibTest/core/Invocation/isSetter_A01_t01: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
 LibTest/core/Invocation/isSetter_A01_t02: RuntimeError # Please triage this failure.
-LibTest/core/Invocation/memberName_A01_t01: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
-LibTest/core/Invocation/namedArguments_A01_t01: RuntimeError # Please triage this failure.
-LibTest/core/Invocation/positionalArguments_A01_t01: RuntimeError # Please triage this failure.
+LibTest/core/Invocation/memberName_A01_t01: RuntimeError # Expect.equals(expected: <Symbol("bar=")>, actual: <Symbol("bar")>) fails.
diff --git a/tests/co19/co19-dartium.status b/tests/co19/co19-dartium.status
index 502bd58..eb8f2c5 100644
--- a/tests/co19/co19-dartium.status
+++ b/tests/co19/co19-dartium.status
@@ -462,8 +462,6 @@
 LayoutTests/fast/mediastream/RTCPeerConnection-AddRemoveStream_t01: Skip # Issue 22111
 LayoutTests/fast/mediastream/RTCPeerConnection-AddRemoveStream_t01: Skip # Passes on Safari, Issue 23475 # co19 issue 11.
 LayoutTests/fast/mediastream/getusermedia_t01: Skip # co19 issue 738
-LayoutTests/fast/multicol/balance-short-trailing-empty-block_t01: RuntimeError # co19-roll r801: Please triage this failure.
-LayoutTests/fast/multicol/balance-trailing-border_t01: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/multicol/balance-trailing-border_t02: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/multicol/balance-unbreakable_t01: Pass, RuntimeError # co19 issue 11.
 LayoutTests/fast/multicol/break-after-always-bottom-margin_t01: RuntimeError # co19-roll r801: Please triage this failure.
@@ -507,7 +505,6 @@
 LayoutTests/fast/multicol/vertical-rl/image-inside-nested-blocks-with-border_t01: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/multicol/widows_t01: Pass, RuntimeError # co19 issue 11.
 LayoutTests/fast/multicol/widows_t01: Pass, RuntimeError # co19-roll r801: Please triage this failure.
-LayoutTests/fast/multicol/widows_t02: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/multicol/zeroColumnCount_t01: RuntimeError # co19 issue 11.
 LayoutTests/fast/overflow/child-100percent-height-inside-fixed-container-with-overflow-auto_t01: Pass, RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/overflow/child-100percent-height-inside-fixed-container-with-overflow-auto_t01: RuntimeError # co19 issue 11.
@@ -702,7 +699,6 @@
 LayoutTests/fast/xpath/attr-namespace_t02: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/xpath/ensure-null-namespace_t01: RuntimeError # co19-roll r761: Please triage this failure.
 LayoutTests/fast/xpath/implicit-node-args_t01: RuntimeError # co19-roll r761: Please triage this failure.
-LayoutTests/fast/xpath/invalid-resolver_t01: RuntimeError # co19-roll r761: Please triage this failure.
 LayoutTests/fast/xpath/node-name-case-sensitivity_t01: RuntimeError # co19-roll r761: Please triage this failure.
 LayoutTests/fast/xpath/node-name-case-sensitivity_t02: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/xpath/position_t01: RuntimeError # co19-roll r761: Please triage this failure.
@@ -731,7 +727,6 @@
 LibTest/html/Element/focus_A01_t01: Skip # co19-roll r706.  Please triage this failure.
 LibTest/html/Element/getAttributeNS_A01_t01: RuntimeError # co19-roll r706.  Issue 16395
 LibTest/html/Element/getAttributeNS_A01_t02: RuntimeError # Please triage this failure.
-LibTest/html/Element/getClientRects_A01_t02: RuntimeError # co19-roll r706.  Issue 16575
 LibTest/html/Element/getNamespacedAttributes_A01_t01: RuntimeError # co19-roll r706.  Issue 16395
 LibTest/html/Element/isContentEditable_A01_t01: RuntimeError # co19-roll r706.  Please triage this failure.
 LibTest/html/Element/isContentEditable_A02_t01: RuntimeError # co19-roll r706.  Please triage this failure.
@@ -763,7 +758,6 @@
 LibTest/html/IFrameElement/createShadowRoot_A01_t01: RuntimeError # co19-roll r706.  Please triage this failure.
 LibTest/html/IFrameElement/enteredView_A01_t01: Skip # co19-roll r706.  Please triage this failure.
 LibTest/html/IFrameElement/focus_A01_t01: Skip # co19-roll r706.  Please triage this failure.
-LibTest/html/IFrameElement/getClientRects_A01_t02: RuntimeError # co19-roll r706.  Please triage this failure.
 LibTest/html/IFrameElement/getNamespacedAttributes_A01_t01: RuntimeError # co19-roll r706.  Please triage this failure.
 LibTest/html/IFrameElement/innerHtml_A01_t01: RuntimeError # co19-roll r706.  Please triage this failure.
 LibTest/html/IFrameElement/isContentEditable_A01_t01: RuntimeError # co19-roll r706.  Please triage this failure.
@@ -780,7 +774,6 @@
 LibTest/html/Node/nodes_A01_t02: RuntimeError # co19-roll r722: Please triage this failure.
 LibTest/html/Node/parent_A01_t01: RuntimeError # co19-roll r722: Please triage this failure.
 LibTest/html/Node/previousNode_A01_t01: RuntimeError # co19-roll r722: Please triage this failure.
-LibTest/html/Window/close_A01_t01: RuntimeError # co19-roll r706.  Please triage this failure.
 LibTest/html/Window/find_A01_t01: RuntimeError # co19-roll r706.  Please triage this failure.
 LibTest/html/Window/find_A03_t01: RuntimeError # co19-roll r706.  Please triage this failure.
 LibTest/html/Window/find_A06_t01: RuntimeError # co19-roll r706.  Please triage this failure.
@@ -863,12 +856,12 @@
 LibTest/isolate/ReceivePort/transform_A01_t02: RuntimeError, OK  # Uses Isolate.spawn.
 LibTest/isolate/ReceivePort/where_A01_t01: RuntimeError, OK  # Uses Isolate.spawn.
 LibTest/isolate/ReceivePort/where_A01_t02: RuntimeError, OK  # Uses Isolate.spawn.
+LibTest/isolate/ReceivePort/close_A01_t01: Pass, RuntimeError # Issue 13921, co19 issue for false pass https://github.com/dart-lang/co19/issues/13
 LibTest/isolate/ReceivePort/asBroadcastStream_A01_t02: Pass, RuntimeError # Issue 13921, co19 issue for false pass https://github.com/dart-lang/co19/issues/13
 LibTest/isolate/ReceivePort/asBroadcastStream_A02_t01: RuntimeError # Issue 13921
 LibTest/isolate/ReceivePort/asBroadcastStream_A03_t01: Pass, RuntimeError # Issue 13921, co19 issue for false pass https://github.com/dart-lang/co19/issues/13
 LibTest/isolate/ReceivePort/asBroadcastStream_A03_t02: Pass, RuntimeError # Issue 13921, co19 issue for false pass https://github.com/dart-lang/co19/issues/13
 LibTest/isolate/ReceivePort/asBroadcastStream_A03_t03: Pass, RuntimeError # Issue 13921, co19 issue for false pass https://github.com/dart-lang/co19/issues/13
-LibTest/isolate/ReceivePort/close_A01_t01: Pass, RuntimeError # Issue 13921, co19 issue for false pass https://github.com/dart-lang/co19/issues/13
 LibTest/isolate/ReceivePort/close_A02_t01: Pass, RuntimeError # Issue 13921, co19 issue for false pass https://github.com/dart-lang/co19/issues/13
 LibTest/isolate/ReceivePort/sendPort_A01_t01: RuntimeError # Issue 13921
 LibTest/isolate/SendPort/send_A01_t01: RuntimeError, OK  # Uses Isolate.spawn.
@@ -1050,8 +1043,6 @@
 WebPlatformTest/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-009_t01: RuntimeError # Please triage this failure.
 WebPlatformTest/webstorage/event_constructor_t01: RuntimeError # co19-roll r761: Please triage this failure.
 WebPlatformTest/webstorage/event_constructor_t02: RuntimeError # co19-roll r761: Please triage this failure.
-WebPlatformTest/webstorage/event_local_key_t01: RuntimeError # co19-roll r761: Please triage this failure.
-WebPlatformTest/webstorage/event_session_key_t01: RuntimeError # co19-roll r761: Please triage this failure.
 WebPlatformTest/webstorage/storage_local_setitem_quotaexceedederr_t01: Skip # Times out flakily. co19-roll r761: Please triage this failure.
 WebPlatformTest/webstorage/storage_session_setitem_quotaexceedederr_t01: Skip # Times out flakily. co19-roll r761: Please triage this failure.
 
@@ -1130,6 +1121,7 @@
 LayoutTests/fast/text/line-break-after-inline-latin1_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/url/trivial-segments_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/url/trivial_t01: RuntimeError # co19-roll r786: Please triage this failure.
+LayoutTests/fast/xpath/invalid-resolver_t01: RuntimeError # https://github.com/dart-lang/co19/issues/21
 LayoutTests/fast/xpath/xpath-result-eventlistener-crash_t01: RuntimeError # co19-roll r761: Please triage this failure.
 LibTest/html/Node/ownerDocument_A01_t01: RuntimeError # co19-roll r722: Issue 18251
 WebPlatformTest/DOMEvents/approved/Propagation.path.target.removed_t01: RuntimeError # co19-roll r738: Please triage this failure.
@@ -1258,50 +1250,49 @@
 LayoutTests/fast/canvas/webgl/viewport-unchanged-upon-resize_t01: RuntimeError # Issue 25653
 LayoutTests/fast/canvas/webgl/webgl-depth-texture_t01: RuntimeError # Please triage this failure
 
-[ $compiler == none && $runtime == dartium && $system != macos ]
-LayoutTests/fast/canvas/webgl/WebGLContextEvent_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/attrib-location-length-limits_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/buffer-bind-test_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/WebGLContextEvent_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/attrib-location-length-limits_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/buffer-bind-test_t01: Pass, RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/buffer-data-array-buffer_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/canvas-test_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/canvas-zero-size_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/compressed-tex-image_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/context-destroyed-crash_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/css-webkit-canvas-repaint_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/css-webkit-canvas_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/context-destroyed-crash_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/css-webkit-canvas-repaint_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/css-webkit-canvas_t01: Pass, RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/draw-arrays-out-of-bounds_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/draw-elements-out-of-bounds_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/draw-webgl-to-canvas-2d_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/error-reporting_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/draw-webgl-to-canvas-2d_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/error-reporting_t01: Pass, RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/framebuffer-bindings-unaffected-on-resize_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/framebuffer-object-attachment_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/framebuffer-test_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/functions-returning-strings_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/get-active-test_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/gl-enable-enum-test_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/framebuffer-test_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/functions-returning-strings_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/get-active-test_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/gl-enable-enum-test_t01: Pass, RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/gl-enum-tests_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/gl-get-calls_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/gl-getshadersource_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/gl-getstring_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/gl-get-calls_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/gl-getshadersource_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/gl-getstring_t01: Pass, RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/gl-teximage_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/gl-uniformmatrix4fv_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/gl-vertex-attrib-zero-issues_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/gl-vertex-attrib_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/gl-vertexattribpointer_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/glsl-conformance_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/gl-vertexattribpointer_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/glsl-conformance_t01: Pass, RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/index-validation-copies-indices_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/index-validation-crash-with-buffer-sub-data_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/index-validation-verifies-too-many-indices_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/index-validation-with-resized-buffer_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/index-validation_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/invalid-UTF-16_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/invalid-UTF-16_t01: Pass, RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/invalid-passed-params_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/null-uniform-location_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/object-deletion-behaviour_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/oes-element-index-uint_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/program-test_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/renderer-and-vendor-strings_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/shader-precision-format_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/renderer-and-vendor-strings_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/shader-precision-format_t01: Pass, RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-array-buffer-view_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas-rgb565_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas-rgba4444_t01: RuntimeError # Issue 22026
@@ -1321,24 +1312,86 @@
 LayoutTests/fast/canvas/webgl/tex-sub-image-cube-maps_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/texImageTest_t01: RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/texture-transparent-pixels-initialized_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/uniform-location-length-limits_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/uniform-location-length-limits_t01: Pass, RuntimeError # Issue 22026
 LayoutTests/fast/canvas/webgl/uninitialized-test_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/webgl-composite-modes-repaint_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/webgl-composite-modes_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/webgl-exceptions_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/webgl-layer-update_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/webgl-specific_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/webgl-unprefixed-context-id_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/webgl-viewport-parameters-preserved_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/gl-object-get-calls_t01: RuntimeError #  Issue 20, 22026
-LayoutTests/fast/canvas/webgl/incorrect-context-object-behaviour_t01: RuntimeError # Issue 20, 22026
-LayoutTests/fast/canvas/webgl/null-object-behaviour_t01: RuntimeError # Issue 20, 22026
-LayoutTests/fast/canvas/webgl/bad-arguments-test_t01: RuntimeError # Issue 20, 22026
+LayoutTests/fast/canvas/webgl/webgl-composite-modes-repaint_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/webgl-composite-modes_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/webgl-exceptions_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/webgl-layer-update_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/webgl-specific_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/webgl-unprefixed-context-id_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/webgl-viewport-parameters-preserved_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/gl-object-get-calls_t01: RuntimeError #  Pass, Issue 20, 22026
+LayoutTests/fast/canvas/webgl/incorrect-context-object-behaviour_t01: Pass, RuntimeError # Issue 20, 22026
+LayoutTests/fast/canvas/webgl/null-object-behaviour_t01: Pass, RuntimeError # Issue 20, 22026
+LayoutTests/fast/canvas/webgl/bad-arguments-test_t01: Pass, RuntimeError # Issue 20, 22026
 LayoutTests/fast/canvas/webgl/context-lost_t01: RuntimeError # Issue 20, 22026
 LayoutTests/fast/canvas/webgl/framebuffer-test_t01: RuntimeError # Issue 20, 22026
 LayoutTests/fast/canvas/webgl/invalid-passed-params_t01: RuntimeError # Issue 20, 22026
 LayoutTests/fast/canvas/webgl/tex-input-validation_t01: RuntimeError # Issue 20, 22026
-LayoutTests/fast/canvas/webgl/tex-sub-image-2d-bad-args_t01: RuntimeError # Issue 20, 22026
+LayoutTests/fast/canvas/webgl/tex-sub-image-2d-bad-args_t01: Pass, RuntimeError # Issue 20, 22026
+
+LayoutTests/fast/canvas/alpha_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/canvas/canvas-lineDash-input-sequence_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css-intrinsic-dimensions/intrinsic-sized-replaced-absolutes_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/MarqueeLayoutTest_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/aspect-ratio-inheritance_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/aspect-ratio-parsing-tests_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/auto-min-size_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/background-position-serialize_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/content-language-case-insensitivity_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/content-language-dynamically-added_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/content-language-dynamically-removed_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/content-language-mapped-to-webkit-locale_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/content-language-multiple_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/content-language-no-content_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/counters/counter-cssText_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/cssText-shorthand_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/csstext-of-content-string_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/ex-unit-with-no-x-height_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/font-shorthand-from-longhands_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/getComputedStyle/computed-style-font_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/getComputedStyle/computed-style-properties_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/getComputedStyle/counterIncrement-without-counter_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/getPropertyValue-columns_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/image-set-setting_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/important-js-override_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/nested-at-rules_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/parse-color-int-or-percent-crash_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/parsing-css-allowed-string-characters_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/parsing-css-nth-child_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/parsing-text-rendering_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/pseudo-valid-unapplied_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/string-quote-binary_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/transform-origin-parsing_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/dom/background-shorthand-csstext_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/dom/css-selectorText_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/dom/custom/element-names_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/dom/fragment-activation-focuses-target_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/dom/shadow/content-reprojection-fallback-crash_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/dom/shadow/event-path_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/dom/shadow/shadow-disable_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/dom/shadow/shadow-root-js-api_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/encoding/css-charset-dom_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/events/overflowchanged-event-raf-timing_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/files/blob-constructor_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/files/file-reader-fffd_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/forms/ValidityState-customError_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/forms/input-value-sanitization_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/forms/validationMessage_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/innerHTML/javascript-url_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/multicol/columns-shorthand-parsing_t02: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/replaced/iframe-with-percentage-height-within-table-with-anonymous-table-cell_t01: RuntimeError # Dartium 45 roll. Issue 25754
+WebPlatformTest/html/semantics/forms/textfieldselection/selection_t01: RuntimeError # Dartium 45 roll. Issue 25754
+WebPlatformTest/shadow-dom/elements-and-dom-objects/extensions-to-event-interface/event-path-001_t01: RuntimeError # Dartium 45 roll. Issue 25754
+WebPlatformTest/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-002_t01: RuntimeError # Dartium 45 roll. Issue 25754
+WebPlatformTest/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-005_t01: RuntimeError # Dartium 45 roll. Issue 25754
+WebPlatformTest/shadow-dom/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-002_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css-intrinsic-dimensions/intrinsic-sized-replaced-absolutes_t01: Timeout # Dartium 45 roll. Issue 25754
+LayoutTests/fast/replaced/iframe-with-percentage-height-within-table-with-anonymous-table-cell_t01: Timeout # Dartium 45 roll. Issue 25754
+LayoutTests/fast/replaced/iframe-with-percentage-height-within-table-with-table-cell-ignore-height_t01: Timeout # Dartium 45 roll. Issue 25754
+LayoutTests/fast/events/change-overflow-on-overflow-change_t01: Timeout # Dartium 45 roll. Issue 25754
+LayoutTests/fast/loader/onload-policy-ignore-for-frame_t01: Timeout # Dartium 45 roll. Issue 25754
 
 [ $compiler == none && ($runtime == dartium || $runtime == ContentShellOnAndroid) && $system != windows ]
 LayoutTests/fast/css/font-face-unicode-range-monospace_t01: RuntimeError # co19-roll r761: Please triage this failure.
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index ae94df1..322d664 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -59,11 +59,13 @@
 [ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && $mode == debug ]
 LibTest/core/List/List_class_A01_t02: Pass, Slow
 
-[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ($arch != x64 && $arch != simarm64) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ($arch != x64 && $arch != simarm64 && $arch != arm64) ]
 LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
 
-[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && $arch == mips ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ($arch == mips) ]
 LibTest/core/double/toInt_A01_t01: Fail
+
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ($arch == mips || $arch == arm64) ]
 # 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
 LibTest/core/List/List_class_A01_t02: Skip # co19 issue 673
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_1.js b/tests/compiler/dart2js/cps_ir/expected/basic_1.js
index 5ae55be..f8384d4 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_1.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_1.js
@@ -19,9 +19,9 @@
   P.print("()");
   P.print("(true)");
   P.print("(1)");
-  P.print("(" + P.IterableBase_iterableToFullString([1, 2, 3], "[", "]") + ")");
+  P.print("(" + H.S([1, 2, 3]) + ")");
   P.print("(" + P.Maps_mapToString(P.LinkedHashMap__makeLiteral(["s", 1])) + ")");
   P.print("(1)");
-  P.print("(" + P.IterableBase_iterableToFullString(l, "[", "]") + ")");
+  P.print("(" + H.S(l) + ")");
   P.print("(" + P.Maps_mapToString(m) + ")");
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_10.js b/tests/compiler/dart2js/cps_ir/expected/basic_10.js
index 104f614..745bc50 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_10.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_10.js
@@ -4,7 +4,7 @@
 // }
 
 function() {
-  var line = Date.now() < Date.now() ? "true" : "false";
+  var line = H.S(Date.now() < Date.now());
   if (typeof dartPrint == "function")
     dartPrint(line);
   else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_11.js b/tests/compiler/dart2js/cps_ir/expected/basic_11.js
index 5f26f1c..68995ca 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_11.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_11.js
@@ -3,14 +3,13 @@
 // main() { foo(); }
 
 function() {
-  var line = "" + 42;
   if (typeof dartPrint == "function")
-    dartPrint(line);
+    dartPrint("42");
   else if (typeof console == "object" && typeof console.log != "undefined")
-    console.log(line);
+    console.log("42");
   else if (!(typeof window == "object")) {
     if (!(typeof print == "function"))
-      throw "Unable to print message: " + String(line);
-    print(line);
+      throw "Unable to print message: " + String("42");
+    print("42");
   }
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_12.js b/tests/compiler/dart2js/cps_ir/expected/basic_12.js
index 084681f..ac9e1d3 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_12.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_12.js
@@ -3,7 +3,7 @@
 // main() { print(foo); }
 
 function() {
-  var v0 = $.foo, line = v0 === 0 ? 1 / v0 < 0 ? "-0.0" : "" + v0 : "" + v0;
+  var line = H.S($.foo);
   if (typeof dartPrint == "function")
     dartPrint(line);
   else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_13.js b/tests/compiler/dart2js/cps_ir/expected/basic_13.js
index 218ba31..e8db598 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_13.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_13.js
@@ -3,14 +3,13 @@
 // main() { foo; }
 
 function() {
-  var line = "" + 42;
   if (typeof dartPrint == "function")
-    dartPrint(line);
+    dartPrint("42");
   else if (typeof console == "object" && typeof console.log != "undefined")
-    console.log(line);
+    console.log("42");
   else if (!(typeof window == "object")) {
     if (!(typeof print == "function"))
-      throw "Unable to print message: " + String(line);
-    print(line);
+      throw "Unable to print message: " + String("42");
+    print("42");
   }
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_14.js b/tests/compiler/dart2js/cps_ir/expected/basic_14.js
index a42876b..068816d 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_14.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_14.js
@@ -3,15 +3,14 @@
 // main() { print(foo = 42); }
 
 function() {
-  var line = "" + 42;
   $.foo = 42;
   if (typeof dartPrint == "function")
-    dartPrint(line);
+    dartPrint("42");
   else if (typeof console == "object" && typeof console.log != "undefined")
-    console.log(line);
+    console.log("42");
   else if (!(typeof window == "object")) {
     if (!(typeof print == "function"))
-      throw "Unable to print message: " + String(line);
-    print(line);
+      throw "Unable to print message: " + String("42");
+    print("42");
   }
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_15.js b/tests/compiler/dart2js/cps_ir/expected/basic_15.js
index ea86609..92ba7b0 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_15.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_15.js
@@ -3,14 +3,13 @@
 // main() { foo = 42; }
 
 function() {
-  var line = "" + 42;
   if (typeof dartPrint == "function")
-    dartPrint(line);
+    dartPrint("42");
   else if (typeof console == "object" && typeof console.log != "undefined")
-    console.log(line);
+    console.log("42");
   else if (!(typeof window == "object")) {
     if (!(typeof print == "function"))
-      throw "Unable to print message: " + String(line);
-    print(line);
+      throw "Unable to print message: " + String("42");
+    print("42");
   }
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_4.js b/tests/compiler/dart2js/cps_ir/expected/basic_4.js
index 68f024f..8ce632a 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_4.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_4.js
@@ -3,15 +3,14 @@
 // main() { return foo(); }
 
 function() {
-  var line = "" + 42;
   if (typeof dartPrint == "function")
-    dartPrint(line);
+    dartPrint("42");
   else if (typeof console == "object" && typeof console.log != "undefined")
-    console.log(line);
+    console.log("42");
   else if (!(typeof window == "object")) {
     if (!(typeof print == "function"))
-      throw "Unable to print message: " + String(line);
-    print(line);
+      throw "Unable to print message: " + String("42");
+    print("42");
   }
   return 42;
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_9.js b/tests/compiler/dart2js/cps_ir/expected/basic_9.js
index b47ad6a..c23788a 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_9.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_9.js
@@ -5,14 +5,14 @@
 // }
 
 function() {
-  var res = "Instance of '" + H.Primitives_objectTypeName(V.C$()) + "'";
+  var line = "Instance of '" + H.Primitives_objectTypeName(V.C$()) + "'";
   if (typeof dartPrint == "function")
-    dartPrint(res);
+    dartPrint(line);
   else if (typeof console == "object" && typeof console.log != "undefined")
-    console.log(res);
+    console.log(line);
   else if (!(typeof window == "object")) {
     if (!(typeof print == "function"))
-      throw "Unable to print message: " + String(res);
-    print(res);
+      throw "Unable to print message: " + String(line);
+    print(line);
   }
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/closures_5.js b/tests/compiler/dart2js/cps_ir/expected/closures_5.js
index 959b14a..3c61ff5 100644
--- a/tests/compiler/dart2js/cps_ir/expected/closures_5.js
+++ b/tests/compiler/dart2js/cps_ir/expected/closures_5.js
@@ -7,7 +7,7 @@
 // }
 
 function() {
-  var _captured_x_0 = 122 + 1, line = _captured_x_0 === 0 ? 1 / _captured_x_0 < 0 ? "-0.0" : "" + _captured_x_0 : "" + _captured_x_0;
+  var line = H.S(122 + 1);
   if (typeof dartPrint == "function")
     dartPrint(line);
   else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/closures_7.js b/tests/compiler/dart2js/cps_ir/expected/closures_7.js
index 4a16c92..62f16ad 100644
--- a/tests/compiler/dart2js/cps_ir/expected/closures_7.js
+++ b/tests/compiler/dart2js/cps_ir/expected/closures_7.js
@@ -10,7 +10,7 @@
 // }
 
 function() {
-  var _captured_x_0 = 122 + 1, line = _captured_x_0 === 0 ? 1 / _captured_x_0 < 0 ? "-0.0" : "" + _captured_x_0 : "" + _captured_x_0;
+  var line = H.S(122 + 1);
   if (typeof dartPrint == "function")
     dartPrint(line);
   else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/codeUnitAt_1.js b/tests/compiler/dart2js/cps_ir/expected/codeUnitAt_1.js
index 92a1969..9043a3f 100644
--- a/tests/compiler/dart2js/cps_ir/expected/codeUnitAt_1.js
+++ b/tests/compiler/dart2js/cps_ir/expected/codeUnitAt_1.js
@@ -5,14 +5,13 @@
 // }
 
 function() {
-  var line = "" + 65;
   if (typeof dartPrint == "function")
-    dartPrint(line);
+    dartPrint("65");
   else if (typeof console == "object" && typeof console.log != "undefined")
-    console.log(line);
+    console.log("65");
   else if (!(typeof window == "object")) {
     if (!(typeof print == "function"))
-      throw "Unable to print message: " + String(line);
-    print(line);
+      throw "Unable to print message: " + String("65");
+    print("65");
   }
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/constructor_1.js b/tests/compiler/dart2js/cps_ir/expected/constructor_1.js
index 21493c2..6afa3a3 100644
--- a/tests/compiler/dart2js/cps_ir/expected/constructor_1.js
+++ b/tests/compiler/dart2js/cps_ir/expected/constructor_1.js
@@ -12,7 +12,7 @@
 // }
 
 function() {
-  var line = 1 === 0 ? 1 / 1 < 0 ? "-0.0" : "" + 1 : "" + 1;
+  var line = H.S(1);
   if (typeof dartPrint == "function")
     dartPrint(line);
   else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/constructor_11.js b/tests/compiler/dart2js/cps_ir/expected/constructor_11.js
index 9c0d6d0..3221867 100644
--- a/tests/compiler/dart2js/cps_ir/expected/constructor_11.js
+++ b/tests/compiler/dart2js/cps_ir/expected/constructor_11.js
@@ -9,7 +9,7 @@
 // }
 
 function() {
-  var line = 1 === 0 ? 1 / 1 < 0 ? "-0.0" : "" + 1 : "" + 1;
+  var line = H.S(1);
   if (typeof dartPrint == "function")
     dartPrint(line);
   else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/constructor_13.js b/tests/compiler/dart2js/cps_ir/expected/constructor_13.js
index 074cf69..a95670c 100644
--- a/tests/compiler/dart2js/cps_ir/expected/constructor_13.js
+++ b/tests/compiler/dart2js/cps_ir/expected/constructor_13.js
@@ -9,14 +9,14 @@
 // }
 
 function() {
-  var res = "Instance of '" + H.Primitives_objectTypeName(new V.Foo(5)) + "'";
+  var line = "Instance of '" + H.Primitives_objectTypeName(new V.Foo(5)) + "'";
   if (typeof dartPrint == "function")
-    dartPrint(res);
+    dartPrint(line);
   else if (typeof console == "object" && typeof console.log != "undefined")
-    console.log(res);
+    console.log(line);
   else if (!(typeof window == "object")) {
     if (!(typeof print == "function"))
-      throw "Unable to print message: " + String(res);
-    print(res);
+      throw "Unable to print message: " + String(line);
+    print(line);
   }
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/gvn_1.js b/tests/compiler/dart2js/cps_ir/expected/gvn_1.js
index 1307a74..5e14c5c 100644
--- a/tests/compiler/dart2js/cps_ir/expected/gvn_1.js
+++ b/tests/compiler/dart2js/cps_ir/expected/gvn_1.js
@@ -45,7 +45,7 @@
   for (; k < 10; sum += i + v0[v1], ++k)
     if (v1 < 0 || v1 >= 10)
       return H.ioore(v0, v1);
-  line = sum === 0 ? 1 / sum < 0 ? "-0.0" : "" + sum : "" + sum;
+  line = H.S(sum);
   if (typeof dartPrint == "function")
     dartPrint(line);
   else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/interceptors_1.js b/tests/compiler/dart2js/cps_ir/expected/interceptors_1.js
index ed58ff0..a8df9d1 100644
--- a/tests/compiler/dart2js/cps_ir/expected/interceptors_1.js
+++ b/tests/compiler/dart2js/cps_ir/expected/interceptors_1.js
@@ -7,14 +7,13 @@
 // }
 
 function() {
-  var line = "" + 4;
   if (typeof dartPrint == "function")
-    dartPrint(line);
+    dartPrint("4");
   else if (typeof console == "object" && typeof console.log != "undefined")
-    console.log(line);
+    console.log("4");
   else if (!(typeof window == "object")) {
     if (!(typeof print == "function"))
-      throw "Unable to print message: " + String(line);
-    print(line);
+      throw "Unable to print message: " + String("4");
+    print("4");
   }
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/operators_4.js b/tests/compiler/dart2js/cps_ir/expected/operators_4.js
index 837c082..65acae6 100644
--- a/tests/compiler/dart2js/cps_ir/expected/operators_4.js
+++ b/tests/compiler/dart2js/cps_ir/expected/operators_4.js
@@ -6,16 +6,12 @@
 function() {
   var v0 = $.x + 1, line;
   $.x = v0;
-  L0: {
-    if (v0 > 10) {
-      $.x = v0 = $.x + 1;
-      if (v0 > 10) {
-        line = "true";
-        break L0;
-      }
-    }
-    line = "false";
-  }
+  if (v0 > 10) {
+    $.x = v0 = $.x + 1;
+    v0 = v0 > 10;
+  } else
+    v0 = false;
+  line = H.S(v0);
   if (typeof dartPrint == "function")
     dartPrint(line);
   else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/operators_5.js b/tests/compiler/dart2js/cps_ir/expected/operators_5.js
index d2986cc..df02418 100644
--- a/tests/compiler/dart2js/cps_ir/expected/operators_5.js
+++ b/tests/compiler/dart2js/cps_ir/expected/operators_5.js
@@ -6,16 +6,13 @@
 function() {
   var v0 = $.x + 1, line;
   $.x = v0;
-  L0: {
-    if (!(v0 > 10)) {
-      $.x = v0 = $.x + 1;
-      if (!(v0 > 10)) {
-        line = "false";
-        break L0;
-      }
-    }
-    line = "true";
+  if (v0 > 10)
+    v0 = true;
+  else {
+    $.x = v0 = $.x + 1;
+    v0 = v0 > 10;
   }
+  line = H.S(v0);
   if (typeof dartPrint == "function")
     dartPrint(line);
   else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/operators_7.js b/tests/compiler/dart2js/cps_ir/expected/operators_7.js
index b81aaa9..9b278bf 100644
--- a/tests/compiler/dart2js/cps_ir/expected/operators_7.js
+++ b/tests/compiler/dart2js/cps_ir/expected/operators_7.js
@@ -10,15 +10,14 @@
 // }
 
 function() {
-  var line = "" + 6;
   V.Foo$();
   if (typeof dartPrint == "function")
-    dartPrint(line);
+    dartPrint("6");
   else if (typeof console == "object" && typeof console.log != "undefined")
-    console.log(line);
+    console.log("6");
   else if (!(typeof window == "object")) {
     if (!(typeof print == "function"))
-      throw "Unable to print message: " + String(line);
-    print(line);
+      throw "Unable to print message: " + String("6");
+    print("6");
   }
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/operators_8.js b/tests/compiler/dart2js/cps_ir/expected/operators_8.js
index 3f1c27e..908c5f3 100644
--- a/tests/compiler/dart2js/cps_ir/expected/operators_8.js
+++ b/tests/compiler/dart2js/cps_ir/expected/operators_8.js
@@ -6,16 +6,16 @@
 // }
 
 function() {
-  var list = [1, 2, 3], res;
+  var list = [1, 2, 3], line;
   list[1] = 6;
-  res = P.IterableBase_iterableToFullString(list, "[", "]");
+  line = H.S(list);
   if (typeof dartPrint == "function")
-    dartPrint(res);
+    dartPrint(line);
   else if (typeof console == "object" && typeof console.log != "undefined")
-    console.log(res);
+    console.log(line);
   else if (!(typeof window == "object")) {
     if (!(typeof print == "function"))
-      throw "Unable to print message: " + String(res);
-    print(res);
+      throw "Unable to print message: " + String(line);
+    print(line);
   }
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/optimize_indexers.js b/tests/compiler/dart2js/cps_ir/expected/optimize_indexers.js
index 21c1d71..1b8c351 100644
--- a/tests/compiler/dart2js/cps_ir/expected/optimize_indexers.js
+++ b/tests/compiler/dart2js/cps_ir/expected/optimize_indexers.js
@@ -5,13 +5,16 @@
 // // This example illustrates a case we wish to do better in terms of inlining and
 // // code generation.
 // //
-// // Today this function is compiled without inlining Wrapper.[], JSArray.[] and
-// // Wrapper.[]= because:
+// // Naively this function would be compiled without inlining Wrapper.[],
+// // JSArray.[] and Wrapper.[]= because:
 // // JSArray.[] is too big (14 nodes)
 // // Wrapper.[] is too big if we force inlining of JSArray (15 nodes)
 // // Wrapper.[]= is even bigger (46 nodes)
 // //
-// // See #25478 for ideas on how to make this better.
+// // We now do specialization of [] and []= by adding guards and injecting builtin
+// // operators. This made it possible to inline []. We still don't see []= inlined
+// // yet, that might require that we improve the inlining counting heuristics a
+// // bit.
 // @NoInline()
 // test(data, x) {
 //   data[x + 1] = data[x];
@@ -33,5 +36,8 @@
 // }
 
 function(data, x) {
-  data.$indexSet(0, J.$add$ns(x, 1), C.JSArray_methods.$index(data.arr, x));
+  var v0 = J.$add$ns(x, 1), v1 = data.arr;
+  if (x >>> 0 !== x || x >= v1.length)
+    return H.ioore(v1, x);
+  data.$indexSet(0, v0, v1[x]);
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/redundant_condition.js b/tests/compiler/dart2js/cps_ir/expected/redundant_condition.js
index a3a2ae0..211aec6 100644
--- a/tests/compiler/dart2js/cps_ir/expected/redundant_condition.js
+++ b/tests/compiler/dart2js/cps_ir/expected/redundant_condition.js
@@ -27,7 +27,7 @@
 
 function() {
   var a = V.nextNumber();
-  if (!(typeof a === "number" && Math.floor(a) === a))
+  if (typeof a !== "number" || Math.floor(a) !== a)
     throw H.wrapException("error 1");
   a += 5;
   V.action(a);
diff --git a/tests/compiler/dart2js/cps_ir/expected/supercall_3.js b/tests/compiler/dart2js/cps_ir/expected/supercall_3.js
index ffc1752..f45afaf 100644
--- a/tests/compiler/dart2js/cps_ir/expected/supercall_3.js
+++ b/tests/compiler/dart2js/cps_ir/expected/supercall_3.js
@@ -10,7 +10,7 @@
 // }
 
 function() {
-  var line = "" + (10 + V.Sub$().field);
+  var line = H.S(10 + V.Sub$().field);
   if (typeof dartPrint == "function")
     dartPrint(line);
   else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/input/optimize_indexers.dart b/tests/compiler/dart2js/cps_ir/input/optimize_indexers.dart
index 084bc34..8150653 100644
--- a/tests/compiler/dart2js/cps_ir/input/optimize_indexers.dart
+++ b/tests/compiler/dart2js/cps_ir/input/optimize_indexers.dart
@@ -4,13 +4,16 @@
 // This example illustrates a case we wish to do better in terms of inlining and
 // code generation.
 //
-// Today this function is compiled without inlining Wrapper.[], JSArray.[] and
-// Wrapper.[]= because:
+// Naively this function would be compiled without inlining Wrapper.[],
+// JSArray.[] and Wrapper.[]= because:
 // JSArray.[] is too big (14 nodes)
 // Wrapper.[] is too big if we force inlining of JSArray (15 nodes)
 // Wrapper.[]= is even bigger (46 nodes)
 //
-// See #25478 for ideas on how to make this better.
+// We now do specialization of [] and []= by adding guards and injecting builtin
+// operators. This made it possible to inline []. We still don't see []= inlined
+// yet, that might require that we improve the inlining counting heuristics a
+// bit.
 @NoInline()
 test(data, x) {
   data[x + 1] = data[x];
diff --git a/tests/compiler/dart2js/diagnostic_helper.dart b/tests/compiler/dart2js/diagnostic_helper.dart
index 26dac30..c9b19e1 100644
--- a/tests/compiler/dart2js/diagnostic_helper.dart
+++ b/tests/compiler/dart2js/diagnostic_helper.dart
@@ -25,7 +25,7 @@
   CollectedMessage(
       this.message, this.uri, this.begin, this.end, this.text, this.kind);
 
-  MessageKind get messageKind => message.kind;
+  MessageKind get messageKind => message?.kind;
 
   String toString() {
     return '${message != null ? message.kind : ''}'
diff --git a/tests/compiler/dart2js/message_span_test.dart b/tests/compiler/dart2js/message_span_test.dart
new file mode 100644
index 0000000..655b814
--- /dev/null
+++ b/tests/compiler/dart2js/message_span_test.dart
@@ -0,0 +1,182 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/diagnostics/messages.dart';
+import 'package:compiler/src/io/source_file.dart';
+import 'package:expect/expect.dart';
+import 'memory_compiler.dart';
+import 'memory_source_file_helper.dart';
+
+const List<Test> TESTS = const <Test>[
+  const Test('''
+class A { A(b); }
+class B extends A {
+  a() {}
+
+  lot() {}
+
+  of() {}
+
+  var members;
+}
+main() => new B();''',
+  const {
+    MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT: '''
+class B extends A {
+^^^^^^^^^^^^^^^^^'''}),
+
+  const Test('''
+class I {}
+class A { A(b); }
+class B extends A implements I {
+  a() {}
+
+  lot() {}
+
+  of() {}
+
+  var members;
+}
+main() => new B();''',
+  const {
+    MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT: '''
+class B extends A implements I {
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^'''}),
+
+  const Test('''
+class M<T> {}
+class A { A(b); }
+class B extends A with M<int> {
+  a() {}
+
+  lot() {}
+
+  of() {}
+
+  var members;
+}
+main() => new B();''',
+  const {
+    MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT: '''
+class B extends A with M<int> {
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^'''}),
+
+  const Test('''
+class A { A(b); }
+class B
+    extends A {
+  a() {}
+
+  lot() {}
+
+  of() {}
+
+  var members;
+}
+main() => new B();''',
+  const {
+    MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT: '''
+class B
+    extends A {
+'''}),
+
+  const Test('''
+void foo(int a) {
+  // a
+  // non-empty
+  // body
+}
+main() => foo('');''',
+  const {
+    MessageKind.THIS_IS_THE_METHOD: '''
+void foo(int a) {
+^^^^^^^^^^^^^^^'''}),
+
+  const Test('''
+void foo(int a,
+         int b) {
+  // a
+  // non-empty
+  // body
+}
+main() => foo('', 0);''',
+  const {
+    MessageKind.THIS_IS_THE_METHOD: '''
+void foo(int a,
+         int b) {
+'''}),
+
+  const Test('''
+class A {
+  int foo() {
+    // a
+    // non-empty
+    // body
+  }
+}
+class B extends A {
+  int get foo {
+    // a
+    // non-empty
+    // body
+    return 0;
+  }
+}
+main() => new B();''',
+  const {
+    MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER: '''
+  int get foo {
+  ^^^^^^^^^^^''',
+    MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER_CONT: '''
+  int foo() {
+  ^^^^^^^^^'''}),
+];
+
+class Test {
+  final String code;
+  final Map<MessageKind, String> kindToSpan;
+
+  const Test(this.code, this.kindToSpan);
+}
+
+const String MARKER = '---marker---';
+
+main() {
+  asyncTest(() async {
+    var cachedCompiler;
+    for (Test test in TESTS) {
+      DiagnosticCollector collector = new DiagnosticCollector();
+      CompilationResult result = await runCompiler(
+          memorySourceFiles: {'main.dart': test.code},
+          options: [Flags.analyzeOnly],
+          diagnosticHandler: collector,
+          cachedCompiler: cachedCompiler);
+      cachedCompiler = result.compiler;
+      MemorySourceFileProvider provider = cachedCompiler.provider;
+      Map<MessageKind, String> kindToSpan =
+          new Map<MessageKind, String>.from(test.kindToSpan);
+      for (CollectedMessage message in collector.messages) {
+        String expectedSpanText = kindToSpan[message.messageKind];
+        if (expectedSpanText != null) {
+          SourceFile sourceFile = provider.getSourceFile(message.uri);
+          String locationMessage =
+              sourceFile.getLocationMessage(MARKER, message.begin, message.end);
+          // Remove `filename:line:column:` and message.
+          String strippedLocationMessage = locationMessage.substring(
+              locationMessage.indexOf(MARKER) + MARKER.length + 1);
+          Expect.equals(expectedSpanText, strippedLocationMessage,
+              "Unexpected span for ${message.messageKind} in\n${test.code}"
+              "\nExpected:${expectedSpanText.codeUnits}"
+              "\nActual  :${strippedLocationMessage.codeUnits}");
+          kindToSpan.remove(message.messageKind);
+        }
+      }
+      kindToSpan.forEach((MessageKind kind, _) {
+        Expect.fail("Missing message kin $kind in\n${test.code}");
+      });
+    }
+  });
+}
\ No newline at end of file
diff --git a/tests/compiler/dart2js/type_variable_bound_test.dart b/tests/compiler/dart2js/type_variable_bound_test.dart
index d8a6903..544d664 100644
--- a/tests/compiler/dart2js/type_variable_bound_test.dart
+++ b/tests/compiler/dart2js/type_variable_bound_test.dart
@@ -17,141 +17,136 @@
   });
 }
 
-test(String source, {var errors, var warnings}) {
+Future test(String source, {var errors, var warnings}) async{
   if (errors == null) errors = [];
   if (errors is! List) errors = [errors];
   if (warnings == null) warnings = [];
   if (warnings is! List) warnings = [warnings];
-  asyncTest(() => compile(source).then((compiler) {
-    DiagnosticCollector collector = compiler.diagnosticCollector;
-    Expect.equals(!errors.isEmpty, compiler.compilationFailed);
-    Expect.equals(errors.length, collector.errors.length,
-                  'unexpected error count: ${collector.errors.length} '
-                  'expected ${errors.length}');
-    Expect.equals(warnings.length, collector.warnings.length,
-                  'unexpected warning count: ${collector.warnings.length} '
-                  'expected ${warnings.length}');
+  var compiler = await compile(source);
+  DiagnosticCollector collector = compiler.diagnosticCollector;
+  Expect.equals(!errors.isEmpty, compiler.compilationFailed);
+  Expect.equals(errors.length, collector.errors.length,
+                'unexpected error count: ${collector.errors.length} '
+                'expected ${errors.length}');
+  Expect.equals(warnings.length, collector.warnings.length,
+                'unexpected warning count: ${collector.warnings.length} '
+                'expected ${warnings.length}');
 
-    for (int i = 0 ; i < errors.length ; i++) {
-      Expect.equals(errors[i], collector.errors.elementAt(i).message.kind);
-    }
-    for (int i = 0 ; i < warnings.length ; i++) {
-      Expect.equals(warnings[i], collector.warnings.elementAt(i).message.kind);
-    }
-  }));
+  for (int i = 0 ; i < errors.length ; i++) {
+    Expect.equals(errors[i], collector.errors.elementAt(i).message.kind);
+  }
+  for (int i = 0 ; i < warnings.length ; i++) {
+    Expect.equals(warnings[i], collector.warnings.elementAt(i).message.kind);
+  }
 }
 
-test1() {
-  asyncTest(() => compile(r"""
+Future test1() async {
+  var compiler = await compile(r"""
 class A<T extends T> {}
 
 void main() {
   new A();
 }
-""").then((compiler) {
-    DiagnosticCollector collector = compiler.diagnosticCollector;
-    Expect.isFalse(compiler.compilationFailed);
-    Expect.isTrue(collector.errors.isEmpty,
-                  'unexpected errors: ${collector.errors}');
-    Expect.equals(1, collector.warnings.length,
-                  'expected exactly one warning, but got ${collector.warnings}');
+""");
+  DiagnosticCollector collector = compiler.diagnosticCollector;
+  Expect.isFalse(compiler.compilationFailed);
+  Expect.isTrue(collector.errors.isEmpty,
+                'unexpected errors: ${collector.errors}');
+  Expect.equals(1, collector.warnings.length,
+                'expected exactly one warning, but got ${collector.warnings}');
 
-    print(collector.warnings.elementAt(0));
-    Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
-                  collector.warnings.elementAt(0).message.kind);
-    Expect.equals("T",
-        collector.warnings.elementAt(0).message.arguments['typeVariableName']);
-  }));
+  print(collector.warnings.elementAt(0));
+  Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
+                collector.warnings.elementAt(0).message.kind);
+  Expect.equals("T",
+      collector.warnings.elementAt(0).message.arguments['typeVariableName']);
 }
 
-test2() {
-  asyncTest(() => compile(r"""
+Future test2() async {
+  var compiler = await compile(r"""
 class B<T extends S, S extends T> {}
 
 void main() {
   new B();
 }
-""").then((compiler) {
-    DiagnosticCollector collector = compiler.diagnosticCollector;
-    Expect.isFalse(compiler.compilationFailed);
-    print(collector.errors);
-    Expect.isTrue(collector.errors.isEmpty, 'unexpected errors');
-    Expect.equals(2, collector.warnings.length,
-                  'expected exactly two errors, but got ${collector.warnings}');
+""");
+  DiagnosticCollector collector = compiler.diagnosticCollector;
+  Expect.isFalse(compiler.compilationFailed);
+  print(collector.errors);
+  Expect.isTrue(collector.errors.isEmpty, 'unexpected errors');
+  Expect.equals(2, collector.warnings.length,
+                'expected exactly two errors, but got ${collector.warnings}');
 
-    Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
-                  collector.warnings.elementAt(0).message.kind);
-    Expect.equals("T",
-        collector.warnings.elementAt(0).message.arguments['typeVariableName']);
+  Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
+                collector.warnings.elementAt(0).message.kind);
+  Expect.equals("T",
+      collector.warnings.elementAt(0).message.arguments['typeVariableName']);
 
-    Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
-                  collector.warnings.elementAt(1).message.kind);
-    Expect.equals("S",
-        collector.warnings.elementAt(1).message.arguments['typeVariableName']);
-  }));
+  Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
+                collector.warnings.elementAt(1).message.kind);
+  Expect.equals("S",
+      collector.warnings.elementAt(1).message.arguments['typeVariableName']);
 }
 
-test3() {
-  asyncTest(() => compile(r"""
+Future test3() async {
+  var compiler = await compile(r"""
 class C<T extends S, S extends U, U extends T> {}
 
 void main() {
   new C();
 }
-""").then((compiler) {
-    DiagnosticCollector collector = compiler.diagnosticCollector;
-    Expect.isFalse(compiler.compilationFailed);
-    print(collector.errors);
-    Expect.isTrue(collector.errors.isEmpty, 'unexpected errors');
-    Expect.equals(3, collector.warnings.length,
-                  'expected exactly one error, but got ${collector.warnings}');
+""");
+  DiagnosticCollector collector = compiler.diagnosticCollector;
+  Expect.isFalse(compiler.compilationFailed);
+  print(collector.errors);
+  Expect.isTrue(collector.errors.isEmpty, 'unexpected errors');
+  Expect.equals(3, collector.warnings.length,
+                'expected exactly one error, but got ${collector.warnings}');
 
-    Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
-                  collector.warnings.elementAt(0).message.kind);
-    Expect.equals("T",
-        collector.warnings.elementAt(0).message.arguments['typeVariableName']);
+  Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
+                collector.warnings.elementAt(0).message.kind);
+  Expect.equals("T",
+      collector.warnings.elementAt(0).message.arguments['typeVariableName']);
 
-    Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
-                  collector.warnings.elementAt(1).message.kind);
-    Expect.equals("S",
-        collector.warnings.elementAt(1).message.arguments['typeVariableName']);
+  Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
+                collector.warnings.elementAt(1).message.kind);
+  Expect.equals("S",
+      collector.warnings.elementAt(1).message.arguments['typeVariableName']);
 
-    Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
-                  collector.warnings.elementAt(2).message.kind);
-    Expect.equals("U",
-        collector.warnings.elementAt(2).message.arguments['typeVariableName']);
-  }));
+  Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
+                collector.warnings.elementAt(2).message.kind);
+  Expect.equals("U",
+      collector.warnings.elementAt(2).message.arguments['typeVariableName']);
 }
 
-test4() {
-  asyncTest(() => compile(r"""
+Future test4() async {
+  var compiler = await compile(r"""
 class D<T extends S, S extends U, U extends S> {}
 
 void main() {
   new D();
 }
-""").then((compiler) {
-    DiagnosticCollector collector = compiler.diagnosticCollector;
-    Expect.isFalse(compiler.compilationFailed);
-    print(collector.errors);
-    Expect.isTrue(collector.errors.isEmpty, 'unexpected errors');
-    Expect.equals(2, collector.warnings.length,
-                  'expected exactly one error, but got ${collector.warnings}');
+""");
+  DiagnosticCollector collector = compiler.diagnosticCollector;
+  Expect.isFalse(compiler.compilationFailed);
+  print(collector.errors);
+  Expect.isTrue(collector.errors.isEmpty, 'unexpected errors');
+  Expect.equals(2, collector.warnings.length,
+                'expected exactly one error, but got ${collector.warnings}');
 
-    Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
-                  collector.warnings.elementAt(0).message.kind);
-    Expect.equals("S",
-        collector.warnings.elementAt(0).message.arguments['typeVariableName']);
+  Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
+                collector.warnings.elementAt(0).message.kind);
+  Expect.equals("S",
+      collector.warnings.elementAt(0).message.arguments['typeVariableName']);
 
-    Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
-                  collector.warnings.elementAt(1).message.kind);
-    Expect.equals("U",
-        collector.warnings.elementAt(1).message.arguments['typeVariableName']);
-  }));
+  Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
+                collector.warnings.elementAt(1).message.kind);
+  Expect.equals("U",
+      collector.warnings.elementAt(1).message.arguments['typeVariableName']);
 }
 
-test5() {
-  test(r"""
+Future test5() {
+  return test(r"""
 class A<T extends num> {}
 
 void main() {
@@ -164,8 +159,8 @@
 """);
 }
 
-test6() {
-  test(r"""
+Future test6() {
+  return test(r"""
 class A<T extends num> {}
 
 void main() {
@@ -174,8 +169,8 @@
 """, warnings: MessageKind.INVALID_TYPE_VARIABLE_BOUND);
 }
 
-test7() {
-  test(r"""
+Future test7() {
+  return test(r"""
 class A<T extends num> {}
 class B<T> extends A<T> {} // Warning produced here.
 
@@ -186,8 +181,8 @@
 """, warnings: MessageKind.INVALID_TYPE_VARIABLE_BOUND);
 }
 
-test8() {
-  test(r"""
+Future test8() {
+  return test(r"""
 class B<T extends B<T>> {}
 class C<T extends B<T>> extends B<T> {}
 class D<T extends C<T>> extends C<T> {}
@@ -213,8 +208,8 @@
 """);
 }
 
-test9() {
-  test(r"""
+Future test9() {
+  return test(r"""
 class B<T extends B<T>> {}
 class C<T extends B<T>> extends B<T> {}
 class D<T extends C<T>> extends C<T> {}
@@ -229,8 +224,8 @@
                 MessageKind.INVALID_TYPE_VARIABLE_BOUND]);
 }
 
-test10() {
-  test(r"""
+Future test10() {
+  return test(r"""
 class A {
   const A();
 }
@@ -246,8 +241,8 @@
 
 // TODO(het): The error is reported twice because both the Dart and JS constant
 // compilers are run on the const constructor, investigate why.
-test11() {
-  test(r"""
+Future test11() {
+  return test(r"""
 class A {
   const A();
 }
@@ -265,15 +260,17 @@
 }
 
 main() {
-  test1();
-  test2();
-  test3();
-  test4();
-  test5();
-  test6();
-  test7();
-  test8();
-  test9();
-  test10();
-  test11();
+  asyncTest(() async {
+    await test1();
+    await test2();
+    await test3();
+    await test4();
+    await test5();
+    await test6();
+    await test7();
+    await test8();
+    await test9();
+    await test10();
+    await test11();
+  });
 }
diff --git a/tests/compiler/dart2js_native/dart2js_native.status b/tests/compiler/dart2js_native/dart2js_native.status
index dfe56d3..3a172de 100644
--- a/tests/compiler/dart2js_native/dart2js_native.status
+++ b/tests/compiler/dart2js_native/dart2js_native.status
@@ -21,6 +21,7 @@
 compute_this_script_test: Skip # Issue 17458
 
 [ $compiler == dart2js && $cps_ir ]
+foreign_test: RuntimeError # Expect.equals(expected: <1234567891011>, actual: <1234567891011>) fails.
 native_exception_test: RuntimeError # Issue 24421
 optimization_hints_test: RuntimeError # Please triage this failure.
 subclassing_constructor_2_test: RuntimeError # Please triage this failure.
diff --git a/tests/html/html.status b/tests/html/html.status
index 8a8dae6..eaf77bd 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -18,6 +18,11 @@
 native_gc_test: Skip # Dartium JSInterop failure
 transferables_test: RuntimeError # Dartium JSInterop failure
 
+blob_constructor_test: RuntimeError # Dartium 45 roll. Issue 25754
+crypto_test/functional: RuntimeError # Dartium 45 roll. Issue 25754
+svgelement_test/constructors: RuntimeError # Dartium 45 roll. Issue 25754
+url_test: RuntimeError # Dartium 45 roll. Issue 25754
+
 [ $compiler == none && ($runtime == drt || $runtime == dartium ) ]
 worker_api_test: Fail # Issue 10223
 resource_http_test: Fail # Issue 24203
@@ -29,6 +34,7 @@
 [ $compiler == dart2js ]
 input_element_test/attributes: Fail # Issue 21555
 wrapping_collections_test: SkipByDesign # Testing an issue that is only relevant to Dartium
+js_typed_interop_default_arg_test/default_value: MissingCompileTimeError # Issue #25759
 
 [ $compiler == dart2js && $checked ]
 js_function_getter_trust_types_test: Skip # --trust-type-annotations incompatible with --checked
@@ -121,6 +127,9 @@
 
 [$runtime == drt || $runtime == dartium || $runtime == chrome || $runtime == chromeOnAndroid || $runtime == ContentShellOnAndroid ]
 webgl_1_test: Pass, Fail # Issue 8219
+element_animate_test/omit_timing: RuntimeError # Dartium 45 roll. Issue 25786
+element_animate_test/simple_timing: RuntimeError # Dartium 45 roll. Issue 25786
+element_animate_test/timing_dict: RuntimeError # Dartium 45 roll. Issue 25786
 
 [ $compiler == none && ($runtime == drt || $runtime == dartium) && $system == windows ]
 websql_test: Skip # Issue 4941: stderr contains a backtrace.
@@ -380,19 +389,20 @@
 
 [ $compiler == dart2js && $csp && ($runtime == drt || $runtime == safari || $runtime == ff || $runtime == chrome || $runtime == chromeOnAndroid) ]
 # Note: these tests are all injecting scripts by design.  This is not allowed under CSP.
-event_customevent_test: Fail        # Test cannot run under CSP restrictions.
-js_interop_1_test: Skip             # Test cannot run under CSP restrictions (times out).
-js_test: Skip                       # Test cannot run under CSP restrictions (times out).
-js_array_test: Skip                 # Test cannot run under CSP restrictions.
-js_typed_interop_test: Skip         # Test cannot run under CSP restrictions.
-js_function_getter_test: Skip       # Test cannot run under CSP restrictions.
-js_function_getter_trust_types_test: Skip  # Test cannot run under CSP restrictions.
-js_dart_to_string_test: Skip        # Test cannot run under CSP restrictions.
-mirrors_js_typed_interop_test: Skip # Test cannot run under CSP restrictions.
-postmessage_structured_test: Skip   # Test cannot run under CSP restrictions (times out).
+event_customevent_test: SkipByDesign
+js_interop_1_test: SkipByDesign
+js_test: SkipByDesign
+js_array_test: SkipByDesign
+js_typed_interop_test: SkipByDesign
+js_typed_interop_default_arg_test: SkipByDesign
+js_function_getter_test: SkipByDesign
+js_function_getter_trust_types_test: SkipByDesign
+js_dart_to_string_test: SkipByDesign
+mirrors_js_typed_interop_test: SkipByDesign
+postmessage_structured_test: SkipByDesign
 
-[ $compiler == dart2js &&  $runtime == chrome]
-svgelement_test/supported_altGlyph: RuntimeError # Issue 23144
+[ $compiler == dart2js &&  ($runtime == chrome || $runtime == drt) ]
+svgelement_test/supported_altGlyph: RuntimeError # Issue 25787
 
 [ ($runtime == dartium) && ($system == macos || $system == windows || $system == linux)]
 # Desktop operating systems do not support touch events on chrome 34 dartium.
@@ -420,9 +430,7 @@
 typing_test: StaticWarning
 webgl_1_test: StaticWarning
 window_nosuchmethod_test: StaticWarning
-
-[ $compiler == dart2js && $cps_ir ]
-resource_http_test: Crash # (await for(var b in r.openRead()){bytes.addAll(b);}): await for
+js_typed_interop_default_arg_test/default_value: MissingCompileTimeError # Issue #25759
 
 [ $compiler == dart2js && $cps_ir && $browser ]
 # Custom element support:
@@ -436,20 +444,9 @@
 custom_elements_test/innerHtml: RuntimeError # Need custom element support #25484
 custom_elements_test/register: RuntimeError # Need custom element support #25484
 
-# New js-interop support via package:js is only implemented in SSA:
-js_array_test: RuntimeError # Need package:js support #24978
-js_dart_to_string_test: RuntimeError # Need package:js support #24978
-js_function_getter_test/call: RuntimeError # Need package:js support #24978
-js_function_getter_test: RuntimeError # Need package:js support #24978
-js_function_getter_trust_types_test: RuntimeError # Need package:js support #24978
-js_typed_interop_anonymous2_exp_test: RuntimeError # Need package:js support #24978
-js_typed_interop_anonymous2_test: RuntimeError # Need package:js support #24978
-js_typed_interop_anonymous_exp_test: RuntimeError # Need package:js support #24978
-js_typed_interop_anonymous_test: RuntimeError # Need package:js support #24978
-js_typed_interop_side_cast_exp_test: RuntimeError # Need package:js support #24978
-js_typed_interop_side_cast_test: RuntimeError # Need package:js support #24978
-js_typed_interop_test: RuntimeError # Need package:js support #24978
-mirrors_js_typed_interop_test: RuntimeError # Need package:js support #24978
+js_typed_interop_side_cast_exp_test: RuntimeError # Corner case in package:js that we might want to remove (See comment in #24978).
+js_typed_interop_test/static_method_tearoff_1: RuntimeError # Tree-shaking a used tear-off (#24978, #25720).
+js_typed_interop_default_arg_test/explicit_argument: RuntimeError # Tree-shaking a used tear-off (#24978, #25720).
 
 # These are raw dart:js tests that fail due to bugs in the CPS IR:
 js_test/Dart_functions: RuntimeError # Tree-shaking an escaping closure #25720
diff --git a/tests/html/js_typed_interop_default_arg_test.dart b/tests/html/js_typed_interop_default_arg_test.dart
new file mode 100644
index 0000000..69a0756
--- /dev/null
+++ b/tests/html/js_typed_interop_default_arg_test.dart
@@ -0,0 +1,58 @@
+// 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.
+
+@JS()
+library js_typed_interop_test;
+
+import 'dart:html';
+
+import 'package:expect/expect.dart' show NoInline;
+import 'package:js/js.dart';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+
+_injectJs() {
+  document.body.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+  var Foo = {
+    get42: function(b) { return arguments.length >= 1 ? b : 42; },
+    get43: function(b) { return arguments.length >= 1 ? b : 43; }
+  };
+""");
+}
+
+@JS()
+class Foo {
+  // Note: it's invalid to provide a default value.
+  external static num get42([num b
+      = 3  /// default_value: compile-time error
+  ]);
+  external static num get43([num b]);
+}
+
+main() {
+  _injectJs();
+  useHtmlConfiguration();
+
+  test('call directly from dart', () {
+    expect(Foo.get42(2), 2);
+    expect(Foo.get42(), 42);
+  });
+
+  test('call tearoff from dart with arg', () {
+    var f = Foo.get42;
+    expect(f(2), 2); /// explicit_argument: ok
+  });
+
+  test('call tearoff from dart with default', () {
+    var f = Foo.get42;
+    // Note: today both SSA and CPS remove the extra argument on static calls,
+    // but they fail to do so on tearoffs.
+    expect(f(), 3); /// default_value: continued
+
+    f = Foo.get43;
+    expect(f(), 43);
+  });
+}
diff --git a/tests/html/js_typed_interop_test.dart b/tests/html/js_typed_interop_test.dart
index 14d931f..431d533 100644
--- a/tests/html/js_typed_interop_test.dart
+++ b/tests/html/js_typed_interop_test.dart
@@ -124,6 +124,7 @@
   external callClosureWithArg1(Function closure, arg1);
   external callClosureWithArg2(Function closure, arg1, arg2);
   external Bar getBar();
+
   external static num multiplyDefault2(num a, [num b]);
 }
 
@@ -277,14 +278,26 @@
     });
   });
 
-  group('static method', () {
-    test('call from dart', () {
+  group('static_method_call', () {
+    test('call directly from dart', () {
       expect(Foo.multiplyDefault2(6, 7), equals(42));
       expect(Foo.multiplyDefault2(6), equals(12));
+    });
+  });
+
+  // Note: these extra groups are added to be able to mark each test
+  // individually in status files. This should be split as separate test files.
+  group('static_method_tearoff_1', () {
+    test('call tearoff from dart', () {
       MultiplyWithDefault tearOffMethod = Foo.multiplyDefault2;
       expect(tearOffMethod(6, 6), equals(36));
+    });
+  });
+
+  group('static_method_tearoff_2', () {
+    test('call tearoff from dart', () {
+      MultiplyWithDefault tearOffMethod = Foo.multiplyDefault2;
       expect(tearOffMethod(6), equals(12));
-      Function untypedTearOff = Foo.multiplyDefault2;
     });
   });
 
diff --git a/tests/isolate/timer_isolate_test.dart b/tests/isolate/timer_isolate_test.dart
index 7513dad..cb8fcbb 100644
--- a/tests/isolate/timer_isolate_test.dart
+++ b/tests/isolate/timer_isolate_test.dart
@@ -23,18 +23,16 @@
 
 main() {
   test("timer in isolate", () {
-    int startTime;
-    int endTime;
-
+    Stopwatch stopwatch = new Stopwatch();
     ReceivePort port = new ReceivePort();
 
     port.first.then(expectAsync((msg) {
       expect("timer_fired", msg);
-      int endTime = (new DateTime.now()).millisecondsSinceEpoch;
-      expect(endTime - startTime + safetyMargin, greaterThanOrEqualTo(TIMEOUT.inMilliseconds));
+      expect(stopwatch.elapsedMilliseconds + safetyMargin,
+             greaterThanOrEqualTo(TIMEOUT.inMilliseconds));
     }));
 
-    startTime = (new DateTime.now()).millisecondsSinceEpoch;
+    stopwatch.start();
     var remote = Isolate.spawn(createTimer, port.sendPort);
   });
 }
diff --git a/tests/language/async_star_no_cancel2_test.dart b/tests/language/async_star_no_cancel2_test.dart
new file mode 100644
index 0000000..fcc82ac
--- /dev/null
+++ b/tests/language/async_star_no_cancel2_test.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+var events = [];
+
+var timer;
+ticker(period) async* {
+  var sc;
+  sc = new StreamController(onListen: () {
+    events.add("listen");
+    timer = new Timer.periodic(period, (_) {
+      sc.add(null);
+    });
+  }, onCancel: () {
+    events.add("cancel");
+    timer.cancel();
+  });
+
+  try {
+    var counter = 0;
+    await for (var tick in sc.stream) {
+      counter++;
+    }
+  } finally {
+    events.add("finally");
+  }
+}
+
+void main() {
+  asyncStart();
+  events.add("main");
+  final subscription =
+      ticker(const Duration(milliseconds: 20)).listen((val) { });
+
+  bool cancelFinished = false;
+  new Timer(const Duration(milliseconds: 100), () async {
+    // Despite the cancel call below, the stream doesn't stop.
+    // The async* function is not blocked at any await (since the inner timer
+    // continuously ticks), but since there/ is no yield-point in the function
+    // it won't cancel.
+    new Timer(const Duration(milliseconds: 30), () {
+      Expect.isFalse(cancelFinished);
+      Expect.listEquals(["main", "listen", "invoke cancel"], events);
+      timer.cancel();
+      asyncEnd();
+    });
+
+    events.add("invoke cancel");
+    await subscription.cancel();
+    // This line should never be reached, since the cancel-future doesn't
+    // complete.
+    cancelFinished = true;
+  });
+}
diff --git a/tests/language/async_star_no_cancel_test.dart b/tests/language/async_star_no_cancel_test.dart
new file mode 100644
index 0000000..82cbe22
--- /dev/null
+++ b/tests/language/async_star_no_cancel_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+var events = [];
+
+ticker() async* {
+  var sc;
+  var sentTickCount = 0;
+  sc = new StreamController(onListen: () {
+    events.add("listen");
+  }, onCancel: () {
+    events.add("cancel");
+  });
+
+  try {
+    var counter = 0;
+    await for (var tick in sc.stream) {
+      counter++;
+    }
+  } finally {
+    events.add("finally");
+  }
+}
+
+void main() {
+  asyncStart();
+  events.add("main");
+  final subscription = ticker().listen((val) { });
+
+  bool cancelFinished = false;
+  // Cancel the subscription.
+  // The async* function is blocked on an `await` (the inner stream) and won't
+  // be able to complete.
+  Timer.run(() {
+    events.add("invoke cancel");
+    subscription.cancel().then((_) => cancelFinished = true);
+  });
+
+  new Timer(const Duration(milliseconds: 100), () {
+    Expect.isFalse(cancelFinished);
+    Expect.listEquals(["main", "listen", "invoke cancel"], events);
+    asyncEnd();
+  });
+}
diff --git a/tests/language/for_in3_test.dart b/tests/language/for_in3_test.dart
new file mode 100644
index 0000000..75ee485
--- /dev/null
+++ b/tests/language/for_in3_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Dart test for testing that strings aren't iterable.
+
+main() {
+  Expect.throws(() {
+    var chars = [];
+    for (var c in "foo") chars.add(c);
+  }, (e) => e is NoSuchMethodError);
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index 5ba9267..2d38d62 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -55,8 +55,6 @@
 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
-issue_25671a_test/01: Skip # RuntimeError (Issue 25671, Issue 25737)
-issue_25671b_test/01: Skip # RuntimeError (Issue 25671, Issue 25737)
 
 [ ($compiler == none || $compiler == precompiler) && $checked ]
 type_variable_bounds4_test/01: Fail # Issue 14006
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 03ae9f9..060a61d 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -34,8 +34,6 @@
 library_env_test/has_no_io_support: RuntimeError, OK
 library_env_test/has_no_mirror_support: RuntimeError, OK
 
-accessor_conflict_export2_test: Crash # Issue 25626
-accessor_conflict_export_test: Crash # Issue 25626
 accessor_conflict_import2_test: RuntimeError # Issue 25626
 accessor_conflict_import_prefixed2_test: RuntimeError # Issue 25626
 accessor_conflict_import_prefixed_test: RuntimeError # Issue 25626
@@ -44,6 +42,8 @@
 [ $compiler == dart2js && $runtime == jsshell ]
 await_for_test: Skip # Jsshell does not provide periodic timers, Issue 7728
 async_star_test: RuntimeError # Jsshell does not provide non-zero timers, Issue 7728
+async_star_no_cancel_test: RuntimeError # Need triage
+async_star_no_cancel2_test: RuntimeError # Need triage
 
 [ $compiler == dart2js && $browser ]
 config_import_test: Fail # Test flag is not passed to the compiler.
@@ -238,6 +238,8 @@
 regress_22443_test: Pass,RuntimeError # Issue 17458
 
 [ $compiler == dart2js && $cps_ir == false ]
+accessor_conflict_export2_test: Crash # Issue 25626
+accessor_conflict_export_test: Crash # Issue 25626
 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
@@ -249,37 +251,33 @@
 issue23244_test: RuntimeError # 23244
 
 [ $compiler == dart2js && $cps_ir ]
+accessor_conflict_export_test: CompileTimeError # Issue 25747
+accessor_conflict_export2_test: CompileTimeError # Issue 25747
 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
 async_await_syntax_test/a09a: Crash # (a09a()async*{yield 0;}): cannot handle sync*/async* functions
 async_await_syntax_test/a10a: Crash # (a10a()async*{yield* [] ;}): cannot handle sync*/async* functions
 async_await_syntax_test/a11d: Crash # (get async async*{}): cannot handle sync*/async* functions
 async_await_syntax_test/b03a: Crash # (b03a()async*{}): cannot handle sync*/async* functions
-async_await_syntax_test/b06a: Crash # (await for(var o in st){}): await for
 async_await_syntax_test/b09a: Crash # (b09a()async*{yield 0;}): cannot handle sync*/async* functions
 async_await_syntax_test/b10a: Crash # (b10a()async*{yield* [] ;}): cannot handle sync*/async* functions
 async_await_syntax_test/b11d: Crash # (get async async*{}): cannot handle sync*/async* functions
 async_await_syntax_test/c03a: Crash # (c03a()async*{}): cannot handle sync*/async* functions
-async_await_syntax_test/c06a: Crash # (await for(var o in st){}): await for
 async_await_syntax_test/c09a: Crash # (c09a()async*{yield 0;}): cannot handle sync*/async* functions
 async_await_syntax_test/c10a: Crash # (c10a()async*{yield* [] ;}): cannot handle sync*/async* functions
 async_await_syntax_test/d03a: Crash # (()async*{}): cannot handle sync*/async* functions
-async_await_syntax_test/d06a: Crash # (await for(var o in st){}): await for
 async_await_syntax_test/d09a: Crash # (()async*{yield 0;}): cannot handle sync*/async* functions
 async_await_syntax_test/d10a: Crash # (()async*{yield* [] ;}): cannot handle sync*/async* functions
-async_await_test/02: Crash # bailout: (await for
-async_await_test/03: Crash # bailout: (await for
-async_await_test/none: Crash # bailout: (await for
 async_or_generator_return_type_stacktrace_test/02: Crash # (void badReturnTypeAsyncStar()async*{}): cannot handle sync*/async* functions
 async_return_types_test/nestedFuture: Crash #  cannot handle sync*/async* functions
 async_return_types_test/none: Crash # cannot handle sync*/async* functions
 async_return_types_test/tooManyTypeParameters: Crash # cannot handle sync*/async* functions
 async_return_types_test/wrongReturnType: Crash # cannot handle sync*/async* functions
 async_return_types_test/wrongTypeParameter: Crash # cannot handle sync*/async* functions
-async_star_await_pauses_test: Crash # (await for(var i in ...  await for
 async_star_cancel_and_throw_in_finally_test: Crash # (foo()async*{try {in...  cannot handle sync*/async* functions
 async_star_cancel_while_paused_test: Crash # (f()async*{list.add(...  cannot handle sync*/async* functions
+async_star_no_cancel_test: Crash # (foo()async*{try {in...  cannot handle sync*/async* functions
+async_star_no_cancel2_test: Crash # (foo()async*{try {in...  cannot handle sync*/async* functions
 async_star_regression_2238_test: Crash # (f()async*{label1:label2:yield 0;}): cannot handle sync*/async* functions
 async_star_regression_23116_test: Crash # (Stream<int> foo(Com...  cannot handle sync*/async* functions
 async_star_regression_fisk_test: Crash # (fisk()async*{res.ad...  cannot handle sync*/async* functions
@@ -290,11 +288,7 @@
 asyncstar_throw_in_catch_test: Crash # (foo4(Tracer tracer)...  cannot handle sync*/async* functions
 asyncstar_yield_test: Crash # (Stream<int> foo4()a...  cannot handle sync*/async* functions
 asyncstar_yieldstar_test: Crash # (foo2(Stream subStream)async*{yield* subStream;}): cannot handle sync*/async* functions
-await_for_cancel_test: Crash # (await for(var x in controller.stream){for(int j=0;j<10;j++ ){if(j==5)continue outer;}}): await for
-await_for_test: Crash # (await for(var x in infiniteStream()){i++ ;if(i>10)break;t4.record(x);}): await for
-await_for_use_local_test: Crash # (await for(var v in s){accum+= v;}): await for
 call_closurization_test: RuntimeError # Bad type inference for ".call" tear-off.
-deferred_super_dependency_test/01: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
 field3a_negative_test: Fail # Bogus result from type inference in case of invalid program.
 gc_test: Crash # Internal Error: Pending statics (see above).
 if_null_assignment_static_test/29: Crash # Pending statics: JSArray
@@ -303,10 +297,10 @@
 if_null_assignment_static_test/33: Crash # Pending statics: JSArray
 if_null_assignment_static_test/35: Crash # Pending statics: JSArray
 invocation_mirror_test: Crash # (super[37]=42): visitUnresolvedSuperIndexSet
-regress_23500_test/01: Crash # (await for(var c in new Stream.fromIterable([] )){}): await for
-savannah_test: RuntimeError # Success depends on the variable hints.
+many_calls_test: Crash # Internal Error: Pending statics (see above).
+mixin_bound_test: RuntimeError # TypeError: Cannot read property 'toString$0' of undefined
 super_call4_test: RuntimeError # Please triage this failure.
-super_getter_setter_test: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
+super_getter_setter_test: RuntimeError # Expect.equals(expected: <42>, actual: <null>) fails.
 super_operator_index5_test: Crash # (super[0]=42): visitUnresolvedSuperIndexSet
 super_operator_index7_test: Crash # (super[0]=42): visitUnresolvedSuperIndexSet
 super_operator_index8_test: Crash # (super[f()]=g()): visitUnresolvedSuperIndexSet
diff --git a/tests/language/regress_25550_test.dart b/tests/language/regress_25550_test.dart
new file mode 100644
index 0000000..4a8a7c5
--- /dev/null
+++ b/tests/language/regress_25550_test.dart
@@ -0,0 +1,17 @@
+// 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.
+
+typedef int Adder(int a, int b);
+
+class Mock {
+  noSuchMethod(i) => null;
+}
+
+class MockAdder extends Mock {
+  int call(int a, int b);
+}
+
+main() {
+  Adder adder = new MockAdder();
+}
diff --git a/tests/lib/async/stream_view_test.dart b/tests/lib/async/stream_view_test.dart
new file mode 100644
index 0000000..5b8308a
--- /dev/null
+++ b/tests/lib/async/stream_view_test.dart
@@ -0,0 +1,37 @@
+// 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.
+
+// Tests the StreamView class.
+
+import "package:expect/expect.dart";
+import "dart:async";
+import "package:async_helper/async_helper.dart";
+
+main() {
+  asyncStart();
+  runTest().whenComplete(asyncEnd);
+}
+
+Future runTest() async {
+  unreachable([a,b]) { throw "UNREACHABLE"; }
+  int tick = 0;
+  ticker() { tick++; }
+
+  asyncStart();
+
+  // Is const constructor.
+  Stream<int> s = const StreamView<int>(const Stream<int>.empty());
+
+  Expect.isFalse(s is Stream<String>);  // Respects type parameter.
+  StreamSubscription<int> sub =
+     s.listen(unreachable, onError: unreachable, onDone: ticker);
+  Expect.isFalse(sub is StreamSubscription<String>);  // Type parameter in sub.
+
+  Stream iterableStream = new Stream.fromIterable([1, 2, 3]);
+  Expect.listEquals([1, 2, 3], await iterableStream.toList());
+
+  asyncEnd();
+}
+
+Future flushMicrotasks() => new Future.delayed(Duration.ZERO);
diff --git a/tests/lib/async/timer_repeat_test.dart b/tests/lib/async/timer_repeat_test.dart
index e963c5a..1ed5139 100644
--- a/tests/lib/async/timer_repeat_test.dart
+++ b/tests/lib/async/timer_repeat_test.dart
@@ -11,16 +11,24 @@
 const int ITERATIONS = 5;
 
 Timer timer;
-int startTime;
+Stopwatch stopwatch = new Stopwatch();
 int iteration;
 
+// Some browsers (Firefox and IE so far) can trigger too early. Add a safety
+// margin. We use identical(1, 1.0) as an easy way to know if the test is
+// compiled by dart2js.
+int get safetyMargin => identical(1, 1.0) ? 100 : 0;
+
 void timeoutHandler(Timer timer) {
-  int endTime = (new DateTime.now()).millisecondsSinceEpoch;
   iteration++;
-  if (iteration < ITERATIONS) {
-    startTime = (new DateTime.now()).millisecondsSinceEpoch;
-  } else {
-    expect(iteration, ITERATIONS);
+  expect(iteration, lessThanOrEqualTo(ITERATIONS));
+  if (iteration == ITERATIONS) {
+    // When we are done with all of the iterations, we expect a
+    // certain amount of time to have passed.  Checking the time on
+    // each iteration doesn't work because the timeoutHandler runs
+    // concurrently with the periodic timer.
+    expect(stopwatch.elapsedMilliseconds + safetyMargin,
+           greaterThanOrEqualTo(ITERATIONS * TIMEOUT.inMilliseconds));
     timer.cancel();
   }
 }
@@ -28,7 +36,7 @@
 main() {
   test("timer_repeat", () {
     iteration = 0;
-    startTime = new DateTime.now().millisecondsSinceEpoch;
+    stopwatch.start();
     timer = new Timer.periodic(TIMEOUT,
         expectAsync(timeoutHandler, count: ITERATIONS));
   });
diff --git a/tests/lib/async/timer_test.dart b/tests/lib/async/timer_test.dart
index fc7ee87..d08754b 100644
--- a/tests/lib/async/timer_test.dart
+++ b/tests/lib/async/timer_test.dart
@@ -11,7 +11,7 @@
 const int DECREASE = 200;
 const int ITERATIONS = 5;
 
-int startTime;
+Stopwatch stopwatch = new Stopwatch();
 int timeout;
 int iteration;
 
@@ -21,13 +21,13 @@
 int get safetyMargin => identical(1, 1.0) ? 100 : 0;
 
 void timeoutHandler() {
-  int endTime = (new DateTime.now()).millisecondsSinceEpoch;
-  expect(endTime - startTime + safetyMargin, greaterThanOrEqualTo(timeout));
+  expect(stopwatch.elapsedMilliseconds + safetyMargin,
+         greaterThanOrEqualTo(timeout));
   if (iteration < ITERATIONS) {
     iteration++;
     timeout = timeout - DECREASE;
     Duration duration = new Duration(milliseconds: timeout);
-    startTime = (new DateTime.now()).millisecondsSinceEpoch;
+    stopwatch.reset();
     new Timer(duration, expectAsync(timeoutHandler));
   }
 }
@@ -37,7 +37,7 @@
     iteration = 0;
     timeout = STARTTIMEOUT;
     Duration duration = new Duration(milliseconds: timeout);
-    startTime = (new DateTime.now()).millisecondsSinceEpoch;
+    stopwatch.start();
     new Timer(duration, expectAsync(timeoutHandler));
   });
 }
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 317880e..3bd73ed 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -188,6 +188,12 @@
 [ ($runtime == vm || $runtime == dart_precompiled) ]
 js/*: Skip
 
+# 'js' tests import the dart:js library, so they only make sense in
+# a browser environment.
+[ $runtime == dart_product ]
+js/*: SkipByDesign
+mirrors/*: SkipByDesign
+
 [ $compiler == dart2js && $minified ]
 mirrors/mirrors_used_get_name_test: RuntimeError
 mirrors/mirrors_used_get_name2_test: RuntimeError
diff --git a/tests/standalone/assert_assignable_canon_test.dart b/tests/standalone/assert_assignable_canon_test.dart
new file mode 100644
index 0000000..7c34328
--- /dev/null
+++ b/tests/standalone/assert_assignable_canon_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// VMOptions=--enable-inlining-annotations --optimization-counter-threshold=10 --no-background-compilation
+
+const AlwaysInline = "AlwaysInline";
+const NeverInline = "NeverInline";
+
+abstract class A<T extends A<T>> {
+  @AlwaysInline
+  f(x) => new R<T>(x);
+}
+
+class B extends A<B> {}
+
+class R<T> {
+  @AlwaysInline
+  R(T field);
+}
+
+class C extends B {}
+
+class D extends C {}
+
+// f will be inlined and T=B will be forwarded to AssertAssignable in the
+// R. However B will be wrapped in the TypeRef which breaks runtime TypeCheck
+// function (Instance::IsInstanceOf does not work for TypeRefs).
+@NeverInline
+f(o) => new B().f(o);
+
+main() {
+  final o = new D();
+  for (var i = 0; i < 10; i++) {
+    f(o);
+  }
+}
diff --git a/tests/standalone/fields_may_be_reset_test.dart b/tests/standalone/fields_may_be_reset_test.dart
new file mode 100644
index 0000000..3ab6fc6
--- /dev/null
+++ b/tests/standalone/fields_may_be_reset_test.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--fields_may_be_reset
+
+main() {
+  print("Okay");
+}
diff --git a/tests/standalone/full_coverage_test.dart b/tests/standalone/full_coverage_test.dart
index 98495b1..e719d42 100644
--- a/tests/standalone/full_coverage_test.dart
+++ b/tests/standalone/full_coverage_test.dart
@@ -17,6 +17,9 @@
     Platform.script.resolve('../../tools/full-coverage.dart').toFilePath();
 final String packageRoot = Platform.packageRoot;
 final List dartBaseArgs = ['--package-root=${packageRoot}', '--checked',];
+final Stopwatch sw = new Stopwatch();
+
+int elapsed() => sw.elapsedMilliseconds;
 
 // With line numbers starting at 0, the list of hits can be understood as
 // follows:
@@ -88,13 +91,14 @@
 
 generateCoverage(String workingDirectory) {
   for (var coverageProg in coverageTests) {
+    print('[+${elapsed()}ms] Generating data for ${coverageProg["name"]}');
     var progPath = path.join(workingDirectory, coverageProg['name']);
     var script = path.join(progPath, "${coverageProg['name']}.dart");
     var dartArgs = new List.from(dartBaseArgs)
       ..addAll(['--coverage-dir=${progPath}', '${script}']);
     var result = Process.runSync(Platform.executable, dartArgs);
     if (result.exitCode != 0) {
-      print("Coverage generator returned exitCode: ${result.exitCode}.");
+      print("[+${elapsed()}ms] Got exitCode: ${result.exitCode}.");
       print("stderr:\n${result.stderr}\n");
       expect(result.exitCode, 0);
     }
@@ -212,6 +216,7 @@
 
 main() {
   String testingDirectory;
+  sw.start();
 
   setUp(() {
     testingDirectory = prepareEnv();
@@ -220,20 +225,23 @@
   tearDown(() => destroyEnv(testingDirectory));
 
   test('CoverageTests', () {
-    print('Generating coverage data...');
+    print('[+${elapsed()}ms] Generating coverage data...');
     generateCoverage(testingDirectory);
-    print('Done Generating coverage data.');
+    print('[+${elapsed()}ms] Done Generating coverage data.');
 
-    print('Running tests...');
+    print('[+${elapsed()}ms] Running tests...');
     coverageTests.forEach((cTest) {
       String programDir = path.join(testingDirectory, cTest['name']);
       String programPath = path.join(programDir, "${cTest['name']}.dart");
+      print('[+${elapsed()}ms] Testing lcov for ${cTest["name"]}');
       testCoverage(programDir, programPath,
                    new LcovDescriptor(programPath),
                    new List.from(cTest['expectedHits']));
+      print('[+${elapsed()}ms] Testing pretty print for ${cTest["name"]}');
       testCoverage(programDir, programPath,
                    new PrettyPrintDescriptor(programPath),
                    new List.from(cTest['expectedHits']));
     });
+    print('[+${elapsed()}ms] Done.');
   });
 }
diff --git a/tests/standalone/io/certificates/client1.p12 b/tests/standalone/io/certificates/client1.p12
new file mode 100644
index 0000000..0b51218
--- /dev/null
+++ b/tests/standalone/io/certificates/client1.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/client1_key.p12 b/tests/standalone/io/certificates/client1_key.p12
new file mode 100644
index 0000000..a65c398
--- /dev/null
+++ b/tests/standalone/io/certificates/client1_key.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/client1_key_malformed.pem b/tests/standalone/io/certificates/client1_key_malformed.pem
new file mode 100644
index 0000000..33a79bf
--- /dev/null
+++ b/tests/standalone/io/certificates/client1_key_malformed.pem
@@ -0,0 +1,18 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE4jAcBgoqhkiG9w0BDAEBMA4ECF4ZB27y60SWAgIIAASCBMCEL3ZCzfC0q+m+
+B8gM9jQe1JFRD5reAuwK6+3speBS4KE+wjbcyQq09/5UoQu3Dci1WG1nKLB1u0Bk
+w9NuRahWCpvVLzz/GQ6Psesixq3V69zD3N6iMl/XQKymQBwGK51xIkeJO+6Skh2d
++qoyBHINTlKY9+548Zgqu+Z3mI3pGmdhd7hCiamiffDwCLEqRxbXdZdLpC9GpAP5
+HOqXHzN2aZbAGHb1GkHVxskSNzAwlEEZhh4Ibe6o7U65hoL9borewT+gj6sQohI5
+/LHL0P2bVvtRZiwBVPUX8HZWuVYIFb6GEGTTqOofNhNHvHaKUlD8Uxi5/h/Xi8fq
+xpdkjIn7VXj9e+I3TkfiphDtk0+Q+f+UkuPyuzU1PafinPfRK1J6gk+ZqAQHW/sp
+g6GVr2r4PkOrBPsA6jmCnQhs2C4MlZyR2p65qjVutdkKU5NgftW+giK9shgglcza
+38RF8i01THOnD3j+2teM/t/Ziqb2PGWv/bmvhcYqt1aG186Pe3bBCxhh/L7bqNKD
+q7sxDmaDE2pTkfyvh07udarmBQc5gvfXYqwghbqP/n7wizqjeEJgAwwHyi8LLsFV
+XreBQ/8Z2gQwXurrh5WD+7KSgvgopW/oVC8a3++8Hmf5Nkj27lACzoDWTG2/Swah
+O1MmdtPyy/KCbf5ujt2BlXM9D206Rsr6hoO9UZ1s1ohRdJReVGc4NZ4XrVWc4TKT
+gUAFTaHIKgFe/DgLaQn8L8Pqb8B/JfoSgQ74r69S434Kc+EDKui8wnkgso5bqrr1
+M07H9Xo+OtG1D6rma2EUlpoU06CAIcyqNx5fHJ3xfk9GHScQi4U6vEDCAQTNTS65
+I5AOHthZ2kZzfXvP6TF39S5D37NrV7/WJu7ZFaJx3bUGwnS2HYTwjFPABHpVLMwJ
+nBylVJs+h7bCZdBNCWgTytcn1mYMCvXVmrW8VTwBRjUQsy4rgE2wjpZuIM9rx+gZ
+HtNvy5t2RlOSqVKapyvV0ll7qbT1lwGIePxjttiWmNbgbwRBQzjv6FZ1Yo331Fl4
diff --git a/tests/standalone/io/certificates/client_authority.p12 b/tests/standalone/io/certificates/client_authority.p12
new file mode 100644
index 0000000..a873b2a
--- /dev/null
+++ b/tests/standalone/io/certificates/client_authority.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/client_authority_malformed.pem b/tests/standalone/io/certificates/client_authority_malformed.pem
new file mode 100644
index 0000000..d206dce3
--- /dev/null
+++ b/tests/standalone/io/certificates/client_authority_malformed.pem
@@ -0,0 +1,9 @@
+-----BEGIN CERTIFICATE-----
+MIIDKjCCAhKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9jbGll
+bnRhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1WjAaMRgw
+FgYDVQQDEw9jbGllbnRhdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCi6wJAs6nppNmTZ3e/wE9l0pAmkMtDONwB9o115XXTG3rmSKfZOxa8
+TFjSn818Pr1OYb9fPdI1Y6x4WY9PELUtQyEBlNcKjwg96vhrP4p2DhqbWsI5nASH
+DSjJsM75bQ7D7qHYzriuAl0Fk1C4LcodRj+5wmErMtvGJG0x06qFbxCCMAJ2kC+h
+SneTN955/YHSXADgxjFlt3s1T0QPnqrr+G7Ro6PrVKLPBulglq7wAeTwrGkPRUt0
+3lDGOSi6i97NbpiXwrGp5XiLUtVCiID6Ro0xKWH4sjJ4JnVjIUG8CQWERc6sFDJM
diff --git a/tests/standalone/io/certificates/server_chain.p12 b/tests/standalone/io/certificates/server_chain.p12
new file mode 100644
index 0000000..c9416eb
--- /dev/null
+++ b/tests/standalone/io/certificates/server_chain.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/server_chain_malformed1.pem b/tests/standalone/io/certificates/server_chain_malformed1.pem
new file mode 100644
index 0000000..cbbeb55
--- /dev/null
+++ b/tests/standalone/io/certificates/server_chain_malformed1.pem
@@ -0,0 +1,7 @@
+-----BEGIN CERTIFICATE-----
+MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
+cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1
+WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCkg/Qr8RQeLTOSgCkyiEX2ztgkgscX8hKGHEHdvlkmVK3JVEIIwkvu
+/Y9LtHZUia3nPAgqEEbexzTENZjSCcC0V6I2XW/e5tIE3rO0KLZyhtZhN/2SfJ6p
+KbOh0HLr1VtkKJGp1tzUmHW/aZI32pK60ZJ/N917NLPCJpCaL8+wHo3+w3oNqln6
diff --git a/tests/standalone/io/certificates/server_chain_malformed2.pem b/tests/standalone/io/certificates/server_chain_malformed2.pem
new file mode 100644
index 0000000..2c99e78
--- /dev/null
+++ b/tests/standalone/io/certificates/server_chain_malformed2.pem
@@ -0,0 +1,42 @@
+-----BEGIN CERTIFICATE-----
+MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
+cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1
+WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCkg/Qr8RQeLTOSgCkyiEX2ztgkgscX8hKGHEHdvlkmVK3JVEIIwkvu
+/Y9LtHZUia3nPAgqEEbexzTENZjSCcC0V6I2XW/e5tIE3rO0KLZyhtZhN/2SfJ6p
+KbOh0HLr1VtkKJGp1tzUmHW/aZI32pK60ZJ/N917NLPCJpCaL8+wHo3+w3oNqln6
+oJsfgxy9SUM8Bsc9WMYKMUdqLO1QKs1A5YwqZuO7Mwj+4LY2QDixC7Ua7V9YAPo2
+1SBeLvMCHbYxSPCuxcZ/kDkgax/DF9u7aZnGhMImkwBka0OQFvpfjKtTIuoobTpe
+PAG7MQYXk4RjnjdyEX/9XAQzvNo1CDObAgMBAAGjgbQwgbEwPAYDVR0RBDUwM4IJ
+bG9jYWxob3N0ggkxMjcuMC4wLjGCAzo6MYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAA
+ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSvhJo6taTggJQBukEvMo/PDk8tKTAf
+BgNVHSMEGDAWgBS98L4T5RaIToE3DkBRsoeWPil0eDAOBgNVHQ8BAf8EBAMCA6gw
+EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAHLOt0mL2S4A
+B7vN7KsfQeGlVgZUVlEjem6kqBh4fIzl4CsQuOO8oJ0FlO1z5JAIo98hZinymJx1
+phBVpyGIKakT/etMH0op5evLe9dD36VA3IM/FEv5ibk35iGnPokiJXIAcdHd1zam
+YaTHRAnZET5S03+7BgRTKoRuszhbvuFz/vKXaIAnVNOF4Gf2NUJ/Ax7ssJtRkN+5
+UVxe8TZVxzgiRv1uF6NTr+J8PDepkHCbJ6zEQNudcFKAuC56DN1vUe06gRDrNbVq
+2JHEh4pRfMpdsPCrS5YHBjVq/XHtFHgwDR6g0WTwSUJvDeM4OPQY5f61FB0JbFza
+PkLkXmoIod8=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDLjCCAhagAwIBAgIBAjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNVoXDTI1MTAyNDEwMjYzNVowIDEeMBwG
+A1UEAwwVaW50ZXJtZWRpYXRlYXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA6GndRFiXk+2q+Ig7ZOWKKGta+is8137qyXz+eVFs5sA0ajMN
+ZBAMWS0TIXw/Yks+y6fEcV/tfv91k1eUN4YXPcoxTdDF97d2hO9wxumeYOMnQeDy
+VZVDKQBZ+jFMeI+VkNpMEdmsLErpZDGob/1dC8tLEuR6RuRR8X6IDGMPOCMw1jLK
+V1bQjPtzqKadTscfjLuKxuLgspJdTrzsu6hdcl1mm8K6CjTY2HNXWxs1yYmwfuQ2
+Z4/8sOMNqFqLjN+ChD7pksTMq7IosqGiJzi2bpd5f44ek/k822Y0ATncJHk4h1Z+
+kZBnW6kgcLna1gDri9heRwSZ+M8T8nlHgIMZIQIDAQABo3sweTASBgNVHRMBAf8E
+CDAGAQH/AgEAMB0GA1UdDgQWBBS98L4T5RaIToE3DkBRsoeWPil0eDAfBgNVHSME
+GDAWgBRxD5DQHTmtpDFKDOiMf5FAi6vfbzAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
+BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAD+4KpUeV5mUPw5IG/7w
+eOXnUpeS96XFGuS1JuFo/TbgntPWSPyo+rD4GrPIkUXyoHaMCDd2UBEjyGbBIKlB
+NZA3RJOAEp7DTkLNK4RFn/OEcLwG0J5brL7kaLRO4vwvItVIdZ2XIqzypRQTc0MG
+MmF08zycnSlaN01ryM67AsMhwdHqVa+uXQPo8R8sdFGnZ33yywTYD73FeImXilQ2
+rDnFUVqmrW1fjl0Fi4rV5XI0EQiPrzKvRtmF8ZqjGATPOsRd64cwQX6V+P5hNeIR
+9pba6td7AbNGausHfacRYMyoGJWWWkFPd+7jWOCPqW7Fk1tmBgdB8GzXa3inWIRM
+RUE=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/server_key.p12 b/tests/standalone/io/certificates/server_key.p12
new file mode 100644
index 0000000..8b59c9b
--- /dev/null
+++ b/tests/standalone/io/certificates/server_key.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/trusted_certs.p12 b/tests/standalone/io/certificates/trusted_certs.p12
new file mode 100644
index 0000000..71ffe1b
--- /dev/null
+++ b/tests/standalone/io/certificates/trusted_certs.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/trusted_certs_malformed.pem b/tests/standalone/io/certificates/trusted_certs_malformed.pem
new file mode 100644
index 0000000..ea26cc7
--- /dev/null
+++ b/tests/standalone/io/certificates/trusted_certs_malformed.pem
@@ -0,0 +1,8 @@
+-----BEGIN CERTIFICATE-----
+MIIC+zCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNFoXDTI1MTAyNDEwMjYzNFowGDEWMBQG
+A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMl+dcraUM/E7E6zl7+7hK9oUJYXJLnfiMtP/TRFVbH4+2aEN8vXzPbzKdR3
+FfaHczXQTwnTCaYA4u4uSDvSOsFFEfxEwYORsdKmQEM8nGpVX2NVvKsMcGIhh8kh
+ZwJfkMIOcAxmGIHGdMhF8VghonJ8uGiuqktxdfpARq0g3fqIjDHsF9/LpfshUfk9
+wsRyTF0yr90U/dsfnE+u8l7GvVl8j2Zegp0sagAGtLaNv7tP17AibqEGg2yDBrBN
diff --git a/tests/standalone/io/secure_server_client_certificate_test.dart b/tests/standalone/io/secure_server_client_certificate_test.dart
index 0ba4103..97bbc4f 100644
--- a/tests/standalone/io/secure_server_client_certificate_test.dart
+++ b/tests/standalone/io/secure_server_client_certificate_test.dart
@@ -12,26 +12,32 @@
 
 String localFile(path) => Platform.script.resolve(path).toFilePath();
 
-SecurityContext serverContext = new SecurityContext()
-  ..useCertificateChainSync(localFile('certificates/server_chain.pem'))
-  ..usePrivateKeySync(localFile('certificates/server_key.pem'),
+SecurityContext serverContext(String certType) => new SecurityContext()
+  ..useCertificateChainSync(localFile('certificates/server_chain.$certType'))
+  ..usePrivateKeySync(localFile('certificates/server_key.$certType'),
                       password: 'dartdart')
-  ..setTrustedCertificatesSync(localFile('certificates/client_authority.pem'))
-  ..setClientAuthoritiesSync(localFile('certificates/client_authority.pem'));
+  ..setTrustedCertificatesSync(localFile(
+      'certificates/client_authority.$certType'))
+  ..setClientAuthoritiesSync(localFile(
+      'certificates/client_authority.$certType'));
 
-SecurityContext clientCertContext = new SecurityContext()
-  ..setTrustedCertificatesSync(localFile('certificates/trusted_certs.pem'))
-  ..useCertificateChainSync(localFile('certificates/client1.pem'))
-  ..usePrivateKeySync(localFile('certificates/client1_key.pem'),
+SecurityContext clientCertContext(String certType) => new SecurityContext()
+  ..setTrustedCertificatesSync(localFile(
+      'certificates/trusted_certs.$certType'))
+  ..useCertificateChainSync(localFile('certificates/client1.$certType'))
+  ..usePrivateKeySync(localFile('certificates/client1_key.$certType'),
                                 password: 'dartdart');
 
-SecurityContext clientNoCertContext = new SecurityContext()
-  ..setTrustedCertificatesSync(localFile('certificates/trusted_certs.pem'));
+SecurityContext clientNoCertContext(String certType) => new SecurityContext()
+  ..setTrustedCertificatesSync(localFile(
+      'certificates/trusted_certs.$certType'));
 
-Future testClientCertificate({bool required, bool sendCert}) async {
-  var server = await SecureServerSocket.bind(HOST, 0, serverContext,
+Future testClientCertificate(
+    {bool required, bool sendCert, String certType}) async {
+  var server = await SecureServerSocket.bind(HOST, 0, serverContext(certType),
       requestClientCertificate: true, requireClientCertificate: required);
-  var clientContext = sendCert ? clientCertContext : clientNoCertContext;
+  var clientContext =
+      sendCert ? clientCertContext(certType) : clientNoCertContext(certType);
   var clientEndFuture =
       SecureSocket.connect(HOST, server.port, context: clientContext);
   if (required && !sendCert) {
@@ -68,9 +74,16 @@
 main() async {
   asyncStart();
   HOST = (await InternetAddress.lookup("localhost")).first;
-  await testClientCertificate(required: false, sendCert: true);
-  await testClientCertificate(required: true, sendCert: true);
-  await testClientCertificate(required: false, sendCert: false);
-  await testClientCertificate(required: true, sendCert: false);
+  await testClientCertificate(required: false, sendCert: true, certType: 'pem');
+  await testClientCertificate(required: true, sendCert: true, certType: 'pem');
+  await testClientCertificate(
+      required: false, sendCert: false, certType: 'pem');
+  await testClientCertificate(required: true, sendCert: false, certType: 'pem');
+
+  await testClientCertificate(required: false, sendCert: true, certType: 'p12');
+  await testClientCertificate(required: true, sendCert: true, certType: 'p12');
+  await testClientCertificate(
+      required: false, sendCert: false, certType: 'p12');
+  await testClientCertificate(required: true, sendCert: false, certType: 'p12');
   asyncEnd();
 }
diff --git a/tests/standalone/io/secure_socket_test.dart b/tests/standalone/io/secure_socket_test.dart
index 443e90b..dbd7271 100644
--- a/tests/standalone/io/secure_socket_test.dart
+++ b/tests/standalone/io/secure_socket_test.dart
@@ -7,6 +7,7 @@
 // VMOptions=--short_socket_write
 // VMOptions=--short_socket_read --short_socket_write
 
+import "package:async_helper/async_helper.dart";
 import "package:expect/expect.dart";
 import "package:path/path.dart";
 import "dart:async";
@@ -14,19 +15,20 @@
 
 String localFile(path) => Platform.script.resolve(path).toFilePath();
 
-SecurityContext serverContext = new SecurityContext()
-  ..useCertificateChainSync(localFile('certificates/server_chain.pem'))
-  ..usePrivateKeySync(localFile('certificates/server_key.pem'),
+SecurityContext serverContext(String certType) => new SecurityContext()
+  ..useCertificateChainSync(localFile('certificates/server_chain.$certType'))
+  ..usePrivateKeySync(localFile('certificates/server_key.$certType'),
                       password: 'dartdart');
 
-SecurityContext clientContext = new SecurityContext()
-  ..setTrustedCertificatesSync(localFile('certificates/trusted_certs.pem'));
+SecurityContext clientContext(String certType) => new SecurityContext()
+  ..setTrustedCertificatesSync(localFile(
+      'certificates/trusted_certs.$certType'));
 
-Future<HttpServer> startServer() {
+Future<HttpServer> startServer(String certType) {
   return HttpServer.bindSecure(
       "localhost",
       0,
-      serverContext,
+      serverContext(certType),
       backlog: 5).then((server) {
     server.listen((HttpRequest request) {
       request.listen(
@@ -43,10 +45,11 @@
   });
 }
 
-void main() {
+Future test(String certType) {
   List<int> body = <int>[];
-  startServer().then((server) {
-    SecureSocket.connect("localhost", server.port, context: clientContext)
+  startServer(certType).then((server) {
+    SecureSocket.connect(
+        "localhost", server.port, context: clientContext(certType))
     .then((socket) {
       socket.write("GET / HTTP/1.0\r\nHost: localhost\r\n\r\n");
       socket.close();
@@ -68,3 +71,10 @@
     });
   });
 }
+
+main() async {
+  asyncStart();
+  await test('pem');
+  await test('p12');
+  asyncEnd();
+}
diff --git a/tests/standalone/io/security_context_argument_test.dart b/tests/standalone/io/security_context_argument_test.dart
index 60577b2..91de8dc 100644
--- a/tests/standalone/io/security_context_argument_test.dart
+++ b/tests/standalone/io/security_context_argument_test.dart
@@ -34,6 +34,32 @@
     Expect.throws(() => c.usePrivateKeySync(
         localFile('certificates/server_key.pem'), password: 3),
         argumentOrTypeError);
+
+    // Empty data.
+    Expect.throws(() => c.usePrivateKeyBytes([], password: 'dartdart'),
+        tlsException);
+    Expect.throws(() => c.setTrustedCertificatesBytes([]), tlsException);
+    Expect.throws(() => c.useCertificateChainBytes([]), tlsException);
+    Expect.throws(() => c.setClientAuthoritiesBytes([]), argumentError);
+
+    // Malformed PEM certs.
+    Expect.throws(() => c.usePrivateKeySync(
+        localFile('certificates/client1_key_malformed.pem'),
+        password: "dartdart"),
+        tlsException);
+    Expect.throws(() => c.setTrustedCertificatesSync(
+        localFile('certificates/trusted_certs_malformed.pem')),
+        tlsException);
+    Expect.throws(() => c.useCertificateChainSync(
+        localFile('certificates/server_chain_malformed1.pem')),
+        tlsException);
+    Expect.throws(() => c.useCertificateChainSync(
+        localFile('certificates/server_chain_malformed2.pem')),
+        tlsException);
+    Expect.throws(() => c.setClientAuthoritiesSync(
+        localFile('certificates/client_authority_malformed.pem')),
+        argumentError);
+
     c.usePrivateKeySync(
         localFile('certificates/server_key.pem'), password: "dartdart");
 }
diff --git a/tests/standalone/io/sleep_test.dart b/tests/standalone/io/sleep_test.dart
index 795de81..91c6625 100644
--- a/tests/standalone/io/sleep_test.dart
+++ b/tests/standalone/io/sleep_test.dart
@@ -2,15 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import "package:expect/expect.dart";
 import "dart:io";
+import "package:unittest/unittest.dart";
 
 test(int milliseconds) {
   var watch = new Stopwatch();
   watch.start();
   sleep(new Duration(milliseconds: milliseconds));
   watch.stop();
-  Expect.isTrue(watch.elapsedMilliseconds + 1 >= milliseconds);
+  expect(watch.elapsedMilliseconds, greaterThanOrEqualTo(milliseconds));
 }
 
 main() {
@@ -18,6 +18,12 @@
   test(1);
   test(10);
   test(100);
-  Expect.throws(() => sleep(new Duration(milliseconds: -1)),
-                (e) => e is ArgumentError);
+  bool sawError = false;
+  try {
+    sleep(new Duration(milliseconds: -1));
+    expect(false, isTrue);  // should not reach here.
+  } on ArgumentError catch(e) {
+    sawError = true;
+  }
+  expect(sawError, isTrue);
 }
diff --git a/tests/standalone/javascript_compatibility_errors_test.dart b/tests/standalone/javascript_compatibility_errors_test.dart
deleted file mode 100644
index 6404a2e..0000000
--- a/tests/standalone/javascript_compatibility_errors_test.dart
+++ /dev/null
@@ -1,183 +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.
-
-// VMOptions=--warn_on_javascript_compatibility --warning_as_error --optimization_counter_threshold=5
-
-import "package:expect/expect.dart";
-
-f(x, y) {
-  // Unoptimized and optimized code.
-  1 is double;  /// 00: ok
-  if (1 is double) { x++; }  /// 01: ok
-  try { 1 as double; } on CastError catch (e) { }  /// 02: ok
-  try { var y = 1 as double; } on CastError catch (e) { }  /// 03: ok
-  1.0 is int;  /// 04: ok
-  if (1.0 is int) { x++; }  /// 05: ok
-  try { 1.0 as int; } on CastError catch (e) { }  /// 06: ok
-  try { var z = 1.0 as int; } on CastError catch (e) { }  /// 07: ok
-
-  x is double;  /// 10: ok
-  if (x is double) { }  /// 11: ok
-  try { x as double; } on CastError catch (e) { }  /// 12: ok
-  try { var z = x as double; } on CastError catch (e) { }  /// 13: ok
-  y is int;  /// 14: ok
-  if (y is int) { }  /// 15: ok
-  try { y as int; } on CastError catch (e) { }  /// 16: ok
-  try { var z = y as int; } on CastError catch (e) { }  /// 17: ok
-
-  // It is a compile-time error if evaluation of a constant object results in
-  // an uncaught exception being thrown, a JavascriptCompatibilityError here.
-  "${1.0}";  /// 20: compile-time error
-  var z = "${1.0}";  /// 21: compile-time error
-
-  (1.0).toString();  /// 22: ok
-  var z = (1.0).toString();  /// 23: ok
-  "$y";  /// 24: ok
-  var z = "$y";  /// 25: ok
-  y.toString();  /// 26: ok
-  var z = y.toString();  /// 27: ok
-
-  var a = "yz";
-  var b = "xyz";
-  b = b.substring(1);
-  if (identical(a, b)) { }  /// 28: ok
-
-  if (identical(x, y)) { }  /// 29: ok
-  if (identical(y, x)) { }  /// 30: ok
-
-  if (x > 10) {
-    // Optimized code.
-    x is double;  /// 40: ok
-    if (x is double) { }  /// 41: ok
-    try { x as double; } on CastError catch (e) { }  /// 42: ok
-    try { var z = x as double; } on CastError catch (e) { }  /// 43: ok
-    y is int;  /// 44: ok
-    if (y is int) { }  /// 45: ok
-    try { y as int; } on CastError catch (e) { }  /// 46: ok
-    try { var z = y as int; } on CastError catch (e) { }  /// 47: ok
-
-    "${1.0}";  /// 50: compile-time error
-    var z = "${1.0}";  /// 51: compile-time error
-
-    (1.0).toString();  /// 52: ok
-    var z = (1.0).toString();  /// 53: ok
-    "$y";  /// 54: ok
-    var z = "$y";  /// 55: ok
-    y.toString();  /// 56: ok
-    var z = y.toString();  /// 57: ok
-
-    var a = "yz";
-    var b = "xyz";
-    b = b.substring(1);
-    if (identical(a, b)) { }  /// 58: ok
-
-    if (identical(x, y)) { }  /// 59: ok
-    if (identical(y, x)) { }  /// 60: ok
-  }
-}
-
-k(x, y) {
-  // Unoptimized and optimized code.
-  1.5 is double;
-  if (1.5 is double) { x++; }
-  try { 1.5 as double; } on CastError catch (e) { }
-  try { var y = 1.5 as double; } on CastError catch (e) { }
-  1.5 is int;
-  if (1.5 is int) { x++; }
-  try { 1.5 as int; } on CastError catch (e) { }
-  try { var z = 1.5 as int; } on CastError catch (e) { }
-
-  1.5 is double;
-  if (1.5 is double) { x++; }
-  try { 1.5 as double; } on CastError catch (e) { }
-  try { var y = 1.5 as double; } on CastError catch (e) { }
-  1.5 is int;
-  if (1.5 is int) { x++; }
-  try { 1.5 as int; } on CastError catch (e) { }
-  try { var z = 1.5 as int; } on CastError catch (e) { }
-
-  x is double;
-  if (x is double) { }
-  try { x as double; } on CastError catch (e) { }
-  try { var z = x as double; } on CastError catch (e) { }
-  y is int;
-  if (y is int) { }
-  try { y as int; } on CastError catch (e) { }
-  try { var z = y as int; } on CastError catch (e) { }
-
-  "${1.5}";
-  var z = "${1.5}";
-  (1.5).toString();
-  z = (1.5).toString();
-  "$y";
-  z = "$y";
-  y.toString();
-  z = y.toString();
-
-  var a = "xyz";
-  var b = "xyz";
-  b = b.substring(1);
-  if (identical(a, b)) { }
-
-  if (identical(x, y)) { }
-  if (identical(y, x)) { }
-
-  if (x > 10) {
-    // Optimized code.
-    x is double;
-    if (x is double) { }
-    try { x as double; } on CastError catch (e) { }
-    try { var z = x as double; } on CastError catch (e) { }
-    y is int;
-    if (y is int) { }
-    try { y as int; } on CastError catch (e) { }
-    try { var z = y as int; } on CastError catch (e) { }
-
-    "${1.5}";
-    var z = "${1.5}";
-    (1.5).toString();
-    z = (1.5).toString();
-    "$y";
-    z = "$y";
-    y.toString();
-    z = y.toString();
-
-    var a = "xyz";
-    var b = "xyz";
-    b = b.substring(1);
-    if (identical(a, b)) { }
-
-    if (identical(x, y)) { }
-    if (identical(y, x)) { }
-  }
-}
-
-g(x, y) => f(x, y);  // Test inlining calls.
-h(x, y) => g(x, y);
-
-// We don't test for _JavascriptCompatibilityError since it's not visible.
-// It should not be visible since it doesn't exist on dart2js.
-bool isJavascriptCompatibilityError(e) =>
-    e is Error && "$e".contains("Javascript Compatibility Error");
-
-main() {
-  // The warning (or error in case of --warning_as_error) is issued at
-  // most once per location.
-  var numWarnings = 0;
-  for (var i = 0; i < 20; i++) {
-    try {
-      h(i, i * 1.0);
-    } catch(e) {
-      Expect.isTrue(isJavascriptCompatibilityError(e));
-      numWarnings++;
-    }
-  }
-  Expect.equals(1, numWarnings);
-  // No warnings (errors) should be issued after this point.
-  for (var i = 0; i < 20; i++) {
-    k(i * 1.0, i);
-    k(i * 1.0, i + 0.5);
-  }
-}
-
diff --git a/tests/standalone/javascript_compatibility_warnings_test.dart b/tests/standalone/javascript_compatibility_warnings_test.dart
deleted file mode 100644
index bb744b1..0000000
--- a/tests/standalone/javascript_compatibility_warnings_test.dart
+++ /dev/null
@@ -1,84 +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.
-
-// VMOptions=--warn_on_javascript_compatibility --no_warning_as_error --optimization_counter_threshold=5
-
-import "package:expect/expect.dart";
-
-f(x, y) {
-  // Unoptimized and optimized code.
-  1 is double;  /// 00: ok
-  if (1 is double) { x++; }  /// 01: ok
-  try { 1 as double; } on CastError catch (e) { }  /// 02: ok
-  try { var y = 1 as double; } on CastError catch (e) { }  /// 03: ok
-  1.0 is int;  /// 04: ok
-  if (1.0 is int) { x++; }  /// 05: ok
-  try { 1.0 as int; } on CastError catch (e) { }  /// 06: ok
-  try { var z = 1.0 as int; } on CastError catch (e) { }  /// 07: ok
-
-  x is double;  /// 10: ok
-  if (x is double) { }  /// 11: ok
-  try { x as double; } on CastError catch (e) { }  /// 12: ok
-  try { var z = x as double; } on CastError catch (e) { }  /// 13: ok
-  y is int;  /// 14: ok
-  if (y is int) { }  /// 15: ok
-  try { y as int; } on CastError catch (e) { }  /// 16: ok
-  try { var z = y as int; } on CastError catch (e) { }  /// 17: ok
-
-  "${1.0}";  /// 20: ok
-  var z = "${1.0}";  /// 21: ok
-  (1.0).toString();  /// 22: ok
-  var z = (1.0).toString();  /// 23: ok
-  "$y";  /// 24: ok
-  var z = "$y";  /// 25: ok
-  y.toString();  /// 26: ok
-  var z = y.toString();  /// 27: ok
-
-  var a = "yz";
-  var b = "xyz";
-  b = b.substring(1);
-  if (identical(a, b)) { }  /// 28: ok
-
-  if (identical(x, y)) { }  /// 29: ok
-  if (identical(y, x)) { }  /// 30: ok
-
-  if (x > 10) {
-    // Optimized code.
-    x is double;  /// 40: ok
-    if (x is double) { }  /// 41: ok
-    try { x as double; } on CastError catch (e) { }  /// 42: ok
-    try { var z = x as double; } on CastError catch (e) { }  /// 43: ok
-    y is int;  /// 44: ok
-    if (y is int) { }  /// 45: ok
-    try { y as int; } on CastError catch (e) { }  /// 46: ok
-    try { var z = y as int; } on CastError catch (e) { }  /// 47: ok
-
-    "${1.0}";  /// 50: ok
-    var z = "${1.0}";  /// 51: ok
-    (1.0).toString();  /// 52: ok
-    var z = (1.0).toString();  /// 53: ok
-    "$y";  /// 54: ok
-    var z = "$y";  /// 55: ok
-    y.toString();  /// 56: ok
-    var z = y.toString();  /// 57: ok
-
-    var a = "yz";
-    var b = "xyz";
-    b = b.substring(1);
-    if (identical(a, b)) { }  /// 58: ok
-
-    if (identical(x, y)) { }  /// 59: ok
-    if (identical(y, x)) { }  /// 60: ok
-  }
-}
-
-g(x, y) => f(x, y);  // Test inlining calls.
-h(x, y) => g(x, y);
-
-main() {
-  for (var i = 0; i < 20; i++) {
-    h(i, i* 1.0);
-  }
-}
-
diff --git a/tests/standalone/javascript_int_overflow_literal_test.dart b/tests/standalone/javascript_int_overflow_literal_test.dart
deleted file mode 100644
index d54df3a..0000000
--- a/tests/standalone/javascript_int_overflow_literal_test.dart
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// VMOptions=--throw_on_javascript_int_overflow --print_stacktrace_at_throw
-
-
-import "package:expect/expect.dart";
-
-int literals() {
-  var okay_literal = 0x20000000000000;
-  var too_big_literal = 0x20000000000001;  /// 01: compile-time error
-  return okay_literal;
-}
-
-main() {
-  Expect.equals(0x20000000000000, literals());
-}
diff --git a/tests/standalone/javascript_int_overflow_test.dart b/tests/standalone/javascript_int_overflow_test.dart
deleted file mode 100644
index 2661cd2..0000000
--- a/tests/standalone/javascript_int_overflow_test.dart
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// VMOptions=--throw_on_javascript_int_overflow --print_stacktrace_at_throw --optimization_counter_threshold=10 --no-use-osr
-
-
-import "package:expect/expect.dart";
-import 'dart:typed_data';
-
-
-double dti_arg;
-int double_to_int() {
-  return dti_arg.toInt();
-}
-
-
-int ia_arg1;
-int ia_arg2;
-int integer_add() {
-  return ia_arg1 + ia_arg2;
-}
-
-
-int is_arg;
-int integer_shift() {
-  return is_arg << 1;
-}
-
-
-int max_add_throws() {
-  return 0x20000000000000 + 1;
-}
-
-
-int min_sub_throws() {
-  return -0x20000000000000 - 1;
-}
-
-
-int n_arg;
-int negate() {
-  return -n_arg;
-}
-
-
-int max_literal() {
-  return 0x20000000000000;
-}
-
-
-int min_literal() {
-  var min_literal = -0x20000000000000;
-  return min_literal;
-}
-
-
-int doNotThrow1(a, b) {
-  return (a << b) & 0xFFFFFFFF;
-}
-
-int doNotThrow2(a, b) {
-  return (a << b) & 0xFFFFFFFF;
-}
-
-
-int doNotThrow3(a, b) {
-  return (a << b) & 0x7FFFFFFF;
-}
-
-
-int doNotThrow4(a, b) {
-  return (a << b) & 0x7FFFFFFF;
-}
-
-
-// We don't test for the _JavascriptIntegerOverflowError since it's not visible.
-// It should not be visible since it doesn't exist on dart2js.
-bool isJavascriptIntError(e) =>
-    e is Error && "$e".startsWith("Javascript Integer Overflow:");
-
-main() {
-  Expect.equals(0x20000000000000, max_literal());
-  Expect.equals(-0x20000000000000, min_literal());
-
-  // Run the tests once before optimizations.
-  dti_arg = 1.9e17;
-  Expect.throws(double_to_int, isJavascriptIntError);
-
-  ia_arg1 = (1 << 53);
-  ia_arg2 = (1 << 53);
-  Expect.throws(integer_add, isJavascriptIntError);
-
-  n_arg = -0x20000000000000;
-  Expect.equals(0x20000000000000, negate());
-
-  is_arg = (1 << 53);
-  Expect.throws(integer_shift, isJavascriptIntError);
-
-  Expect.throws(max_add_throws, isJavascriptIntError);
-  Expect.throws(min_sub_throws, isJavascriptIntError);
-
-  for (int i = 0; i < 20; i++) {
-    dti_arg = i.toDouble();
-    // Expect.throws calls through the closure, so we have to here, too.
-    var f = double_to_int;
-    Expect.equals(i, f());
-
-    ia_arg1 = i;
-    ia_arg2 = i;
-    f = integer_add;
-    Expect.equals(i + i, f());
-
-    n_arg = i;
-    f = negate;
-    Expect.equals(-i, f());
-
-    is_arg = i;
-    f = integer_shift;
-    Expect.equals(i << 1, f());
-  }
-
-   // The optimized functions should now deoptimize and throw the error.
-  dti_arg = 1.9e17;
-  Expect.throws(double_to_int, isJavascriptIntError);
-
-  ia_arg1 = (1 << 53);
-  ia_arg2 = (1 << 53);
-  Expect.throws(integer_add, isJavascriptIntError);
-
-  n_arg = -0x20000000000000;
-  Expect.equals(0x20000000000000, negate());
-
-  is_arg = (1 << 53);
-  Expect.throws(integer_shift, isJavascriptIntError);
-
-  Expect.throws(max_add_throws, isJavascriptIntError);
-  Expect.throws(min_sub_throws, isJavascriptIntError);
-
-  for (int i = 0; i < 20; i++) {
-    Expect.equals(0xAFAFA000, doNotThrow1(0xFAFAFA, 12));
-    Expect.equals(0x2FAFA000, doNotThrow3(0xFAFAFA, 12));
-    Expect.equals(0xABABA000, doNotThrow2(0xFAFAFAABABA, 12));
-    Expect.equals(0x2BABA000, doNotThrow4(0xFAFAFAABABA, 12));
-  }
-  for (int i = 0; i < 20; i++) {
-    Expect.equals(0xABABA000, doNotThrow1(0xFAFAFAABABA, 12));
-    Expect.equals(0x2BABA000, doNotThrow3(0xFAFAFAABABA, 12));
-  }
-
-}
diff --git a/tests/standalone/link_natives_lazily_test.dart b/tests/standalone/link_natives_lazily_test.dart
new file mode 100644
index 0000000..35a53a1
--- /dev/null
+++ b/tests/standalone/link_natives_lazily_test.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--link_natives_lazily
+
+main() {
+  print("Okay");
+}
diff --git a/tests/standalone/no_allow_absolute_addresses_test.dart b/tests/standalone/no_allow_absolute_addresses_test.dart
new file mode 100644
index 0000000..e013c5e
--- /dev/null
+++ b/tests/standalone/no_allow_absolute_addresses_test.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--no_allow_absolute_addresses
+
+main() {
+  print("Okay");
+}
diff --git a/tests/standalone/no_lazy_dispatchers_test.dart b/tests/standalone/no_lazy_dispatchers_test.dart
index 999505f..f45ba1c 100644
--- a/tests/standalone/no_lazy_dispatchers_test.dart
+++ b/tests/standalone/no_lazy_dispatchers_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--no-lazy-dispatchers
+// VMOptions=--no_lazy_dispatchers
 
 main() {
   print("Okay");
diff --git a/tests/standalone/precompilation_dart2js_test.dart b/tests/standalone/precompilation_dart2js_test.dart
index d7a8b71..0deafcb 100644
--- a/tests/standalone/precompilation_dart2js_test.dart
+++ b/tests/standalone/precompilation_dart2js_test.dart
@@ -77,7 +77,7 @@
 
     result = Process.runSync(
         cc,
-        [shared, cc_flags, "-o", libname, "precompiled.S"],
+        [shared, cc_flags, "-nostartfiles", "-o", libname, "precompiled.S"],
         workingDirectory: tmp.path);
     if (result.exitCode != 0) {
       print(result.stdout);
diff --git a/tests/standalone/precompilation_test.dart b/tests/standalone/precompilation_test.dart
index e58c5fe..e65bf17 100644
--- a/tests/standalone/precompilation_test.dart
+++ b/tests/standalone/precompilation_test.dart
@@ -74,7 +74,7 @@
 
     result = Process.runSync(
         cc,
-        [shared, cc_flags, "-o", libname, "precompiled.S"],
+        [shared, cc_flags, "-nostartfiles", "-o", libname, "precompiled.S"],
         workingDirectory: tmp.path);
     if (result.exitCode != 0) {
       print(result.stdout);
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 438e394..43cd0bc 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -18,8 +18,6 @@
 
 issue14236_test: Pass # Do not remove this line. It serves as a marker for Issue 14516 comment #4.
 
-javascript_compatibility_errors_test/none: Fail, OK  # Not possible to exclude or annotate with '/// none:'
-
 [ ($runtime != vm && $runtime != dart_precompiled) && ($runtime != drt || $compiler != none)) ]
 no_assert_test: Fail, OK # This is testing a vm flag.
 
@@ -27,9 +25,6 @@
 package/package_isolate_test: Fail # Issue 12474
 io/observatory_test: Fail
 package/scenarios/invalid/same_package_twice_test: Pass # Issue 24119
-javascript_int_overflow_test: Skip  # Fails if the bot's uptime becomes too high.
-javascript_int_overflow_literal_test: Skip  # Fails if the bot's uptime becomes too high.
-
 
 [ ($runtime == vm || $runtime == dart_precompiled) && $checked ]
 # These tests have type errors on purpose.
@@ -68,8 +63,6 @@
 http_launch_test: Skip
 vmservice/*: SkipByDesign # Do not run standalone vm service tests in browser.
 issue14236_test: Skip # Issue 14236 Script snapshots do not work in the browser.
-javascript_compatibility_errors_test: Skip
-javascript_compatibility_warnings_test: Skip
 oom_error_stacktrace_test: Skip
 out_of_memory_test: Skip
 verbose_gc_to_bmu_test: Skip
@@ -78,7 +71,6 @@
 noopt_test: Skip # Standalone only test.
 
 [ $compiler == dartanalyzer || $compiler == dart2analyzer ]
-javascript_int_overflow_literal_test/01: Fail, OK
 issue14236_test: Skip # Analyzer can't handle Script snapshots.
 
 # test issue https://code.google.com/p/dart/issues/detail?id=11518
@@ -109,13 +101,9 @@
 pow_test: Skip # Precision > 53 bits.
 double_smi_comparison_test: Skip # Precision > 53 bits.
 http_launch_test: Skip
-javascript_int_overflow_test: Skip
-javascript_int_overflow_literal_test: Skip
 oom_error_stacktrace_test: RuntimeError, OK # (OOM on JS may produce a stacktrace).
 vmservice/*: Skip # Do not run standalone vm service tests with dart2js.
 issue14236_test: Skip # dart2js does not deal with Script snapshots.
-javascript_compatibility_errors_test: Skip
-javascript_compatibility_warnings_test: Skip
 unboxed_int_converter_test: Skip
 pair_location_remapping_test: Skip
 precompilation_test: Skip # Standalone only test.
@@ -156,9 +144,6 @@
 out_of_memory_test: Skip # passes on Mac, crashes on Linux
 oom_error_stacktrace_test: Skip # Fails on Linux
 
-[ $arch == simmips || $arch == mips ]
-javascript_int_overflow_test: Skip # --throw_on_javascript_int_overflow not supported on MIPS.
-
 [ $arch == mips ]
 io/signals_test: Fail # Issue 17440
 io/file_stat_test: Fail # Issue 17440
@@ -176,10 +161,6 @@
 [ ($compiler == none || $compiler == precompiler) && ($runtime == dartium || $runtime == ContentShellOnAndroid) && $unchecked ]
 assert_test: Fail # Issue 14651.
 
-[ ($compiler == none || $compiler == precompiler) && ($runtime == dartium || $runtime == ContentShellOnAndroid) ]
-javascript_int_overflow_literal_test/01: Fail # Issue 14651.
-javascript_int_overflow_test: Fail # Issue 14651.
-
 [ $compiler == none && $runtime == drt ]
 map_literal_oom_test: RuntimeError # Issue 24571
 
@@ -197,8 +178,6 @@
 package/scenarios/packages_file_in_parent/sub/packages_file_in_parent_test: StaticWarning
 typed_data_test: StaticWarning
 typed_data_view_test: StaticWarning
-javascript_compatibility_errors_test: Skip
-javascript_compatibility_warnings_test: Skip
 
 [ $compiler == dart2analyzer ]
 package/package1_test: CompileTimeError
@@ -217,6 +196,7 @@
 verbose_gc_to_bmu_test: Skip
 io/platform_resolved_executable_test/06: RuntimeError  # Issue 23641
 io/process_sync_test: Pass, Timeout  # Issue 24596
+io/sleep_test: Pass, Fail # Issue 25757
 
 [ $arch != ia32 && $arch != x64 && $arch != simarm && $arch != simarmv5te && $mode == debug ]
 verified_mem_test: Skip  # Not yet implemented.
@@ -233,9 +213,12 @@
 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.
 
+[ $arch == ia32 ]
+no_allow_absolute_addresses_test: SkipByDesign # Not supported.
+link_natives_lazily_test: SkipByDesign # Not supported.
+
 [ ($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
 assert_test: RuntimeError # Expects line and column numbers
 precompilation_test: Skip # Platform.executable
diff --git a/tools/VERSION b/tools/VERSION
index 4d09691..fde1253 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 15
 PATCH 0
-PRERELEASE 2
+PRERELEASE 3
 PRERELEASE_PATCH 0
diff --git a/tools/bots/cross-vm.py b/tools/bots/cross-vm.py
index 9fd751f..9865547 100644
--- a/tools/bots/cross-vm.py
+++ b/tools/bots/cross-vm.py
@@ -47,7 +47,7 @@
       with bot.BuildStep('Create build tarball'):
         run(['tar', '-cjf', tarball, '--exclude=**/obj',
              '--exclude=**/obj.host', '--exclude=**/obj.target',
-             '--exclude=**/*analyzer*', 'out/', 'tools/testing/bin/'])
+             '--exclude=**/*analyzer*', 'out/'])
 
       with bot.BuildStep('Upload build tarball'):
         uri = "%s/%s" % (GCS_BUCKET, tarball)
diff --git a/tools/create_sdk.py b/tools/create_sdk.py
index c84f40d..1e4fc74 100755
--- a/tools/create_sdk.py
+++ b/tools/create_sdk.py
@@ -143,7 +143,7 @@
   for library in ['analyzer', 'analysis_server']:
     copytree(join(home, 'pkg', library), join(lib_dir, library),
              ignore=ignore_patterns('*.svn', 'doc', '*.py', '*.gypi', '*.sh',
-                                    '.gitignore'))
+                                    '.gitignore', 'packages'))
 
 def CopyDartdocResources(home, sdk_root):
   RESOURCE_DIR = join(sdk_root, 'bin', 'snapshots', 'resources')
diff --git a/tools/create_tarball.py b/tools/create_tarball.py
index 462bd9d..887bc86 100755
--- a/tools/create_tarball.py
+++ b/tools/create_tarball.py
@@ -40,8 +40,7 @@
 versiondir = ''
 
 # Ignore Git/SVN files, checked-in binaries, backup files, etc..
-ignoredPaths = ['tools/testing/bin',
-                'tools/sdks',
+ignoredPaths = ['tools/sdks',
                 'third_party/7zip', 'third_party/android_tools',
                 'third_party/clang', 'third_party/d8',
                 'third_party/firefox_jsshell']
diff --git a/tools/dartium/archive.py b/tools/dartium/archive.py
index 5f8bae8..973731d 100755
--- a/tools/dartium/archive.py
+++ b/tools/dartium/archive.py
@@ -21,7 +21,7 @@
   CONTENTSHELL_FILES = ['content_shell', 'content_shell.pak', 'fonts.conf',
                         'libffmpegsumo.so', 'libosmesa.so', 'lib',
                         'icudtl.dat', 'AHEM____.TTF', 'GardinerModBug.ttf',
-                        'GardinerModCat.ttf']
+                        'GardinerModCat.ttf', 'natives_blob.bin']
   CHROMEDRIVER_FILES = ['chromedriver']
 elif HOST_OS == 'win':
   # TODO: provide proper list.
diff --git a/tools/dartium/test.py b/tools/dartium/test.py
index d879d6e..0f16b41 100755
--- a/tools/dartium/test.py
+++ b/tools/dartium/test.py
@@ -183,8 +183,7 @@
     'arch': options.arch,
   }
 
-  test_script = os.path.join(srcpath, 'webkit', 'tools', 'layout_tests',
-                             'run_webkit_tests.py')
+  test_script = os.path.join(srcpath, 'third_party', 'WebKit', 'Tools', 'Scripts', 'run-webkit-tests')
 
   errors = False
   for component in components:
diff --git a/tools/dartium/update_deps.py b/tools/dartium/update_deps.py
index 6e27437..3370a24 100755
--- a/tools/dartium/update_deps.py
+++ b/tools/dartium/update_deps.py
@@ -41,8 +41,9 @@
 ########################################################################
 
 BRANCH_CURRENT="dart/dartium"
-BRANCH_NEXT="dart/dartium"
-BRANCH_MULTIVM="dart/multivm"
+BRANCH_NEXT="dart/2454_1"
+
+# (repo_name, deps_dir, repo_branch, prefix, repos, branch)
 
 TARGETS = {
   'dartium': (
@@ -56,9 +57,9 @@
     ),
   'integration': (
     # TODO(jacobr): what is the git repo for integration if any?
-    'https://dart.googlecode.com/svn/branches/dartium_integration/deps/dartium.deps',
+    'git@github.com:dart-lang/sdk.git',
     'tools/deps/dartium.deps',
-    'origin/master',
+    'origin/integration',
     'dartium',
     # TODO(vsm): Reenable 'chromium'
     ['webkit'],
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index accf568..43447ed 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -8,13 +8,9 @@
 # Now we need to override some settings and add some new ones.
 
 vars.update({
-  "chromium_url": "http://src.chromium.org/svn",
-  "dartium_base": "http://src.chromium.org",
-  "dartium_chromium_branch": "master",
-  "dartium_chromium_commit": "62a7524d4f71c9e0858d24b0aa1bbff3a2d09bff",
-  "chromium_base_revision": "297060",
-  "dartium_webkit_branch": "/blink/branches/dart/dartium",
-  "dartium_webkit_revision": "202760",
+  "dartium_chromium_commit": "8df9de5a8f073d9c0feadf8d652408807e4a254e",
+  "dartium_webkit_commit": "1d73225937ba77bba2d4279fe7b23bfb542d35d9",
+  "chromium_base_revision": "338390",
 
   # We use mirrors of all github repos to guarantee reproducibility and
   # consistency between what users see and what the bots see.
@@ -69,39 +65,19 @@
   "yaml_rev": "@563a5ffd4a800a2897b8f4dd6b19f2a370df2f2b",
   "zlib_rev": "@c3d0a6190f2f8c924a05ab6cc97b8f975bddd33f",
   "web_components_rev": "@0e636b534d9b12c9e96f841e6679398e91a986ec",
-  "WebCore_rev": "@4f90b41b0165f23f412cecdba07b7d81d3fbb5b5",
+  "WebCore_rev": "@5ecb723fd9ffcc0d108f5e0e24d12b8b3df7b200",
 
   "co19_rev": "@3ed795ea02e022ef19c77cf1b6095b7c8f5584d0",
 })
 
-def massage_deps(deps):
-  for key, value in deps.items():
-    if value is None: continue
-
-    if value.startswith('/trunk'):
-      deps[key] = Var("chromium_url") + value
-      continue
-
-    if value.startswith(Var("webkit_trunk")):
-      path, revision = value.split('@') # and svn revision.
-      path = path[len(Var("webkit_trunk")):]  # Strip WebKit repo.
-      value = (Var("dartium_base") + Var("dartium_webkit_branch") + path +
-               '@' + Var("dartium_webkit_revision"))
-      deps[key] = value
-      continue
-
-massage_deps(deps)
-for os_deps in deps_os.values():
-  massage_deps(os_deps)
-
 deps.update({
   "src":
     Var("chromium_git") + "/dart/dartium/src.git" + "@" +
         Var("dartium_chromium_commit"),
 
   "src/third_party/WebKit":
-    Var("dartium_base") + Var("dartium_webkit_branch") + "@" +
-        Var("dartium_webkit_revision"),
+    Var("chromium_git") + "/dart/dartium/blink.git" + "@" +
+        Var("dartium_webkit_commit"),
 
   "src/dart/third_party/pkg/args":
       (Var("github_mirror") % "args") + Var("args_tag"),
@@ -232,20 +208,6 @@
       Var('webkit_revision') + "\\n')" ],
 })
 hooks.append({
-  "name": "checked_in_dart_binaries",
-  "pattern": ".",
-  "action": [
-    "download_from_google_storage",
-    "--no_auth",
-    "--no_resume",
-    "--bucket",
-    "dart-dependencies",
-    "--recursive",
-    "--directory",
-    "src/dart/tools/testing/bin",
-  ],
-})
-hooks.append({
   "name": "checked_in_dart_sdks",
   "pattern": ".",
   "action": [
diff --git a/tools/deps/dartium.deps/DEPS.chromium b/tools/deps/dartium.deps/DEPS.chromium
index c4117a5..4abb484 100644
--- a/tools/deps/dartium.deps/DEPS.chromium
+++ b/tools/deps/dartium.deps/DEPS.chromium
@@ -1,81 +1,76 @@
-# This file is automatically processed to create .DEPS.git which is the file
-# that gclient uses under git.
+# This file is used to manage the dependencies of the Chromium src repo. It is
+# used by gclient to determine what version of each dependency to check out, and
+# where.
 #
-# See http://code.google.com/p/chromium/wiki/UsingGit
-#
-# To test manually, run:
-#   python tools/deps2git/deps2git.py -o .DEPS.git -w <gclientdir>
-# where <gcliendir> is the absolute path to the directory containing the
-# .gclient file (the parent of 'src').
-#
-# Then commit .DEPS.git locally (gclient doesn't like dirty trees) and run
-#   gclient sync
-# Verify the thing happened you wanted. Then revert your .DEPS.git change
-# DO NOT CHECK IN CHANGES TO .DEPS.git upstream. It will be automatically
-# updated by a bot when you modify this one.
+# For more information, please refer to the official documentation:
+#   https://sites.google.com/a/chromium.org/dev/developers/how-tos/get-the-code
 #
 # When adding a new dependency, please update the top-level .gitignore file
 # to list the dependency's destination directory.
+#
+# -----------------------------------------------------------------------------
+# Rolling deps
+# -----------------------------------------------------------------------------
+# All repositories in this file are git-based, using Chromium git mirrors where
+# necessary (e.g., a git mirror is used when the source project is SVN-based).
+# To update the revision that Chromium pulls for a given dependency:
+#
+#  # Create and switch to a new branch
+#  git new-branch depsroll
+#  # Run roll-dep (provided by depot_tools) giving the dep's path and the
+#  # desired SVN revision number (e.g., third_party/foo/bar and a revision such
+#  # number from Subversion)
+#  roll-dep third_party/foo/bar REVISION_NUMBER
+#  # You should now have a modified DEPS file; commit and upload as normal
+#  git commit -a
+#  git cl upload
+
 
 vars = {
   # 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',
-  'sourceforge_url': 'http://svn.code.sf.net/p/%(repo)s/code',
-  'llvm_url': 'http://src.chromium.org/llvm-project',
-  'llvm_git': 'https://llvm.googlesource.com',
-  'libcxx_revision': '48198f9110397fff47fe7c37cbfa296be7d44d3d',
-  'libcxxabi_revision': '4ad1009ab3a59fa7a6896d74d5e4de5885697f95',
-  'webkit_trunk': 'http://src.chromium.org/blink/trunk',
-  'webkit_revision': '889f35a63b23d86c0f318af9a65a875117811cfd', # from svn revision 182778
+  'webkit_revision': 'abaaf1d0b6b6483140b5dca34e80fc259833ddf7', # from svn revision 198714
   'chromium_git': 'https://chromium.googlesource.com',
-  'chromiumos_git': 'https://chromium.googlesource.com/chromiumos',
-  'pdfium_git': 'https://pdfium.googlesource.com',
-  'skia_git': 'https://skia.googlesource.com',
-  'boringssl_git': 'https://boringssl.googlesource.com',
-  'libvpx_revision': 'efe9712d52c2d216fb3d1ceb508b8148847a7e4b',
+  'libvpx_revision': '96484d320036bbc1e30f1dea232799a3e0517b1d',
   'sfntly_revision': '1bdaae8fc788a5ac8936d68bf24f37d977a13dac',
-  'skia_revision': 'b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49a',
+  'skia_revision': 'ea561bf055bb803f4c10ca323ea60a9d94da7956',
   # Three lines of non-changing comments so that
-  # the commit queue can handle CLs rolling Skia
-  # and V8 without interference from each other.
-  'v8_branch': 'trunk',
-  'v8_revision': '5830436a84f7792f61451af9bccd991d923fe81c', # from svn revision 24223
-  # Three lines of non-changing comments so that
-  # the commit queue can handle CLs rolling WebRTC
-  # and V8 without interference from each other.
+  # the commit queue can handle CLs rolling V8
+  # and whatever else without interference from each other.
+  'v8_revision': '7f211533faba9dd85708b1394186c7fe99b88392',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
-  'swarming_revision': '79940aeeec0ace78ade0fec27515850268761af5',
+  'swarming_revision': 'b39a448d8522392389b28f6997126a6ab04bfe87',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  "angle_revision": "df647a2a354d5dc9affdd6a982fccb6b95d361b0",
+  'angle_revision': '44897140a2ae07dc5ba88190100179baa6fe7914',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
-  'buildtools_revision': '56bc51aff4175d3fa27dcd0faa2c345ab046c8a5',
+  'buildtools_revision': 'ecc8e253abac3b6186a97573871a084f4c0ca3ae',
   # Three lines of non-changing comments so that
-  # the commit queue can handle CLs rolling PDFIum
+  # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '7a649fe262d77f93ad3213f53e973a7665d95a23',
+  'pdfium_revision': 'cc2323f0d0d626edac4a426097eb38b53ba54848',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
-  'openmax_dl_revision': '79e64bc9243e5ff11822434cf39b9fabefff3bfb',
+  'openmax_dl_revision': '22bb1085a6a0f6f3589a8c3d60ed0a9b82248275',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
-  'boringssl_revision': '01fe820ab957514f6b83e511492de1b3c03649d5',
+  'boringssl_revision': 'de24aadc5bc01130b6a9d25582203bb5308fabe1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling nss
   # and whatever else without interference from each other.
-  'nss_revision': '87b96db4268293187d7cf741907a6d5d1d8080e0',
+  'nss_revision': 'aab0d08a298b29407397fbb1c4219f99e99431ed', # from svn revision 295435
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
-  'google_toolbox_for_mac_revision': 'a09526298f9dd1ec49d3b3ac5608d2a257b94cef',
+  'google_toolbox_for_mac_revision': 'ce47a231ea0b238fbe95538e86cc61d74c234be6', # from svn revision 705
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling lighttpd
   # and whatever else without interference from each other.
@@ -83,11 +78,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling lss
   # and whatever else without interference from each other.
-  'lss_revision': '952107fa7cea0daaabead28c0e92d579bee517eb',
+  'lss_revision': '6f97298fe3794e92c8c896a6bc06e0b36e4c3de3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling NaCl
   # and whatever else without interference from each other.
-  'nacl_revision': 'c65c1ed84d500015273d5e72c6ddcebc2a23f9b8', # from svn revision r13797
+  'nacl_revision': 'b3d4cc125348924f727d3b87cee3674a839b54a0',
 }
 
 # Only these hosts are allowed for dependencies in this DEPS file.
@@ -96,11 +91,12 @@
   'chromium.googlesource.com',
   'boringssl.googlesource.com',
   'pdfium.googlesource.com',
+  'android.googlesource.com',
 ]
 
 deps = {
   'src/breakpad/src':
-   Var('chromium_git') + '/external/google-breakpad/src.git' + '@' + '35189355da4b65ed5e7692f790c240a9ab347731', # from svn revision 1387
+   Var('chromium_git') + '/external/google-breakpad/src.git' + '@' + '242fb9a38db6ba534b1f7daa341dd4d79171658b', # from svn revision 1471
 
   'src/buildtools':
    Var('chromium_git') + '/chromium/buildtools.git' + '@' +  Var('buildtools_revision'),
@@ -109,10 +105,10 @@
    Var('chromium_git') + '/external/open-vcdiff.git' + '@' + '438f2a5be6d809bc21611a94cd37bfc8c28ceb33', # from svn revision 41
 
   'src/testing/gtest':
-   Var('chromium_git') + '/external/googletest.git' + '@' + '4650552ff637bb44ecf7784060091cbed3252211', # from svn revision 692
+   Var('chromium_git') + '/external/googletest.git' + '@' + '23574bf2333f834ff665f894c97bef8a5b33a0a9', # from svn revision 711
 
   'src/testing/gmock':
-   Var('chromium_git') + '/external/googlemock.git' + '@' + '896ba0e03f520fb9b6ed582bde2bd00847e3c3f2', # from svn revision 485
+   Var('chromium_git') + '/external/googlemock.git' + '@' + '29763965ab52f24565299976b936d1265cb6a271', # from svn revision 501
 
   'src/third_party/angle':
    Var('chromium_git') + '/angle/angle.git' + '@' +  Var('angle_revision'),
@@ -120,47 +116,38 @@
   'src/third_party/colorama/src':
    Var('chromium_git') + '/external/colorama.git' + '@' + '799604a1041e9b3bc5d2789ecbd7e8db2e18e6b8',
 
+  'src/third_party/crashpad/crashpad':
+   Var('chromium_git') + '/crashpad/crashpad.git' + '@' + '797adb320680a4a8ad39428075cca287e04b111f',
+
   'src/third_party/trace-viewer':
-   Var('chromium_git') + '/external/trace-viewer.git' + '@' + '76a4496033c164d8be9ee8c57f702b0859cb1911',
+   Var('chromium_git') + '/external/trace-viewer.git' + '@' + '4f30209abd53c699c937519f39ce41888f93507b',
 
   'src/third_party/WebKit':
    Var('chromium_git') + '/chromium/blink.git' + '@' +  Var('webkit_revision'),
 
   'src/third_party/icu':
-   Var('chromium_git') + '/chromium/deps/icu52.git' + '@' + 'd2abf6c1e1f986f4a8db0341b8a8c55c55ec1174', # from svn revision 292003
+   Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'c81a1a3989c3b66fa323e9a6ee7418d7c08297af',
 
   'src/third_party/libexif/sources':
    Var('chromium_git') + '/chromium/deps/libexif/sources.git' + '@' + 'ed98343daabd7b4497f97fda972e132e6877c48a',
 
-  'src/third_party/hunspell':
-   Var('chromium_git') + '/chromium/deps/hunspell.git' + '@' + 'c956c0e97af00ef789afb2f64d02c9a5a50e6eb1',
-
   'src/third_party/hunspell_dictionaries':
-   Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + '4560bdd463a3500e2334e85c8a0e9e5d5d6774e7',
+   Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + 'c106afdcec5d3de2622e19f1b3294c47bbd8bd72',
 
   'src/third_party/safe_browsing/testing':
     Var('chromium_git') + '/external/google-safe-browsing/testing.git' + '@' + '9d7e8064f3ca2e45891470c9b5b1dce54af6a9d6',
 
-  'src/third_party/cacheinvalidation/src':
-    Var('chromium_git') + '/external/google-cache-invalidation-api/src.git' + '@' + 'c91bd9d9fed06bf440be64f87b94a2effdb32bc4', # from svn revision 341
-
   'src/third_party/leveldatabase/src':
-    Var('chromium_git') + '/external/leveldb.git' + '@' + '3f77584eb3f9754bbb7079070873ece3f30a1e6b',
-
-  'src/third_party/libc++/trunk':
-   Var('chromium_git') + '/chromium/llvm-project/libcxx.git' + '@' +  Var('libcxx_revision'),
-
-  'src/third_party/libc++abi/trunk':
-   Var('chromium_git') + '/chromium/llvm-project/libcxxabi.git' + '@' +  Var('libcxxabi_revision'),
+    Var('chromium_git') + '/external/leveldb.git' + '@' + '40c17c0b84ac0b791fb434096fd5c05f3819ad55',
 
   'src/third_party/snappy/src':
     Var('chromium_git') + '/external/snappy.git' + '@' + '762bb32f0c9d2f31ba4958c7c0933d22e80c20bf',
 
   'src/tools/grit':
-    Var('chromium_git') + '/external/grit-i18n.git' + '@' + '740badd5e3e44434a9a47b5d16749daac1e8ea80', # from svn revision 176
+    Var('chromium_git') + '/external/grit-i18n.git' + '@' + '1dac9ae64b0224beb1547810933a6f9998d0d55e', # from svn revision 191
 
   'src/tools/gyp':
-    Var('chromium_git') + '/external/gyp.git' + '@' + '46282cedf40ff7fe803be4af357b9d59050f02e4', # from svn revision 1977
+    Var('chromium_git') + '/external/gyp.git' + '@' + '5122240c5e5c4d8da12c543d82b03d6089eb77c5',
 
   'src/tools/swarming_client':
    Var('chromium_git') + '/external/swarming.client.git' + '@' +  Var('swarming_revision'),
@@ -171,21 +158,12 @@
   'src/native_client':
    Var('chromium_git') + '/native_client/src/native_client.git' + '@' + Var('nacl_revision'),
 
-  'src/chrome/test/data/extensions/api_test/permissions/nacl_enabled/bin':
-   Var('chromium_git') + '/native_client/src/native_client/tests/prebuilt.git' + '@' + '3e17365176c94624f46cace174f61834b7f3c35d',
-
   'src/third_party/sfntly/cpp/src':
     Var('chromium_git') + '/external/sfntly/cpp/src.git' + '@' +  Var('sfntly_revision'),
 
   'src/third_party/skia':
    Var('chromium_git') + '/skia.git' + '@' +  Var('skia_revision'),
 
-  'src/third_party/ots':
-    Var('chromium_git') + '/external/ots.git' + '@' + '98897009f3ea8a5fa3e20a4a74977da7aaa8e61a',
-
-  'src/third_party/brotli/src':
-   Var('chromium_git') + '/external/font-compression-reference.git' + '@' + '6cef49677dc4c650ef6e3f56041e0a41803afa8c',
-
   'src/tools/page_cycler/acid3':
    Var('chromium_git') + '/chromium/deps/acid3.git' + '@' + '6be0a66a1ebd7ebc5abc1b2f405a945f6d871521',
 
@@ -199,10 +177,7 @@
     Var('chromium_git') + '/external/bidichecker/lib.git' + '@' + '97f2aa645b74c28c57eca56992235c79850fa9e0',
 
   'src/third_party/webgl/src':
-   Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'b1a7210dc4034793e34a2149cb571e85700a85f2',
-
-  'src/third_party/swig/Lib':
-   Var('chromium_git') + '/chromium/deps/swig/Lib.git' + '@' + 'f2a695d52e61e6a8d967731434f165ed400f0d69',
+   Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '8986f8bfa84547b1a30a9256ebdd665024d68d71',
 
   'src/third_party/webdriver/pylib':
     Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
@@ -211,28 +186,25 @@
    Var('chromium_git') + '/chromium/deps/libvpx.git' + '@' +  Var('libvpx_revision'),
 
   'src/third_party/ffmpeg':
-   Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '438ff61fe51641665f0ec3bc55e7b416d0aa251a',
+   Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'f76066ad9f4aea07a53890b54d24cc22830b9efd',
 
   'src/third_party/libjingle/source/talk':
-    Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + '40539b82d5a2c9bcf23d078e997ce0368160f5a3',
+    Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + 'f7c923ddc729dc7f002b0e194ab72b661f932c00', # commit position 9564
 
   'src/third_party/usrsctp/usrsctplib':
-    Var('chromium_git') + '/external/usrsctplib.git' + '@' + '8975bd5397c2ec97f50e0b87b544054e0536bfe1',
+    Var('chromium_git') + '/external/usrsctplib.git' + '@' + '36444a999739e9e408f8f587cb4c3ffeef2e50ac', # from svn revision 9215
 
   'src/third_party/libsrtp':
-   Var('chromium_git') + '/chromium/deps/libsrtp.git' + '@' + '98284c8600c73812ff4716a6ea157d1e11d417dc',
-
-  'src/third_party/speex':
-   Var('chromium_git') + '/chromium/deps/speex.git' + '@' + '5260621c36c227209c7ba64ea71ca3418cf9e2b4',
+   Var('chromium_git') + '/chromium/deps/libsrtp.git' + '@' + '9c53f858cddd4d890e405e91ff3af0b48dfd90e6', # from svn revision 295151
 
   'src/third_party/yasm/source/patched-yasm':
-   Var('chromium_git') + '/chromium/deps/yasm/patched-yasm.git' + '@' + 'c960eb11ccda80b10ed50be39df4f0663b371d1d',
+   Var('chromium_git') + '/chromium/deps/yasm/patched-yasm.git' + '@' + '4671120cd8558ce62ee8672ebf3eb6f5216f909b',
 
   'src/third_party/libjpeg_turbo':
-   Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + '034e9a9747e0983bc19808ea70e469bc8342081f',
+   Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + 'f4631b6ee8b1dbb05e51ae335a7886f9ac598ab6',
 
   'src/third_party/flac':
-   Var('chromium_git') + '/chromium/deps/flac.git' + '@' + '0635a091379d9677f1ddde5f2eec85d0f096f219',
+   Var('chromium_git') + '/chromium/deps/flac.git' + '@' + 'c291ce676d2c855f7b2739f00f5c7f7e813813dc',
 
   'src/third_party/pyftpdlib/src':
     Var('chromium_git') + '/external/pyftpdlib.git' + '@' + '2be6d65e31c7ee6320d059f581f05ae8d89d7e45',
@@ -241,38 +213,36 @@
    Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067',
 
   'src/third_party/webrtc':
-    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '53545bbfc47f2cddb7038395369a0dcd457c8b34',
+    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '847b12a225694e10425c8a9b31e0eec028baf841', # commit position 9565
 
   'src/third_party/openmax_dl':
     Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
 
-  'src/third_party/jsoncpp/source/include':
-    Var('chromium_git') + '/external/jsoncpp/jsoncpp/include.git' + '@' + 'b0dd48e02b6e6248328db78a65b5c601f150c349',
-
-  'src/third_party/jsoncpp/source/src/lib_json':
-    Var('chromium_git') + '/external/jsoncpp/jsoncpp/src/lib_json.git' + '@' + 'a8caa51ba2f80971a45880425bf2ae864a786784',
+  'src/third_party/jsoncpp/source':
+    Var('chromium_git') + '/external/github.com/open-source-parsers/jsoncpp.git' + '@' + 'f572e8e42e22cfcf5ab0aea26574f408943edfa4', # from svn 248
 
   'src/third_party/libyuv':
-    Var('chromium_git') + '/external/libyuv.git' + '@' + '455c66b4375d72984b79249616d0a708ad568894',
+    Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '0e83b64e8879e9469919dc96b5d970c7c5bd05af', # from version 1444
 
   'src/third_party/smhasher/src':
     Var('chromium_git') + '/external/smhasher.git' + '@' + 'e87738e57558e0ec472b2fc3a643b838e5b6e88f',
 
   'src/third_party/libaddressinput/src':
-    Var('chromium_git') + '/external/libaddressinput.git' + '@' + '945d96387a716d0d82b195fa69a5e9a701249517', # from svn revision 334
+    Var('chromium_git') + '/external/libaddressinput.git' + '@' + '5eeeb797e79fa01503fcdcbebdc50036fac023ef',
 
+  # These are all at libphonenumber r728.
   'src/third_party/libphonenumber/src/phonenumbers':
-    Var('chromium_git') + '/external/libphonenumber/cpp/src/phonenumbers.git' + '@' + '8d8b5b3b2035197795d27573d4cf566b5d9ad689',
+    Var('chromium_git') + '/external/libphonenumber/cpp/src/phonenumbers.git' + '@' + '0d6e3e50e17c94262ad1ca3b7d52b11223084bca',
   'src/third_party/libphonenumber/src/test':
-    Var('chromium_git') + '/external/libphonenumber/cpp/test.git' + '@' + '883b7b86541d64b2691f7c0e65facb0b08db73e8',
+    Var('chromium_git') + '/external/libphonenumber/cpp/test.git' + '@' + 'f351a7e007f9c9995494499120bbc361ca808a16',
   'src/third_party/libphonenumber/src/resources':
-    Var('chromium_git') + '/external/libphonenumber/resources.git' + '@' + 'de095548d2ae828a414e01f3951bfefba902b4e4',
+    Var('chromium_git') + '/external/libphonenumber/resources.git' + '@' + 'b6dfdc7952571ff7ee72643cd88c988cbe966396',
 
   'src/tools/deps2git':
    Var('chromium_git') + '/chromium/tools/deps2git.git' + '@' + 'f04828eb0b5acd3e7ad983c024870f17f17b06d9',
 
   'src/third_party/webpagereplay':
-   Var('chromium_git') + '/external/web-page-replay.git' + '@' + '2f7b704b8b567983c040f555d3e46f9766db8e87',
+   Var('chromium_git') + '/external/github.com/chromium/web-page-replay.git' + '@' + '5da5975950daa7b30a6938da73fd0b3200901b0c',
 
   'src/third_party/pywebsocket/src':
     Var('chromium_git') + '/external/pywebsocket/src.git' + '@' + 'cb349e87ddb30ff8d1fa1a89be39cec901f4a29c',
@@ -281,25 +251,25 @@
    Var('chromium_git') + '/chromium/deps/opus.git' + '@' + 'cae696156f1e60006e39821e79a1811ae1933c69',
 
   'src/media/cdm/ppapi/api':
-   Var('chromium_git') + '/chromium/cdm.git' + '@' + '41c8183a3966a17b440dbe606cb2840e1b7ce884',
+   Var('chromium_git') + '/chromium/cdm.git' + '@' + '7377023e384f296cbb27644eb2c485275f1f92e8', # from svn revision 294518
 
   'src/third_party/mesa/src':
-   Var('chromium_git') + '/chromium/deps/mesa.git' + '@' + '457812d99a213dedf1c4cd38018ff48118d0c44f',
+   Var('chromium_git') + '/chromium/deps/mesa.git' + '@' + '071d25db04c23821a12a8b260ab9d96a097402f0',
 
   'src/third_party/cld_2/src':
-    Var('chromium_git') + '/external/cld2.git' + '@' + 'bb5c092e8c02dcc2319c5056aff2182199d51c2f',
-
-  'src/chrome/browser/resources/pdf/html_office':
-    Var('chromium_git') + '/chromium/html-office-public.git' + '@' + 'eeff97614f65e0578529490d44d412032c3d7359',
-
-  'src/third_party/libwebm/source':
-   Var('chromium_git') + '/webm/libwebm.git' + '@' + '0d4cb404ea4195e5e21d04db2c955615535ce62e',
+    Var('chromium_git') + '/external/cld2.git' + '@' + '14d9ef8d4766326f8aa7de54402d1b9c782d4481', # from svn revision 193
 
   'src/third_party/pdfium':
    'https://pdfium.googlesource.com/pdfium.git' + '@' +  Var('pdfium_revision'),
 
   'src/third_party/boringssl/src':
    'https://boringssl.googlesource.com/boringssl.git' + '@' +  Var('boringssl_revision'),
+
+  'src/third_party/py_trace_event/src':
+    Var('chromium_git') + '/external/py_trace_event.git' + '@' + 'dd463ea9e2c430de2b9e53dea57a77b4c3ac9b30',
+
+  'src/third_party/dom_distiller_js/dist':
+    Var('chromium_git') + '/external/github.com/chromium/dom-distiller-dist.git' + '@' + '81e5b59da2a7a0a518b90b5ded58670322c98128',
 }
 
 
@@ -334,9 +304,6 @@
     'src/third_party/nss':
      Var('chromium_git') + '/chromium/deps/nss.git' + '@' + Var('nss_revision'),
 
-    'src/third_party/swig/win':
-     Var('chromium_git') + '/chromium/deps/swig/win.git' + '@' + '986f013ba518541adf5c839811efb35630a31031',
-
     # GNU binutils assembler for x86-32.
     'src/third_party/gnu_binutils':
       Var('chromium_git') + '/native_client/deps/third_party/gnu_binutils.git' + '@' + 'f4003433b61b25666565690caf3d7a7a1a4ec436',
@@ -351,8 +318,15 @@
     # Binaries for nacl sdk.
     'src/third_party/nacl_sdk_binaries':
      Var('chromium_git') + '/chromium/deps/nacl_sdk_binaries.git' + '@' + '759dfca03bdc774da7ecbf974f6e2b84f43699a5',
+
+    # ANGLE uses dEQP for GPU testing
+    'src/third_party/deqp/src':
+     'https://android.googlesource.com/platform/external/deqp@194294e69d44eac48bc1fb063bd607189650aa5e',
   },
   'ios': {
+    'src/ios/third_party/gcdwebserver/src':
+     Var('chromium_git') + '/external/github.com/swisspol/GCDWebServer.git' + '@' + '3d5fd0b8281a7224c057deb2d17709b5bea64836',
+
     'src/third_party/google_toolbox_for_mac/src':
       Var('chromium_git') + '/external/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'),
 
@@ -360,45 +334,16 @@
      Var('chromium_git') + '/chromium/deps/nss.git' + '@' + Var('nss_revision'),
 
     # class-dump utility to generate header files for undocumented SDKs
-    'src/testing/iossim/third_party/class-dump':
-     Var('chromium_git') + '/chromium/deps/class-dump.git' + '@' + '89bd40883c767584240b4dade8b74e6f57b9bdab',
+    'src/third_party/class-dump/src':
+     Var('chromium_git') + '/external/github.com/nygard/class-dump.git' + '@' + '93e7c6a5419380d89656dcc511dc60d475199b67',
 
     # Code that's not needed due to not building everything
-    'src/build/util/support': None,
-    'src/chrome/test/data/extensions/api_test/permissions/nacl_enabled/bin': None,
     'src/chrome/test/data/perf/canvas_bench': None,
     'src/chrome/test/data/perf/frame_rate/content': None,
-    'src/media/cdm/ppapi/api': None,
     'src/native_client': None,
-    'src/third_party/bidichecker': None,
-    'src/third_party/brotli/src': None,
-    'src/third_party/cld_2/src': None,
     'src/third_party/ffmpeg': None,
     'src/third_party/hunspell_dictionaries': None,
-    'src/third_party/hunspell': None,
-    'src/third_party/libc++/trunk': None,
-    'src/third_party/libc++abi/trunk': None,
-    'src/third_party/libexif/sources': None,
-    'src/third_party/libjpeg_turbo': None,
-    'src/third_party/libsrtp': None,
-    'src/third_party/opus/src': None,
-    'src/third_party/openmax_dl': None,
-    'src/third_party/ots': None,
-    'src/third_party/pymox/src': None,
-    'src/third_party/safe_browsing/testing': None,
-    'src/third_party/scons-2.0.1': None,
-    'src/third_party/sfntly/cpp/src': None,
-    'src/third_party/speex': None,
-    'src/third_party/swig/Lib': None,
-    'src/third_party/usrsctp/usrsctplib': None,
-    'src/third_party/v8-i18n': None,
-    'src/third_party/webdriver/pylib': None,
     'src/third_party/webgl': None,
-    'src/third_party/webpagereplay': None,
-    'src/third_party/WebKit/LayoutTests/w3c/web-platform-tests': None,
-    'src/third_party/WebKit/LayoutTests/w3c/csswg-test': None,
-    'src/third_party/yasm/source/patched-yasm': None,
-    'src/tools/page_cycler/acid3': None,
   },
   'mac': {
     'src/chrome/tools/test/reference_build/chrome_mac':
@@ -414,9 +359,6 @@
     'src/third_party/lighttpd':
      Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'),
 
-    'src/third_party/swig/mac':
-     Var('chromium_git') + '/chromium/deps/swig/mac.git' + '@' + '1b182eef16df2b506f1d710b34df65d55c1ac44e',
-
     # NSS, for SSLClientSocketNSS.
     'src/third_party/nss':
      Var('chromium_git') + '/chromium/deps/nss.git' + '@' + Var('nss_revision'),
@@ -432,58 +374,59 @@
     'src/third_party/xdg-utils':
      Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
 
-    'src/third_party/swig/linux':
-     Var('chromium_git') + '/chromium/deps/swig/linux.git' + '@' + '866b8e0e0e0cfe99ebe608260030916ca0c3f92d',
-
     'src/third_party/lss':
       Var('chromium_git') + '/external/linux-syscall-support/lss.git' + '@' + Var('lss_revision'),
 
     # For Linux and Chromium OS.
     'src/third_party/cros_system_api':
-     Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + 'f0fc55329fa536195861778a2ddc6115b4a977bc',
+     Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '513f58ccbcecfd4a3d21545f67136090838eaf52',
 
     # Note that this is different from Android's freetype repo.
     'src/third_party/freetype2/src':
-     Var('chromium_git') + '/chromium/src/third_party/freetype2.git' + '@' + 'd699c2994ecc178c4ed05ac2086061b2034c2178',
+     Var('chromium_git') + '/chromium/src/third_party/freetype2.git' + '@' + '1dd5f5f4a909866f15c92a45c9702bce290a0151',
 
     # Build tools for Chrome OS.
     'src/third_party/chromite':
-     Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '8e92d5c24da7967e27ab2498abc2d2f7ac6ec65a',
+     Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'e19f83ba227bf1ec0077f5d3a816a415f1dd88d0',
 
     # Dependency of chromite.git.
     'src/third_party/pyelftools':
      Var('chromium_git') + '/chromiumos/third_party/pyelftools.git' + '@' + 'bdc1d380acd88d4bfaf47265008091483b0d614e',
 
-    'src/third_party/undoview':
-     Var('chromium_git') + '/chromium/deps/undoview.git' + '@' + '3ba503e248f3cdbd81b78325a24ece0984637559',
-
     'src/third_party/liblouis/src':
      Var('chromium_git') + '/external/liblouis-github.git' + '@' + '5f9c03f2a3478561deb6ae4798175094be8a26c2',
 
     # Used for embedded builds. CrOS & Linux use the system version.
     'src/third_party/fontconfig/src':
      Var('chromium_git') + '/external/fontconfig.git' + '@' + 'f16c3118e25546c1b749f9823c51827a60aeb5c1',
+
+    'src/third_party/stp/src':
+     Var('chromium_git') + '/external/github.com/stp/stp.git' + '@' + 'fc94a599207752ab4d64048204f0c88494811b62',
   },
   'android': {
     'src/third_party/android_protobuf/src':
-     Var('chromium_git') + '/external/android_protobuf.git' + '@' + '94f522f907e3f34f70d9e7816b947e62fddbb267',
-
-    # Whenever you roll this please also change frameworks/webview in
-    # src/android_webview/buildbot/aosp_manifest.xml to point to the same revision.
-    'src/third_party/android_webview_glue/src':
-     Var('chromium_git') + '/external/android_webview_glue.git' + '@' + 'a1b0248c80f239e2f6476b9f395b27d0ba1eb3cd',
+     Var('chromium_git') + '/external/android_protobuf.git' + '@' + '999188d0dc72e97f7fe08bb756958a2cf090f4e7',
 
     'src/third_party/android_tools':
-     Var('chromium_git') + '/android_tools.git' + '@' + 'd2b86205ff973a3844020feacb35ca6b1d82efbe',
+     Var('chromium_git') + '/android_tools.git' + '@' + '21f4bcbd6cd927e4b4227cfde7d5f13486be1236',
 
     'src/third_party/apache-mime4j':
      Var('chromium_git') + '/chromium/deps/apache-mime4j.git' + '@' + '28cb1108bff4b6cf0a2e86ff58b3d025934ebe3a',
 
+    'src/third_party/appurify-python/src':
+     Var('chromium_git') + '/external/github.com/appurify/appurify-python.git' + '@' + 'ee7abd5c5ae3106f72b2a0b9d2cb55094688e867',
+
+    'src/third_party/cardboard-java/src':
+     Var('chromium_git') + '/external/github.com/googlesamples/cardboard-java.git' + '@' + '08ad25a04f2801bd822c3f2cd28301b68d74aef6',
+
+    'src/third_party/errorprone/lib':
+      Var('chromium_git') + '/chromium/third_party/errorprone.git' + '@' + '6c66e56c0f9d750aef83190466df834f9d6af8ab',
+
     'src/third_party/findbugs':
      Var('chromium_git') + '/chromium/deps/findbugs.git' + '@' + '7f69fa78a6db6dc31866d09572a0e356e921bf12',
 
-    'src/third_party/freetype':
-     Var('chromium_git') + '/chromium/src/third_party/freetype.git' + '@' + 'a2b9955b49034a51dfbc8bf9f4e9d312149cecac',
+    'src/third_party/freetype-android/src':
+     Var('chromium_git') + '/chromium/src/third_party/freetype2.git' + '@' + 'e186230678ee8e4ea4ac4797ece8125761e3225a',
 
    'src/third_party/elfutils/src':
      Var('chromium_git') + '/external/elfutils.git' + '@' + '249673729a7e5dbd5de4f3760bdcaa3d23d154d7',
@@ -501,19 +444,32 @@
       Var('chromium_git') + '/external/jsr-305.git' + '@' + '642c508235471f7220af6d5df2d3210e3bfc0919',
 
     'src/third_party/junit/src':
-      Var('chromium_git') + '/external/junit.git' + '@' + 'c62e2df8dbecccb1b434d4ba8843b59e90b03266',
+      Var('chromium_git') + '/external/junit.git' + '@' + '45a44647e7306262162e1346b750c3209019f2e1',
+
+    'src/third_party/mockito/src':
+      Var('chromium_git') + '/external/mockito/mockito.git' + '@' + 'ed99a52e94a84bd7c467f2443b475a22fcc6ba8e',
+
+    'src/third_party/robolectric/lib':
+      Var('chromium_git') + '/chromium/third_party/robolectric.git' + '@' + '6b63c99a8b6967acdb42cbed0adb067c80efc810',
+
+    'src/third_party/ub-uiautomator/lib':
+      Var('chromium_git') + '/chromium/third_party/ub-uiautomator.git' + '@' + 'e6f02481bada8bdbdfdd7987dd6e648c44a3adcb',
 
     'src/third_party/lss':
       Var('chromium_git') + '/external/linux-syscall-support/lss.git' + '@' + Var('lss_revision'),
 
-    'src/third_party/eyesfree/src/android/java/src/com/googlecode/eyesfree/braille':
-      Var('chromium_git') + '/external/eyes-free/braille/client/src/com/googlecode/eyesfree/braille.git' + '@' + '77bf6edb0138e3a38a2772248696f130dab45e34',
+    'src/third_party/requests/src':
+      Var('chromium_git') + '/external/github.com/kennethreitz/requests.git' + '@' + 'f172b30356d821d180fa4ecfa3e71c7274a32de4',
+
+    'src/third_party/custom_tabs_client/src':
+      Var('chromium_git') + '/external/github.com/GoogleChrome/custom-tabs-client.git' + '@' + 'ef3ea193af9f4e45dd5094e8b6a952fb213bf11e',
   },
 }
 
 
 include_rules = [
   # Everybody can use some things.
+  # NOTE: THIS HAS TO STAY IN SYNC WITH third_party/DEPS which disallows these.
   '+base',
   '+build',
   '+ipc',
@@ -531,14 +487,11 @@
 # checkdeps.py shouldn't check include paths for files in these dirs:
 skip_child_includes = [
   'breakpad',
-  'delegate_execute',
-  'metro_driver',
   'native_client_sdk',
-  'o3d',
+  'out',
   'sdch',
   'skia',
   'testing',
-  'third_party',
   'v8',
   'win8',
 ]
@@ -563,42 +516,31 @@
     'name': 'nacltools',
     'pattern': '.',
     'action': [
-        'python', 'src/build/download_nacl_toolchains.py',
-        '--exclude', 'arm_trusted',
+        'python',
+        'src/build/download_nacl_toolchains.py',
+        '--mode', 'nacl_core_sdk',
+        'sync', '--extract',
     ],
   },
   {
-    # Downloads an ARM sysroot image to src/arm-sysroot. This image updates
-    # at about the same rate that the chrome build deps change.
-    # This script is a no-op except for linux users who have
-    # target_arch=arm in their GYP_DEFINES.
-    'name': 'sysroot',
+    # This downloads SDK extras and puts them in the
+    # third_party/android_tools/sdk/extras directory on the bots. Developers
+    # need to manually install these packages and accept the ToS.
+    'name': 'sdkextras',
     'pattern': '.',
-    'action': ['python', 'src/build/linux/install-arm-sysroot.py',
-               '--linux-only'],
+    # When adding a new sdk extras package to download, add the package
+    # directory and zip file to .gitignore in third_party/android_tools.
+    'action': ['python', 'src/build/download_sdk_extras.py'],
   },
   {
-    # Downloads the Debian Wheezy sysroot to chrome/installer/linux if needed.
+    # Downloads the current stable linux sysroot to build/linux/ if needed.
     # This sysroot updates at about the same rate that the chrome build deps
     # change. This script is a no-op except for linux users who are doing
-    # official chrome builds.
+    # official chrome builds or cross compiling.
     'name': 'sysroot',
     'pattern': '.',
-    'action': [
-        'python',
-        'src/chrome/installer/linux/sysroot_scripts/install-debian.wheezy.sysroot.py',
-        '--linux-only',
-        '--arch=amd64'],
-  },
-  {
-    # Same as above, but for 32-bit Linux.
-    'name': 'sysroot',
-    'pattern': '.',
-    'action': [
-        'python',
-        'src/chrome/installer/linux/sysroot_scripts/install-debian.wheezy.sysroot.py',
-        '--linux-only',
-        '--arch=i386'],
+    'action': ['python', 'src/build/linux/sysroot_scripts/install-sysroot.py',
+               '--running-as-hook'],
   },
   {
     # Update the Windows toolchain if necessary.
@@ -606,6 +548,17 @@
     'pattern': '.',
     'action': ['python', 'src/build/vs_toolchain.py', 'update'],
   },
+  # Pull binutils for linux, enabled debug fission for faster linking /
+  # debugging when used with clang on Ubuntu Precise.
+  # https://code.google.com/p/chromium/issues/detail?id=352046
+  {
+    'name': 'binutils',
+    'pattern': 'src/third_party/binutils',
+    'action': [
+        'python',
+        'src/third_party/binutils/download.py',
+    ],
+  },
   {
     # Pull clang if needed or requested via GYP_DEFINES.
     # Note: On Win, this should run after win_toolchain, as it may use it.
@@ -614,16 +567,14 @@
     'action': ['python', 'src/tools/clang/scripts/update.py', '--if-needed'],
   },
   {
-    # Update LASTCHANGE. This is also run by export_tarball.py in
-    # src/tools/export_tarball - please keep them in sync.
+    # Update LASTCHANGE.
     'name': 'lastchange',
     'pattern': '.',
     'action': ['python', 'src/build/util/lastchange.py',
                '-o', 'src/build/util/LASTCHANGE'],
   },
   {
-    # Update LASTCHANGE.blink. This is also run by export_tarball.py in
-    # src/tools/export_tarball - please keep them in sync.
+    # Update LASTCHANGE.blink.
     'name': 'lastchange',
     'pattern': '.',
     'action': ['python', 'src/build/util/lastchange.py',
@@ -654,17 +605,6 @@
     ],
   },
   {
-    'name': 'gn_linux32',
-    'pattern': '.',
-    'action': [ 'download_from_google_storage',
-                '--no_resume',
-                '--platform=linux*',
-                '--no_auth',
-                '--bucket', 'chromium-gn',
-                '-s', 'src/buildtools/linux32/gn.sha1',
-    ],
-  },
-  {
     'name': 'gn_linux64',
     'pattern': '.',
     'action': [ 'download_from_google_storage',
@@ -709,15 +649,38 @@
                 '-s', 'src/buildtools/linux64/clang-format.sha1',
     ],
   },
-  # Pull binutils for linux, enabled debug fission for faster linking /
-  # debugging when used with clang on Ubuntu Precise.
-  # https://code.google.com/p/chromium/issues/detail?id=352046
+  # Pull luci-go binaries (isolate, swarming) using checked-in hashes.
   {
-    'name': 'binutils',
-    'pattern': 'src/third_party/binutils',
-    'action': [
-        'python',
-        'src/third_party/binutils/download.py',
+    'name': 'luci-go_win',
+    'pattern': '.',
+    'action': [ 'download_from_google_storage',
+                '--no_resume',
+                '--platform=win32',
+                '--no_auth',
+                '--bucket', 'chromium-luci',
+                '-d', 'src/tools/luci-go/win64',
+    ],
+  },
+  {
+    'name': 'luci-go_mac',
+    'pattern': '.',
+    'action': [ 'download_from_google_storage',
+                '--no_resume',
+                '--platform=darwin',
+                '--no_auth',
+                '--bucket', 'chromium-luci',
+                '-d', 'src/tools/luci-go/mac64',
+    ],
+  },
+  {
+    'name': 'luci-go_linux',
+    'pattern': '.',
+    'action': [ 'download_from_google_storage',
+                '--no_resume',
+                '--platform=linux*',
+                '--no_auth',
+                '--bucket', 'chromium-luci',
+                '-d', 'src/tools/luci-go/linux64',
     ],
   },
   # Pull eu-strip binaries using checked-in hashes.
@@ -750,7 +713,19 @@
     'action': ['python',
                'src/build/get_syzygy_binaries.py',
                '--output-dir=src/third_party/syzygy/binaries',
-               '--revision=363bc02a09c380b6f5f397606cc0744d85d54a51',
+               '--revision=e50a9822fc8aeb5e7902da5e2940ea135d732e57',
+               '--overwrite',
+    ],
+  },
+  {
+    'name': 'kasko',
+    'pattern': '.',
+    'action': ['python',
+               'src/build/get_syzygy_binaries.py',
+               '--output-dir=src/third_party/kasko',
+               '--revision=283aeaceeb22e2ba40a1753e3cb32454b59cc017',
+               '--resource=kasko.zip',
+               '--resource=kasko_symbols.zip',
                '--overwrite',
     ],
   },
@@ -768,6 +743,40 @@
                 'src/third_party/apache-win32',
     ],
   },
+  # Pull the mojo_shell binary, used for mojo development
+  {
+    'name': 'download_mojo_shell',
+    'pattern': '',
+    'action': [ 'python',
+                'src/third_party/mojo/src/mojo/public/tools/download_shell_binary.py',
+                '--tools-directory=../../../../../../tools',
+              ],
+  },
+  {
+    # Pull sanitizer-instrumented third-party libraries if requested via
+    # GYP_DEFINES.
+    'name': 'instrumented_libraries',
+    'pattern': '\\.sha1',
+    'action': ['python', 'src/third_party/instrumented_libraries/scripts/download_binaries.py'],
+  },
+  {
+    # Ensure that while generating dependencies lists in .gyp files we don't
+    # accidentally reference any .pyc files whose corresponding .py files have
+    # already been deleted.
+    # We should actually try to avoid generating .pyc files, crbug.com/500078.
+    'name': 'remove_stale_pyc_files',
+    'pattern': '.',
+    'action': [
+        'python',
+        'src/tools/remove_stale_pyc_files.py',
+        'src/android_webview/tools',
+        'src/gpu/gles2_conform_support',
+        'src/ppapi',
+        'src/printing',
+        'src/third_party/closure_compiler/build',
+        'src/tools',
+    ],
+  },
   {
     # A change to a .gyp, .gypi, or to GYP itself should run the generator.
     'name': 'gyp',
@@ -786,15 +795,4 @@
         '--running-as-hook',
     ],
   },
-  {
-    # Ensure that we don't accidentally reference any .pyc files whose
-    # corresponding .py files have already been deleted.
-    'name': 'remove_stale_pyc_files',
-    'pattern': 'src/tools/.*\\.py',
-    'action': [
-        'python',
-        'src/tools/remove_stale_pyc_files.py',
-        'src/tools',
-    ],
-  },
 ]
diff --git a/tools/dom/dom.py b/tools/dom/dom.py
index c69d065..1316ab1 100755
--- a/tools/dom/dom.py
+++ b/tools/dom/dom.py
@@ -148,7 +148,7 @@
   print('Browse tests at '
       '\033[94mhttp://localhost:%d/root_build/generated_tests/\033[0m' % port)
   return call([
-    utils.DartBinary(),
+    utils.CheckedInSdkExecutable(),
     os.path.join('tools', 'testing', 'dart', 'http_server.dart'),
     '--port=%d' % port,
     '--crossOriginPort=%d' % (port + 1),
diff --git a/tools/dom/new_scripts/dart_utilities.py b/tools/dom/new_scripts/dart_utilities.py
index f67437b..3972783 100644
--- a/tools/dom/new_scripts/dart_utilities.py
+++ b/tools/dom/new_scripts/dart_utilities.py
@@ -156,7 +156,6 @@
 DartUtilities.has_extended_attribute = v8_utilities.has_extended_attribute
 DartUtilities.has_extended_attribute_value = v8_utilities.has_extended_attribute_value
 DartUtilities.measure_as = _measure_as
-DartUtilities.per_context_enabled_function_name = v8_utilities.per_context_enabled_function_name
 DartUtilities.runtime_enabled_function_name = v8_utilities.runtime_enabled_function_name
 DartUtilities.scoped_name = _scoped_name
 DartUtilities.strip_suffix = v8_utilities.strip_suffix
diff --git a/tools/dom/new_scripts/dependency.py b/tools/dom/new_scripts/dependency.py
new file mode 100644
index 0000000..060277e
--- /dev/null
+++ b/tools/dom/new_scripts/dependency.py
@@ -0,0 +1,9 @@
+builder = None
+
+def set_builder(created_builder):
+  global builder;
+  builder = created_builder
+
+def get_interfaces_info():
+  global builder;
+  return builder._info_collector.interfaces_info
diff --git a/tools/dom/scripts/dartdomgenerator.py b/tools/dom/scripts/dartdomgenerator.py
index 5a35903..4b07d77 100755
--- a/tools/dom/scripts/dartdomgenerator.py
+++ b/tools/dom/scripts/dartdomgenerator.py
@@ -45,6 +45,7 @@
 import time
 from dartmetadata import DartMetadata
 from generator import TypeRegistry
+from generate_blink_file import Generate_Blink
 from htmleventgenerator import HtmlEventGenerator
 from htmlrenamer import HtmlRenamer
 from systemhtml import DartLibraryEmitter, Dart2JSBackend,\
@@ -78,8 +79,9 @@
     common_database.Load()
   return common_database
 
-def GenerateFromDatabase(common_database, dart2js_output_dir,
-                         dartium_output_dir, update_dom_metadata=False,
+def GenerateFromDatabase(common_database,
+                         dart2js_output_dir, dartium_output_dir, blink_output_dir,
+                         update_dom_metadata=False,
                          logging_level=logging.WARNING, dart_js_interop=False):
   print '\n ----- Accessing DOM using %s -----\n' % ('dart:js' if dart_js_interop else 'C++')
 
@@ -194,6 +196,14 @@
         webkit_database, dartium_output_dir, type_registry, renamer)
     emitters.Flush()
 
+  if blink_output_dir:
+    print '\nGenerating _blink:\n'
+    start_time = time.time()
+
+    Generate_Blink(blink_output_dir, webkit_database, type_registry)
+
+    print 'Generated _blink in %s seconds' % round(time.time() - start_time, 2)
+
   if update_dom_metadata:
     metadata.Flush()
 
@@ -222,8 +232,8 @@
                     help='Use fremontcut in parallel mode.')
   parser.add_option('--systems', dest='systems',
                     action='store', type='string',
-                    default='htmldart2js,htmldartium',
-                    help='Systems to generate (htmldart2js, htmldartium)')
+                    default='htmldart2js,htmldartium,_blink',
+                    help='Systems to generate (htmldart2js, htmldartium, _blink)')
   parser.add_option('--output-dir', dest='output_dir',
                     action='store', type='string',
                     default=None,
@@ -267,6 +277,9 @@
   dartium_output_dir = None
   if 'htmldartium' in systems:
     dartium_output_dir = os.path.join(output_dir, 'dartium')
+  blink_output_dir = None
+  if '_blink' in systems:
+    blink_output_dir = os.path.join(output_dir, 'dartium')
 
   logging_level = options.logging_level \
     if options.logging == logging.NOTSET else options.logging
@@ -278,8 +291,13 @@
   # Parse the IDL and create the database.
   database = fremontcutbuilder.main(options.parallel, logging_level=logging_level, examine_idls=options.examine_idls)
 
-  GenerateFromDatabase(database, dart2js_output_dir, dartium_output_dir,
-      options.update_dom_metadata, logging_level, options.dart_js_interop)
+  GenerateFromDatabase(database,
+                       dart2js_output_dir,
+                       dartium_output_dir,
+                       blink_output_dir,
+                       options.update_dom_metadata,
+                       logging_level,
+                       options.dart_js_interop)
 
   file_generation_start_time = time.time()
 
@@ -300,6 +318,14 @@
           os.path.join(dartium_output_dir, '%s_dartium.dart' % library_name),
           os.path.join('..', '..', '..', 'sdk', 'lib', library_name, 'dartium'))
 
+  if '_blink' in systems:
+    _logger.info('Generating dartium _blink file.')
+    file_generation_start_time = time.time()
+
+    GenerateSingleFile(
+        os.path.join(dartium_output_dir, '%s_dartium.dart' % '_blink'),
+        os.path.join('..', '..', '..', 'sdk', 'lib', '_blink', 'dartium'))
+
   print '\nGenerating single file %s seconds' % round(time.time() - file_generation_start_time, 2)
 
   end_time = time.time()
diff --git a/tools/dom/scripts/dartgenerator.py b/tools/dom/scripts/dartgenerator.py
index 1b8db33..55a3499 100755
--- a/tools/dom/scripts/dartgenerator.py
+++ b/tools/dom/scripts/dartgenerator.py
@@ -38,6 +38,10 @@
     if IsRegisteredType(type_name):
       return True
 
+    # References a typedef - normally a union type.
+    if database.HasTypeDef(type_name):
+      return True
+
     if type_name.endswith('?'):
       return self._IsCompoundType(database, type_name[:-len('?')])
 
diff --git a/tools/dom/scripts/database.py b/tools/dom/scripts/database.py
index fc8b659..19ca222 100755
--- a/tools/dom/scripts/database.py
+++ b/tools/dom/scripts/database.py
@@ -44,6 +44,8 @@
     self._interfaces_to_delete = []
     self._enums = {}
     self._all_dictionaries = {}
+    # TODO(terry): Hack to remember all typedef unions.
+    self._all_type_defs = {}
 
   def Clone(self):
     new_database = Database(self._root_dir)
@@ -52,6 +54,7 @@
         self._interfaces_to_delete)
     new_database._enums = copy.deepcopy(self._enums)
     new_database._all_dictionaries = copy.deepcopy(self._all_dictionaries)
+    new_database._all_type_defs = copy.deepcopy(self._all_type_defs)
 
     return new_database
 
@@ -282,6 +285,29 @@
       res.append(dictionary)
     return res
 
+  def HasTypeDef(self, type_def_name):
+    """Returns True if the typedef is in memory"""
+    return type_def_name in self._all_type_defs
+
+  def GetTypeDef(self, type_def_name):
+    """Returns an IDLTypeDef corresponding to the type_def_name
+    from memory.
+
+    Args:
+      type_def_name -- the name of the typedef.
+    """
+    if type_def_name not in self._all_type_defs:
+      raise RuntimeError('Typedef %s is not loaded' % type_def_name)
+    return self._all_type_defs[type_def_name]
+
+  def AddTypeDef(self, type_def):
+    """Add only a typedef that a unions they map to any (no type)."""
+    type_def_name = type_def.id
+    if type_def_name in self._all_type_defs:
+      raise RuntimeError('Typedef %s already exists' % type_def_name)
+    self._all_type_defs[type_def_name] = type_def
+    print '  Added typedef %s' % type_def_name
+
   def TransitiveSecondaryParents(self, interface, propagate_event_target):
     """Returns a list of all non-primary parents.
 
diff --git a/tools/dom/scripts/databasebuilder.py b/tools/dom/scripts/databasebuilder.py
index f61b81b..ceb6eb1 100755
--- a/tools/dom/scripts/databasebuilder.py
+++ b/tools/dom/scripts/databasebuilder.py
@@ -20,9 +20,7 @@
 
 import compiler
 import compute_interfaces_info_individual
-from compute_interfaces_info_individual import compute_info_individual, info_individual
-import compute_interfaces_info_overall
-from compute_interfaces_info_overall import compute_interfaces_info_overall, interfaces_info
+from compute_interfaces_info_individual import InterfaceInfoCollector
 import idl_definitions
 
 from idlnode import *
@@ -132,7 +130,7 @@
         # Create compiler.
         self.idl_compiler = compiler.IdlCompilerDart(self.output_directory,
                                             attrib_file,
-                                            interfaces_info=interfaces_info,
+                                            interfaces_info=provider._info_collector.interfaces_info,
                                             only_if_changed=True)
 
     def format_exception(self, e):
@@ -168,13 +166,15 @@
   def __init__(self, database):
     """DatabaseBuilder is used for importing and merging interfaces into
     the Database"""
+    self._info_collector = InterfaceInfoCollector()
+
     self._database = database
     self._imported_interfaces = []
     self._impl_stmts = []
     self.conditionals_met = set()
 
     # Spin up the new IDL parser.
-    self.build = Build(None)
+    self.build = Build(self)
 
     # Global typedef to mapping.
     self.global_type_defs = monitored.Dict('databasebuilder.global_type_defs', {
@@ -186,13 +186,21 @@
   #              a type name.
   def _resolve_type_defs(self, idl_file):
     for type_node in idl_file.all(IDLType):
+      resolved = False
       type_name = type_node.id
       for typedef in self.global_type_defs:
         seq_name_typedef = 'sequence<%s>' % typedef
         if type_name == typedef:
           type_node.id = self.global_type_defs[typedef]
+          resolved = True
         elif type_name == seq_name_typedef:
           type_node.id = 'sequence<%s>' % self.global_type_defs[typedef]
+          resolved = True
+      if not(resolved):
+        for typedef in idl_file.typeDefs:
+          if type_name == typedef.id:
+            type_node.id = typedef.type.id
+            resolved = True
 
   def _strip_ext_attributes(self, idl_file):
     """Strips unuseful extended attributes."""
@@ -559,11 +567,11 @@
     if not(is_dart_idl):
       start_time = time.time()
 
-      # 2-stage computation: individual, then overall
+    # Compute information for individual files
+    # Information is stored in global variables interfaces_info and
+    # partial_interface_files.
       for file_path in file_paths:
-        compute_info_individual(file_path)
-      info_individuals = [info_individual()]
-      compute_interfaces_info_overall(info_individuals)
+        self._info_collector.collect_info(file_path)
 
       end_time = time.time()
       print 'Compute dependencies %s seconds' % round((end_time - start_time), 2)
@@ -572,7 +580,7 @@
       # file is special in that more than one interface can exist in this file.
       implement_pairs = self._compute_dart_idl_implements(file_paths[0])
 
-      interfaces_info['__dart_idl___'] = {
+      self._info_collector.interfaces_info['__dart_idl___'] = {
         'implement_pairs': implement_pairs,
       }
 
@@ -645,6 +653,10 @@
     for dictionary in idl_file.dictionaries:
       self._database.AddDictionary(dictionary)
 
+    # TODO(terry): Hack to remember all typedef unions they're mapped to any
+    #              - no type.
+    for typedef in idl_file.typeDefs:
+      self._database.AddTypeDef(typedef)
 
   def _is_node_enabled(self, node, idl_defines):
     if not 'Conditional' in node.ext_attrs:
diff --git a/tools/dom/scripts/fremontcutbuilder.py b/tools/dom/scripts/fremontcutbuilder.py
index ed11625..d368470 100755
--- a/tools/dom/scripts/fremontcutbuilder.py
+++ b/tools/dom/scripts/fremontcutbuilder.py
@@ -10,6 +10,7 @@
 import sys
 import time
 import utilities
+import dependency
 
 _logger = logging.getLogger('fremontcutbuilder')
 
@@ -50,6 +51,7 @@
   db.Delete()
 
   builder = databasebuilder.DatabaseBuilder(db)
+  dependency.set_builder(builder)
 
   # TODO(vsm): Move this to a README.
   # This is the Dart SVN revision.
diff --git a/tools/dom/scripts/generate_blink_file.py b/tools/dom/scripts/generate_blink_file.py
new file mode 100644
index 0000000..d5ea86f
--- /dev/null
+++ b/tools/dom/scripts/generate_blink_file.py
@@ -0,0 +1,275 @@
+#!/usr/bin/python
+#
+# 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.
+
+"""Generates sdk/lib/_blink/dartium/_blink_dartium.dart file."""
+
+import os
+
+from generator import AnalyzeOperation, AnalyzeConstructor
+
+HEADER = """/* 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.
+ *
+ * DO NOT EDIT
+ * Auto-generated _blink library.
+ */
+library dart.dom._blink;
+
+import 'dart:js' as js;
+import 'dart:html' show DomException;
+// This is a place to put custom renames if we need them.
+final resolverMap = {
+};
+
+dynamic resolver(String s) {
+"""
+
+END_RESOLVER = """
+  // Failed to find it, check for custom renames
+  dynamic obj = resolverMap[s];
+  if (obj != null) return obj;
+  throw("No such interface exposed in blink: ${s}");
+}
+
+"""
+
+BLINK_UTILS = """
+// _Utils native entry points
+class Blink_Utils {
+  static window() native "Utils_window";
+
+  static forwardingPrint(message) native "Utils_forwardingPrint";
+
+  static spawnDomUri(uri) native "Utils_spawnDomUri";
+
+  static void spawnDomHelper(Function f, int replyTo) native "Utils_spawnDomHelper";
+
+  static register(document, tag, customType, extendsTagName) native "Utils_register";
+
+  static createElement(document, tagName) native "Utils_createElement";
+
+  static constructElement(element_type, jsObject) native "Utils_constructor_create";
+
+  static initializeCustomElement(element) native "Utils_initializeCustomElement";
+
+  static changeElementWrapper(element, type) native "Utils_changeElementWrapper";
+}
+
+class Blink_DOMWindowCrossFrame {
+  // FIXME: Return to using explicit cross frame entry points after roll to M35
+  static get_history(_DOMWindowCrossFrame) native "Window_history_cross_frame_Getter";
+
+  static get_location(_DOMWindowCrossFrame) native "Window_location_cross_frame_Getter";
+
+  static get_closed(_DOMWindowCrossFrame) native "Window_closed_Getter";
+
+  static get_opener(_DOMWindowCrossFrame) native "Window_opener_Getter";
+
+  static get_parent(_DOMWindowCrossFrame) native "Window_parent_Getter";
+
+  static get_top(_DOMWindowCrossFrame) native "Window_top_Getter";
+
+  static close(_DOMWindowCrossFrame) native "Window_close_Callback";
+
+  static postMessage(_DOMWindowCrossFrame, message, targetOrigin, [messagePorts]) native "Window_postMessage_Callback";
+}
+
+class Blink_HistoryCrossFrame {
+  // _HistoryCrossFrame native entry points
+  static back(_HistoryCrossFrame) native "History_back_Callback";
+
+  static forward(_HistoryCrossFrame) native "History_forward_Callback";
+
+  static go(_HistoryCrossFrame, distance) native "History_go_Callback";
+}
+
+class Blink_LocationCrossFrame {
+  // _LocationCrossFrame native entry points
+  static set_href(_LocationCrossFrame, h) native "Location_href_Setter";
+}
+
+class Blink_DOMStringMap {
+  // _DOMStringMap native entry  points
+  static containsKey(_DOMStringMap, key) native "DOMStringMap_containsKey_Callback";
+
+  static item(_DOMStringMap, key) native "DOMStringMap_item_Callback";
+
+  static setItem(_DOMStringMap, key, value) native "DOMStringMap_setItem_Callback";
+
+  static remove(_DOMStringMap, key) native "DOMStringMap_remove_Callback";
+
+  static get_keys(_DOMStringMap) native "DOMStringMap_getKeys_Callback";
+}
+
+// Calls through JsNative but returns DomException instead of error strings.
+class Blink_JsNative_DomException {
+  static getProperty(js.JsObject o, name) {
+    try {
+      return js.JsNative.getProperty(o, name);
+    } catch (e) {
+      // Re-throw any errors (returned as a string) as a DomException.
+      throw new DomException.jsInterop(e);
+    }
+  }
+
+  static callMethod(js.JsObject o, String method, List args) {
+    try {
+      return js.JsNative.callMethod(o, method, args);
+    } catch (e) {
+      // Re-throw any errors (returned as a string) as a DomException.
+      throw new DomException.jsInterop(e);
+    }
+  }
+}"""
+
+CLASS_DEFINITION = """class Blink%s {
+  static final instance = new Blink%s();
+
+"""
+
+CLASS_DEFINITION_EXTENDS = """class Blink%s extends Blink%s {
+  static final instance = new Blink%s();
+
+"""
+
+#(interface_name)
+CONSTRUCTOR_0 = '  constructorCallback_0_() => new js.JsObject(Blink_JsNative_DomException.getProperty(js.context, "%s"), []);\n\n'
+
+#(argument_count, arguments, interface_name, arguments)
+CONSTRUCTOR_ARGS = '  constructorCallback_%s_(%s) => new js.JsObject(Blink_JsNative_DomException.getProperty(js.context, "%s"), [%s]);\n\n'
+
+#(attribute_name, attribute_name)
+ATTRIBUTE_GETTER = '  %s_Getter_(mthis) => Blink_JsNative_DomException.getProperty(mthis, "%s");\n\n'
+ATTRIBUTE_SETTER = '  %s_Setter_(mthis, __arg_0) => mthis["%s"] = __arg_0;\n\n'
+
+#(operation_name, operationName)
+OPERATION_0 = '  %s_Callback_0_(mthis) => Blink_JsNative_DomException.callMethod(mthis, "%s", []);\n\n'
+
+#(operation_name, argument_count, arguments, operation_name, arguments)
+ARGUMENT_NUM = "__arg_%s"
+OPERATION_ARGS = '  %s_Callback_%s_(mthis, %s) => Blink_JsNative_DomException.callMethod(mthis, "%s", [%s]);\n\n'
+
+CLASS_DEFINITION_END = """}
+
+"""
+
+def ConstantOutputOrder(a, b):
+  """Canonical output ordering for constants."""
+  return cmp(a.id, b.id)
+
+def generate_parameter_entries(param_infos):
+    optional_default_args = 0;
+    for argument in param_infos:
+      if argument.is_optional:
+        optional_default_args += 1
+
+    arg_count = len(param_infos)
+    min_arg_count = arg_count - optional_default_args
+    lb = min_arg_count - 2 if min_arg_count > 2 else 0
+    return (lb, arg_count + 1)
+
+def Generate_Blink(output_dir, database, type_registry):
+  blink_filename = os.path.join(output_dir, '_blink_dartium.dart')
+  blink_file = open(blink_filename, 'w')
+
+  blink_file.write(HEADER);
+
+  interfaces = database.GetInterfaces()
+  for interface in interfaces:
+    name = interface.id
+    resolver_entry = '  if (s == "%s") return Blink%s.instance;\n' % (name, name)
+    blink_file.write(resolver_entry)
+
+  blink_file.write(END_RESOLVER);
+
+  for interface in interfaces:
+    name = interface.id
+
+    if interface.parents and len(interface.parents) > 0 and interface.parents[0].id:
+      extends = interface.parents[0].id
+      class_def = CLASS_DEFINITION_EXTENDS % (name, extends, name)
+    else:
+      class_def = CLASS_DEFINITION % (name, name)
+    blink_file.write(class_def);
+
+    analyzed_constructors = AnalyzeConstructor(interface)
+    if analyzed_constructors:
+      _Emit_Blink_Constructors(blink_file, analyzed_constructors)
+    elif 'Constructor' in interface.ext_attrs:
+      # Zero parameter constructor.
+      blink_file.write(CONSTRUCTOR_0 % name)
+
+    _Process_Attributes(blink_file, interface.attributes)
+    _Process_Operations(blink_file, interface, interface.operations)
+
+    secondary_parents = database.TransitiveSecondaryParents(interface, False)
+    for secondary in secondary_parents:
+      _Process_Attributes(blink_file, secondary.attributes)
+      _Process_Operations(blink_file, secondary, secondary.operations)
+
+    blink_file.write(CLASS_DEFINITION_END);
+
+  blink_file.write(BLINK_UTILS)
+
+  blink_file.close()
+
+def _Emit_Blink_Constructors(blink_file, analyzed_constructors):
+  (arg_min_count, arg_max_count) = generate_parameter_entries(analyzed_constructors.param_infos)
+  name = analyzed_constructors.js_name
+  if not(name):
+    name = analyzed_constructors.type_name
+
+  for callback_index in range(arg_min_count, arg_max_count):
+    if callback_index == 0:
+      blink_file.write(CONSTRUCTOR_0 % (name))
+    else:
+      arguments = []
+      for i in range(0, callback_index):
+        arguments.append(ARGUMENT_NUM % i)
+      argument_list = ', '.join(arguments)
+      blink_file.write(CONSTRUCTOR_ARGS % (callback_index, argument_list, name, argument_list))
+
+def _Process_Attributes(blink_file, attributes):
+  # Emit an interface's attributes and operations.
+  for attribute in sorted(attributes, ConstantOutputOrder):
+    name = attribute.id
+    if attribute.is_read_only:
+      blink_file.write(ATTRIBUTE_GETTER % (name, name))
+    else:
+      blink_file.write(ATTRIBUTE_GETTER % (name, name))
+      blink_file.write(ATTRIBUTE_SETTER % (name, name))
+
+def _Process_Operations(blink_file, interface, operations):
+  analyzeOperations = []
+
+  for operation in sorted(operations, ConstantOutputOrder):
+    if len(analyzeOperations) == 0:
+      analyzeOperations.append(operation)
+    else:
+      if analyzeOperations[0].id == operation.id:
+        # Handle overloads
+        analyzeOperations.append(operation)
+      else:
+        _Emit_Blink_Operation(blink_file, interface, analyzeOperations)
+        analyzeOperations = [operation]
+  if len(analyzeOperations) > 0:
+    _Emit_Blink_Operation(blink_file, interface, analyzeOperations)
+
+def _Emit_Blink_Operation(blink_file, interface, analyzeOperations):
+  analyzed = AnalyzeOperation(interface, analyzeOperations)
+  (arg_min_count, arg_max_count) = generate_parameter_entries(analyzed.param_infos)
+  name = analyzed.js_name
+
+  for callback_index in range(arg_min_count, arg_max_count):
+    if callback_index == 0:
+      blink_file.write(OPERATION_0 % (name, name))
+    else:
+      arguments = []
+      for i in range(0, callback_index):
+        arguments.append(ARGUMENT_NUM % i)
+      argument_list = ', '.join(arguments)
+      blink_file.write(OPERATION_ARGS % (name, callback_index, argument_list, name, argument_list))
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index 6d235b81..bb26d6f 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -457,7 +457,14 @@
         parameter declaration.
     """
     def FormatParam(param):
-      dart_type = rename_type(param.type_id) if param.type_id else 'dynamic'
+      # Is the type a typedef if so it's a union so it's dynamic.
+      # TODO(terry): This may have to change for dart2js for code shaking the
+      #              return types (unions) needs to be emitted with @create
+      #              annotations and/or with JS('type1|type2',...)
+      if hasattr(rename_type, 'im_self') and rename_type.im_self._database.HasTypeDef(param.type_id):
+        dart_type = 'dynamic'
+      else:
+        dart_type = rename_type(param.type_id) if param.type_id else 'dynamic'
       return (TypeOrNothing(dart_type, param.type_id), param.name)
     required = []
     optional = []
@@ -1367,6 +1374,9 @@
   def HasInterface(self, type_name):
     return self._database.HasInterface(type_name)
 
+  def HasTypeDef(self, type_def_name):
+    return self._database.HasTypeDef(type_def_name)
+
   def TypeInfo(self, type_name):
     if not type_name in self._cache:
       self._cache[type_name] = self._TypeInfo(type_name)
@@ -1379,7 +1389,11 @@
     match = re.match(r'(?:sequence<([\w ]+)>|(\w+)\[\])$', type_name)
     if match:
       type_data = TypeData('Sequence')
-      item_info = self.TypeInfo(match.group(1) or match.group(2))
+      if self.HasTypeDef(match.group(1) or match.group(2)):
+        # It's a typedef (union)
+        item_info = self.TypeInfo('any')
+      else:
+        item_info = self.TypeInfo(match.group(1) or match.group(2))
       # TODO(vsm): Generalize this code.
       if 'SourceInfo' in type_name:
         type_data.native_type = 'const Vector<RefPtr<SourceInfo> >& '
@@ -1393,8 +1407,23 @@
 
       if self._database.HasInterface(type_name):
         interface = self._database.GetInterface(type_name)
-      else:
+      elif self._database.HasDictionary(type_name):
         interface = self._database.GetDictionary(type_name)
+      elif type_name.startswith('sequence<('):
+        if type_name.find(' or ') != -1:
+          # Union type of sequence is an any type (no type).
+          type_data = TypeData('Sequence')
+          item_info = self.TypeInfo('any')
+          return SequenceIDLTypeInfo(type_name, type_data, item_info)
+      elif type_name.startswith('sequence<sequence<'):
+        # TODO(terry): Cleanup up list of list, etc.
+        type_data = TypeData('Sequence')
+        item_info = self.TypeInfo('any')
+        return SequenceIDLTypeInfo(type_name, type_data, item_info)
+      elif self.HasTypeDef(type_name):
+        # It's a typedef (implied union)
+        return self.TypeInfo('any')
+
       if 'Callback' in interface.ext_attrs:
         return CallbackIDLTypeInfo(type_name, TypeData('Callback',
             self._renamer.DartifyTypeName(type_name)))
diff --git a/tools/dom/scripts/go.sh b/tools/dom/scripts/go.sh
index c17719f..a830a9b 100755
--- a/tools/dom/scripts/go.sh
+++ b/tools/dom/scripts/go.sh
@@ -18,7 +18,7 @@
 #
 # To generate a subset of systems:
 #
-#   ./go.sh dart2js,htmldart2js
+#   ./go.sh dart2js,htmldartium
 #
 # The following gives a picture of the changes due to 'work'
 #
@@ -29,7 +29,7 @@
 #   ./go.sh
 #   meld ../generated0 ../generated   # compare directories with too
 
-ALLSYSTEMS="htmldart2js,htmldartium"
+ALLSYSTEMS="htmldart2js,htmldartium,_blink"
 SYSTEMS="$ALLSYSTEMS"
 
 if [[ "$1" != "" ]] ; then
diff --git a/tools/dom/scripts/htmldartgenerator.py b/tools/dom/scripts/htmldartgenerator.py
index e7e500f..b93b0ca 100644
--- a/tools/dom/scripts/htmldartgenerator.py
+++ b/tools/dom/scripts/htmldartgenerator.py
@@ -311,6 +311,11 @@
       self.EmitAttribute(attribute, attr_name, read_only)
 
   def AddOperation(self, info, declare_only=False, dart_js_interop=False):
+    # TODO(terry): Hack window has 2 overloaded getter one returns Window and
+    #              and other object (we'll always return Window)?
+    if self._interface.id == "Window" and info.name == '__getter__':
+      info.operations[1].type = info.operations[0].type;
+
     """ Adds an operation to the generated class.
     Arguments:
       info - The operation info of the operation to be added.
@@ -528,7 +533,9 @@
   def _AddConstructor(self,
       constructor_info, factory_name, factory_constructor_name):
     # Hack to ignore the Image constructor used by JavaScript.
-    if ((self._interface.id == 'HTMLImageElement' or self._interface.id == 'Blob')
+    if ((self._interface.id == 'HTMLImageElement' or
+         self._interface.id == 'Blob' or
+         self._interface.id == 'DOMException')
       and not constructor_info.pure_dart_constructor):
       return
 
@@ -850,17 +857,20 @@
         verified_type = temp_type  # verified by assignment in checked mode.
       else:
         converted_arguments.append(info.param_infos[position].name)
-        param_type = self._NarrowInputType(arg.type.id)
-        # Verified by argument checking on entry to the dispatcher.
-
-        verified_type = self._InputType(
-            info.param_infos[position].type_id, info)
-        # The native method does not need an argument type if we know the type.
-        # But we do need the native methods to have correct function types, so
-        # be conservative.
-        if param_type == verified_type:
-          if param_type in ['String', 'num', 'int', 'double', 'bool', 'Object']:
-            param_type = 'dynamic'
+        if self._database.HasTypeDef(arg.type.id):
+          param_type = 'dynamic'
+        else:
+          param_type = self._NarrowInputType(arg.type.id)
+          # Verified by argument checking on entry to the dispatcher.
+  
+          verified_type = self._InputType(
+              info.param_infos[position].type_id, info)
+          # The native method does not need an argument type if we know the type.
+          # But we do need the native methods to have correct function types, so
+          # be conservative.
+          if param_type == verified_type:
+            if param_type in ['String', 'num', 'int', 'double', 'bool', 'Object']:
+              param_type = 'dynamic'
 
       target_parameters.append(
           '%s%s' % (TypeOrNothing(param_type), param_name))
@@ -872,4 +882,8 @@
     if conversion:
       return conversion.input_type
     else:
-      return self._NarrowInputType(type_name) if type_name else 'dynamic'
+      # If typedef it's a union return dynamic.
+      if self._database.HasTypeDef(type_name):
+        return 'dynamic'
+      else:
+        return self._NarrowInputType(type_name) if type_name else 'dynamic'
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index 78193a5..823666c 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -60,7 +60,8 @@
     'SVGSVGElement': 'SvgSvgElement', # Manual to avoid name conflicts.
     'Stream': 'FileStream',
     'StringCallback': '_StringCallback',
-    'WebGLVertexArrayObjectOES': 'VertexArrayObject',
+    'WebGL2RenderingContext': 'RenderingContext2',
+    'WebGL2RenderingContextBase': 'RenderingContextBase2',
     'WindowTimers': '_WindowTimers',
     'XMLHttpRequest': 'HttpRequest',
     'XMLHttpRequestUpload': 'HttpRequestUpload',
diff --git a/tools/dom/scripts/idlnode.py b/tools/dom/scripts/idlnode.py
index e09c8c8..8dfd3b8 100755
--- a/tools/dom/scripts/idlnode.py
+++ b/tools/dom/scripts/idlnode.py
@@ -8,9 +8,7 @@
 
 import idl_definitions
 from idl_types import IdlType, IdlNullableType, IdlUnionType, IdlArrayOrSequenceType
-
-from compute_interfaces_info_overall import interfaces_info
-
+import dependency
 
 new_asts = {}
 
@@ -363,7 +361,7 @@
           # Special handling for dart.idl we need to remember the interface,
           # since we could have many (not one interface / file). Then build up
           # the IDLImplementsStatement for any implements in dart.idl.
-          interface_info = interfaces_info['__dart_idl___'];
+          interface_info = dependency.get_interfaces_info()['__dart_idl___'];
 
           self.implementsStatements = []
 
@@ -377,10 +375,10 @@
                                                                   implemented_name)
 
             self.implementsStatements.append(implement_statement)
-        elif interface.id in interfaces_info:
-          interface_info = interfaces_info[interface.id]
+        elif interface.id in dependency.get_interfaces_info():
+          interface_info = dependency.get_interfaces_info()[interface.id]
 
-          implements = interface_info['implements_interfaces']
+          implements = interface_info['implements_interfaces'] if interface_info.has_key('implements_interfaces') else []
           if not(blink_interface.is_partial) and len(implements) > 0:
             implementor = new_asts[interface.id].interfaces.get(interface.id)
 
@@ -400,6 +398,15 @@
     # No reason to handle typedef they're already aliased in Blink's AST.
     self.typeDefs = [] if is_blink else self._convert_all(ast, 'TypeDef', IDLTypeDef)
 
+    # Hack to record typedefs that are unions.
+    for typedefName in ast.typedefs:
+      typedef_type = ast.typedefs[typedefName]
+      if isinstance(typedef_type.idl_type, IdlUnionType):
+        self.typeDefs.append(IDLTypeDef(typedef_type))
+      elif typedef_type.idl_type.base_type == 'Dictionary':
+        dictionary = IDLDictionary(typedef_type, True)
+        self.dictionaries.append(dictionary)
+
     self.enums = self._convert_all(ast, 'Enum', IDLEnum)
 
   def _createImplementsStatement(self, implementor, implemented_name):
@@ -433,7 +440,7 @@
       # implements is handled by the interface merging step (see the function
       # merge_interface_dependencies).
       for interface in self.interfaces:
-        interface_info = interfaces_info[interface.id]
+        interface_info = get_interfaces_info()[interface.id]
         # TODO(terry): Same handling for implementsStatements as in IDLFile?
         self.implementsStatements = interface_info['implements_interfaces']
     else:
@@ -567,13 +574,12 @@
       if isinstance(ast, IdlType) or isinstance(ast, IdlArrayOrSequenceType) or \
          isinstance(ast, IdlNullableType):
         type_name = str(ast)
-
         # TODO(terry): For now don't handle unrestricted types see
         #              https://code.google.com/p/chromium/issues/detail?id=354298
         type_name = type_name.replace('unrestricted ', '', 1);
 
-        # TODO(terry): Handled ScalarValueString as a DOMString.
-        type_name = type_name.replace('ScalarValueString', 'DOMString', 1)
+        # TODO(terry): Handled USVString as a DOMString.
+        type_name = type_name.replace('USVString', 'DOMString', 1)
 
         self.id = type_name
       else:
@@ -635,13 +641,16 @@
   """IDLDictionary node contains members,
   as well as parent references."""
 
-  def __init__(self, ast):
+  def __init__(self, ast, typedefDictionary=False):
     IDLNode.__init__(self, ast)
 
     self.javascript_binding_name = self.id
-    self._convert_ext_attrs(ast)
-    self._convert_constants(ast, self.id)
-
+    if (typedefDictionary):
+        # Dictionary is a typedef to a union.
+        self._convert_ext_attrs(None)
+    else:
+        self._convert_ext_attrs(ast)
+        self._convert_constants(ast, self.id)
 
 class IDLDictionaryMembers(IDLDictNode):
   """IDLDictionaryMembers specialization for a list of FremontCut dictionary values."""
@@ -754,6 +763,8 @@
           # Handling __propertyQuery__ the extended attribute is:
           # [Custom=PropertyQuery] getter boolean (DOMString name);
           self.id = '__propertyQuery__'
+        elif self.ext_attrs.get('ImplementedAs'):
+          self.id = self.ext_attrs.get('ImplementedAs')
         else:
           self.id = '__getter__'
       elif self.specials == ['setter']:
diff --git a/tools/dom/scripts/idlsync.py b/tools/dom/scripts/idlsync.py
index dc49fce..24aae09 100755
--- a/tools/dom/scripts/idlsync.py
+++ b/tools/dom/scripts/idlsync.py
@@ -7,6 +7,7 @@
 import os
 import os.path
 import re
+import requests
 import shutil
 import subprocess
 import sys
@@ -15,9 +16,10 @@
 SCRIPT_PATH = os.path.abspath(os.path.dirname(__file__))
 DART_PATH = os.path.abspath(os.path.join(SCRIPT_PATH, '..', '..', '..'))
 
-# Dartium DEPS file with Chrome and WebKit revisions.
-DEPS = ('http://dart.googlecode.com/svn/branches/'
-        'bleeding_edge/deps/dartium.deps/DEPS')
+# Dartium DEPS file from the DEPS file checked into the dart-lang/sdk integration
+# branch.
+DEPS_GIT = ('https://raw.githubusercontent.com/dart-lang/sdk/'
+            'integration/tools/deps/dartium.deps/DEPS')
 
 # Whitelist of files to keep.
 WHITELIST = [
@@ -29,7 +31,7 @@
     ]
 
 # WebKit / WebCore info.
-CHROME_TRUNK = "http://src.chromium.org"
+CHROME_TRUNK = "https://src.chromium.org"
 WEBKIT_URL_PATTERN = r'"dartium_webkit_branch": "(\S+)",'
 WEBKIT_REV_PATTERN = r'"dartium_webkit_revision": "(\d+)",'
 WEBCORE_SUBPATH = 'Source/core'
@@ -84,7 +86,7 @@
 # DEPS file.
 DEPS_PATTERNS = {
     'webkit': (CHROME_TRUNK, WEBKIT_URL_PATTERN, WEBKIT_REV_PATTERN),
-    'chrome': (CHROME_TRUNK, CHROME_URL_PATTERN, CHROME_REV_PATTERN),
+#    'chrome': (CHROME_TRUNK, CHROME_URL_PATTERN, CHROME_REV_PATTERN),
     }
 
 # List of components to update.
@@ -130,11 +132,9 @@
     print 'FAILED. RET_CODE=%d' % pipe.returncode
     sys.exit(pipe.returncode)
 
-
-def GetDeps():
-  """Returns the DEPS file contents with pinned revision info."""
-  return RunCommand(['svn', 'cat', DEPS])
-
+def GetDepsFromGit():
+  req = requests.get(DEPS_GIT)
+  return req.text
 
 def GetSvnRevision(deps, component):
   """Returns a tuple with the (dartium webkit repo, latest revision)."""
@@ -208,21 +208,15 @@
                     help='WebKit IDL revision to install', default=None)
   parser.add_option('--chrome-revision', '-c', dest='chrome_revision',
                     help='Chrome IDL revision to install', default=None)
-  parser.add_option('--update', '-u', dest='update',
-                    help='IDL to update (webkit | chrome | all)',
-                    default='webkit')
   args, _ = parser.parse_args()
   update = {}
-  if args.update == 'all' or args.update == 'chrome':
-    update['chrome'] = args.chrome_revision
-  if args.update == 'all' or args.update == 'webkit':
-    update['webkit'] = args.webkit_revision
+  update['webkit'] = args.webkit_revision
   return update
 
 
 def main():
-  deps = GetDeps()
   update = ParseOptions()
+  deps = GetDepsFromGit()
   for (component, remote_path, local_path, readme, depth) in UPDATE_LIST:
     if component in update.keys():
       revision = update[component]
diff --git a/tools/dom/src/native_DOMImplementation.dart b/tools/dom/src/native_DOMImplementation.dart
index e9e3720..b624dd0 100644
--- a/tools/dom/src/native_DOMImplementation.dart
+++ b/tools/dom/src/native_DOMImplementation.dart
@@ -774,7 +774,7 @@
     return [
         "inspect",
         (o) {
-          host.callMethod("inspect", [o]);
+          host.callMethod("_inspect", [unwrap_jso(o)]);
           return o;
         },
         "dir",
diff --git a/tools/dom/templates/html/impl/impl_MessageEvent.darttemplate b/tools/dom/templates/html/impl/impl_MessageEvent.darttemplate
index cf3c4e4..1b3280d 100644
--- a/tools/dom/templates/html/impl/impl_MessageEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_MessageEvent.darttemplate
@@ -21,11 +21,22 @@
           type, canBubble, cancelable, data, origin, lastEventId, source,
           messagePorts);
     }
-$endif 
+$endif
     var event = document._createEvent("MessageEvent");
     event._initMessageEvent(type, canBubble, cancelable, data, origin,
         lastEventId, source, messagePorts);
     return event;
   }
+
+$if DARTIUM
+  // TODO(alanknight): This really should be generated by the
+  // _OutputConversion in the systemnative.py script, but that doesn't
+  // use those conversions right now, so do this as a one-off.
+  @DomName('MessageEvent.data')
+  @DocsEditable()
+  dynamic get data => convertNativeToDart_SerializedScriptValue(
+      _blink.BlinkMessageEvent.instance.data_Getter_(unwrap_jso(this)));
+$endif
+
 $!MEMBERS
 }
diff --git a/tools/observatory_tool.py b/tools/observatory_tool.py
index 67c52d7..4cb5dbf 100755
--- a/tools/observatory_tool.py
+++ b/tools/observatory_tool.py
@@ -144,7 +144,8 @@
       # development flow.
       # REMOVE THE FOLLOWING LINE TO USE the dart_bootstrap binary.
       # return False
-    print >> sys.stderr, ('Running command "%s"') % (executable + command)
+    if not silent:
+      print >> sys.stderr, ('Running command "%s"') % (executable + command)
     return subprocess.call(executable + command,
                            stdout=silent_sink if silent else None,
                            stderr=silent_sink if silent else None)
diff --git a/tools/precompilation/test_linux.sh b/tools/precompilation/test_linux.sh
index 93de570..514ac04 100755
--- a/tools/precompilation/test_linux.sh
+++ b/tools/precompilation/test_linux.sh
@@ -10,6 +10,6 @@
 
 ./out/DebugX64/dart_no_snapshot --gen-precompiled-snapshot --package-root=out/DebugX64/packages/ "$1"
 
-gcc -m64 -shared -Wl,-soname,libprecompiled.so -o libprecompiled.so precompiled.S
+gcc -nostartfiles -m64 -shared -Wl,-soname,libprecompiled.so -o libprecompiled.so precompiled.S
 
 LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PWD" gdb -ex run --args ./out/DebugX64/dart_precompiled_runtime --run-precompiled-snapshot not_used.dart
diff --git a/tools/precompilation/test_linux_simarm.sh b/tools/precompilation/test_linux_simarm.sh
index 8a8f36c..bd0f1f0 100755
--- a/tools/precompilation/test_linux_simarm.sh
+++ b/tools/precompilation/test_linux_simarm.sh
@@ -10,6 +10,6 @@
 
 ./out/DebugSIMARM/dart_no_snapshot --gen-precompiled-snapshot --package-root=out/DebugX64/packages/ "$1"
 
-gcc -m32 -shared -Wl,-soname,libprecompiled.so -o libprecompiled.so precompiled.S
+gcc -nostartfiles -m32 -shared -Wl,-soname,libprecompiled.so -o libprecompiled.so precompiled.S
 
 LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PWD" gdb -ex run --args ./out/DebugSIMARM/dart_precompiled_runtime --run-precompiled-snapshot not_used.dart
diff --git a/tools/precompilation/test_macos.sh b/tools/precompilation/test_macos.sh
index e853b1b..ed90d12 100755
--- a/tools/precompilation/test_macos.sh
+++ b/tools/precompilation/test_macos.sh
@@ -10,6 +10,6 @@
 
 ./xcodebuild/DebugX64/dart_no_snapshot --gen-precompiled-snapshot --package-root=xcodebuild/DebugX64/packages/ "$1"
 
-clang -m64 -dynamiclib -o libprecompiled.dylib precompiled.S
+clang -nostartfiles -m64 -dynamiclib -o libprecompiled.dylib precompiled.S
 
 LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PWD" lldb -- ./xcodebuild/DebugX64/dart_precompiled_runtime --run-precompiled-snapshot not_used.dart
diff --git a/tools/sdks/linux/dart-sdk.tar.gz.sha1 b/tools/sdks/linux/dart-sdk.tar.gz.sha1
index 90b6e73..9083f2b 100644
--- a/tools/sdks/linux/dart-sdk.tar.gz.sha1
+++ b/tools/sdks/linux/dart-sdk.tar.gz.sha1
@@ -1 +1 @@
-2709941a74b808414feb005dfa50986680f9bd20
\ No newline at end of file
+360de5bc1ad8b525f2ccc98c80fd87131caaefe2
\ No newline at end of file
diff --git a/tools/sdks/mac/dart-sdk.tar.gz.sha1 b/tools/sdks/mac/dart-sdk.tar.gz.sha1
index 9f3c196..292199a 100644
--- a/tools/sdks/mac/dart-sdk.tar.gz.sha1
+++ b/tools/sdks/mac/dart-sdk.tar.gz.sha1
@@ -1 +1 @@
-8d928e400289862483a11e798743e49815c06c43
\ No newline at end of file
+45bb23f239c67de5e01a24e7efcf4b323eb9c36c
\ No newline at end of file
diff --git a/tools/sdks/win/dart-sdk.tar.gz.sha1 b/tools/sdks/win/dart-sdk.tar.gz.sha1
index a5b7f6a..54587b2 100644
--- a/tools/sdks/win/dart-sdk.tar.gz.sha1
+++ b/tools/sdks/win/dart-sdk.tar.gz.sha1
@@ -1 +1 @@
-90d43da115a1eafe707f6f5c5c0d718ff716c227
\ No newline at end of file
+1264ca2ff3131284a53ccffadeb230835300c602
\ No newline at end of file
diff --git a/tools/test.py b/tools/test.py
index 69b9ed8..9a32fa5 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -16,7 +16,8 @@
   tools_dir = os.path.dirname(os.path.realpath(__file__))
   dart_script_name = 'test.dart'
   dart_test_script = string.join([tools_dir, dart_script_name], os.sep)
-  command = [utils.DartBinary(), '--checked', dart_test_script] + args
+  command = [utils.CheckedInSdkExecutable(),
+             '--checked', dart_test_script] + args
   exit_code = subprocess.call(command)
   utils.DiagnoseExitCode(exit_code, command)
   return exit_code
diff --git a/tools/testing/bin/linux/dart-arm.sha1 b/tools/testing/bin/linux/dart-arm.sha1
deleted file mode 100644
index c00a011..0000000
--- a/tools/testing/bin/linux/dart-arm.sha1
+++ /dev/null
@@ -1 +0,0 @@
-5246a42926c8d5c2ac785c952b76b746270c9484
\ No newline at end of file
diff --git a/tools/testing/bin/linux/dart-mips.sha1 b/tools/testing/bin/linux/dart-mips.sha1
deleted file mode 100644
index 6100eae..0000000
--- a/tools/testing/bin/linux/dart-mips.sha1
+++ /dev/null
@@ -1 +0,0 @@
-7ab189bca5c5cf2997b9ab5770a5b418cd4fa5b1
\ No newline at end of file
diff --git a/tools/testing/bin/linux/dart.sha1 b/tools/testing/bin/linux/dart.sha1
deleted file mode 100644
index d8f03be..0000000
--- a/tools/testing/bin/linux/dart.sha1
+++ /dev/null
@@ -1 +0,0 @@
-701c1f2bda5c7fa3cc0f044d7515237bdc2cc163
\ No newline at end of file
diff --git a/tools/testing/bin/macos/dart.sha1 b/tools/testing/bin/macos/dart.sha1
deleted file mode 100644
index c30354b..0000000
--- a/tools/testing/bin/macos/dart.sha1
+++ /dev/null
@@ -1 +0,0 @@
-ecefe6ba96b8da00d171e199b2801982f98cc78d
\ No newline at end of file
diff --git a/tools/testing/bin/windows/dart.exe.sha1 b/tools/testing/bin/windows/dart.exe.sha1
deleted file mode 100644
index c43f346..0000000
--- a/tools/testing/bin/windows/dart.exe.sha1
+++ /dev/null
@@ -1 +0,0 @@
-c1394c6a589c47f7a6a1315eb1f9885d66852d67
\ No newline at end of file
diff --git a/tools/testing/dart/co19_test.dart b/tools/testing/dart/co19_test.dart
index f138688e..d826263 100644
--- a/tools/testing/dart/co19_test.dart
+++ b/tools/testing/dart/co19_test.dart
@@ -11,7 +11,7 @@
  * co19.
  *
  * Usage:
- * [: ./tools/testing/bin/$OS/dart tools/testing/dart/co19_test.dart :]
+ * [: dart tools/testing/dart/co19_test.dart :]
  */
 
 library co19_test;
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 70c1264..931a53d 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -73,6 +73,9 @@
             isHostChecked: isHostChecked, useCps: useCps, useSdk: useSdk,
             isCsp: isCsp, extraDart2jsOptions:
                 TestUtils.getExtraOptions(configuration, 'dart2js_options'));
+      case 'dart2app':
+        return new Dart2AppSnapshotCompilerConfiguration(
+            isDebug: isDebug, isChecked: isChecked);
       case 'precompiler':
         return new PrecompilerCompilerConfiguration(
             isDebug: isDebug, isChecked: isChecked);
@@ -214,22 +217,11 @@
     arguments = new List.from(arguments);
     arguments.add('--out=$outputFileName');
 
-    // We want all dart2js compilers to run the vm with the
-    // --abort-on-assertion-errors flag.
-    // We have allowed constant maps as environmentOverrides,
-    // so we modify a new map.
-    var newOverrides = {'DART_VM_OPTIONS': '--abort-on-assertion-errors'};
-    if (environmentOverrides != null) {
-      newOverrides.addAll(environmentOverrides);
-      if (environmentOverrides.containsKey('DART_VM_OPTIONS')) {
-        newOverrides['DART_VM_OPTIONS'] += ' --abort-on-assertion-errors';
-      }
-    }
     return commandBuilder.getCompilationCommand(
         moniker, outputFileName, !useSdk,
         bootstrapDependencies(buildDir),
         computeCompilerPath(buildDir),
-        arguments, newOverrides);
+        arguments, environmentOverrides);
   }
 
   List<Uri> bootstrapDependencies(String buildDir) {
@@ -394,6 +386,93 @@
 }
 
 
+class Dart2AppSnapshotCompilerConfiguration extends CompilerConfiguration {
+  Dart2AppSnapshotCompilerConfiguration({
+      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)],
+        computeOutputName(tempDir),
+        'application/dart-snapshot');
+  }
+
+  String computeOutputName(String tempDir) {
+    return '$tempDir/test.snapshot';
+  }
+
+  CompilationCommand computeCompilationCommand(
+      String tempDir,
+      String buildDir,
+      CommandBuilder commandBuilder,
+      List arguments,
+      Map<String, String> environmentOverrides) {
+    var exec = "$buildDir/dart_no_snapshot";
+    var args = new List();
+    args.add("--full-snapshot-after-run=${computeOutputName(tempDir)}");
+    args.addAll(arguments);
+
+    return commandBuilder.getCompilationCommand(
+        'dart2snapshot', computeOutputName(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/http_server.dart b/tools/testing/dart/http_server.dart
index 843aaaf..1cfdb65 100644
--- a/tools/testing/dart/http_server.dart
+++ b/tools/testing/dart/http_server.dart
@@ -172,7 +172,7 @@
   }
 
   String httpServerCommandline() {
-    var dart = TestUtils.dartTestExecutable.toNativePath();
+    var dart = Platform.resolvedExecutable;
     var dartDir = TestUtils.dartDir;
     var script = dartDir.join(new Path("tools/testing/dart/http_server.dart"));
     var buildDirectory = _buildDirectory.toNativePath();
diff --git a/tools/testing/dart/runtime_configuration.dart b/tools/testing/dart/runtime_configuration.dart
index 8596c6f..c2b2aed 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_product':
+        return new DartProductRuntimeConfiguration();
+
       case 'dart_precompiled':
         return new DartPrecompiledRuntimeConfiguration();
 
@@ -218,7 +221,7 @@
     if (script != null && type != 'application/dart') {
       throw "Dart VM cannot run files of type '$type'.";
     }
-    String executable = suite.configuration['noopt'] 
+    String executable = suite.configuration['noopt']
         ? suite.dartVmNooptBinaryFileName
         : suite.dartVmBinaryFileName;
     return <Command>[commandBuilder.getVmCommand(
@@ -226,6 +229,29 @@
   }
 }
 
+class DartProductRuntimeConfiguration 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-snapshot') {
+      throw "dart_product cannot run files of type '$type'.";
+    }
+
+    var augmentedArgs = new List();
+    augmentedArgs.add("--run-full-snapshot=${artifact.filename}");
+    augmentedArgs.addAll(arguments);
+
+    return <Command>[commandBuilder.getVmCommand(
+          suite.dartVmProductBinaryFileName,
+          augmentedArgs,
+          environmentOverrides)];
+  }
+}
 
 class DartPrecompiledRuntimeConfiguration extends DartVmRuntimeConfiguration {
   List<Command> computeRuntimeCommands(
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index 8e23169..26d5249 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -65,9 +65,13 @@
          none (compile only)),
 
    dart2analyzer: Perform static analysis on Dart code by running the analyzer
-          (only valid with the following runtimes: none)''',
+          (only valid with the following runtimes: none)
+
+   dart2app: Compile the Dart code into an app snapshot before running the test
+          (only valid with the following runtimes: dart_product)''',
               ['-c', '--compiler'],
-              ['none', 'precompiler', 'dart2js', 'dart2analyzer'],
+              ['none', 'precompiler', 'dart2js', 'dart2analyzer',
+               'dart2app'],
               'none'),
           // TODO(antonm): fix the option drt.
           new _TestOptionSpecification(
@@ -78,6 +82,8 @@
     dart_precompiled: Run a precompiled snapshot on a variant of the standalone
                       dart vm lacking a JIT.
 
+    dart_product: Run a full app snapshot in product mode.
+
     d8: Run JavaScript from the command line using v8.
 
     jsshell: Run JavaScript from the command line using firefox js-shell.
@@ -98,7 +104,8 @@
     none: No runtime, compile only (for example, used for dart2analyzer static
           analysis tests).''',
               ['-r', '--runtime'],
-              ['vm', 'dart_precompiled', 'd8', 'jsshell', 'drt', 'dartium',
+              ['vm', 'dart_precompiled', 'dart_product',
+               'd8', 'jsshell', 'drt', 'dartium',
                'ff', 'firefox',
                'chrome', 'safari', 'ie9', 'ie10', 'ie11', 'opera',
                'chromeOnAndroid', 'safarimobilesim',
@@ -648,6 +655,9 @@
       case 'dart2analyzer':
         validRuntimes = const ['none'];
         break;
+      case 'dart2app':
+        validRuntimes = const ['dart_product'];
+        break;
       case 'precompiler':
         validRuntimes = const ['dart_precompiled'];
         break;
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index ffd9921..42dba81 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -292,7 +292,7 @@
       retry == other.retry;
 
   String get reproductionCommand {
-    var parts = [TestUtils.dartTestExecutable.toString(),
+    var parts = [io.Platform.resolvedExecutable,
                 'tools/testing/dart/launch_browser.dart',
                 browser,
                 url];
@@ -1679,7 +1679,8 @@
     return new VmCommandOutputImpl(
         command, exitCode, timedOut, stdout, stderr, time, pid);
   } else if (command is CompilationCommand) {
-    if (command.displayName == 'precompiler.dart') {
+    if (command.displayName == 'precompiler.dart' ||
+        command.displayName == 'dart2snapshot') {
       return new VmCommandOutputImpl(
           command, exitCode, timedOut, stdout, stderr, time, pid);
     }
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index ed354d2..21a99a8 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -240,6 +240,21 @@
     return dartExecutable;
   }
 
+  String get dartVmProductBinaryFileName {
+    // Controlled by user with the option "--dart".
+    String dartExecutable = configuration['dart'];
+
+    if (dartExecutable == '') {
+      String suffix = executableBinarySuffix;
+      dartExecutable = useSdk
+          ? '$buildDir/dart-sdk/bin/dart_product$suffix'
+          : '$buildDir/dart_product$suffix';
+    }
+
+    TestUtils.ensureExists(dartExecutable, configuration);
+    return dartExecutable;
+  }
+
   String get d8FileName {
     var suffix = getExecutableSuffix('d8');
     var d8Dir = TestUtils.dartDir.append('third_party/d8');
@@ -1807,8 +1822,9 @@
   }
 
   List<List<String>> getVmOptions(Map optionsFromFile) {
-    var COMPILERS = const ['none', 'precompiler'];
-    var RUNTIMES = const ['none', 'dart_precompiled', 'vm', 'drt', 'dartium',
+    var COMPILERS = const ['none', 'precompiler', 'dart2app'];
+    var RUNTIMES = const ['none', 'dart_precompiled', 'dart_product', 'vm',
+                          'drt', 'dartium',
                           'ContentShellOnAndroid', 'DartiumOnAndroid'];
     var needsVmOptions = COMPILERS.contains(configuration['compiler']) &&
                          RUNTIMES.contains(configuration['runtime']);
@@ -2371,19 +2387,6 @@
   }
 
   /**
-   * Returns the path to the dart binary checked into the repo, used for
-   * bootstrapping test.dart.
-   */
-  static Path get dartTestExecutable {
-    var path = '$dartDir/tools/testing/bin/'
-        '${Platform.operatingSystem}/dart';
-    if (Platform.operatingSystem == 'windows') {
-      path = '$path.exe';
-    }
-    return new Path(path);
-  }
-
-  /**
    * Gets extra options under [key] passed to the testing script.
    */
   static List<String> getExtraOptions(Map configuration, String key) {
diff --git a/tools/utils.py b/tools/utils.py
index 8ea1874..69d6a39 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -573,38 +573,6 @@
   return pipe.returncode, output
 
 
-def DartBinary():
-  # TODO(24311): Replace all uses of this with CheckedInSdk[Fix]Executable().
-  tools_dir = os.path.dirname(os.path.realpath(__file__))
-  dart_binary_prefix = os.path.join(tools_dir, 'testing', 'bin')
-  if IsWindows():
-    return os.path.join(dart_binary_prefix, 'windows', 'dart.exe')
-  else:
-    arch = GuessArchitecture()
-    system = GuessOS()
-    if arch == 'armv5te':
-      # TODO(zra): This binary does not exist, yet. Check one in once we have
-      # sufficient stability.
-      return os.path.join(dart_binary_prefix, system, 'dart-armv5te')
-    elif arch == 'armv6':
-      # TODO(zra): Ditto.
-      return os.path.join(dart_binary_prefix, system, 'dart-armv6')
-    elif arch == 'arm':
-      return os.path.join(dart_binary_prefix, system, 'dart-arm')
-    elif arch == 'arm64':
-      return os.path.join(dart_binary_prefix, system, 'dart-arm64')
-    elif arch == 'mips':
-      return os.path.join(dart_binary_prefix, system, 'dart-mips')
-    else:
-      return os.path.join(dart_binary_prefix, system, 'dart')
-
-
-def DartSdkBinary():
-  tools_dir = os.path.dirname(os.path.realpath(__file__))
-  dart_binary_prefix = os.path.join(tools_dir, '..', 'sdk' , 'bin')
-  return os.path.join(dart_binary_prefix, 'dart')
-
-
 # The checked-in SDKs are documented at
 #     https://github.com/dart-lang/sdk/wiki/The-checked-in-SDK-in-tools
 def CheckedInSdkPath():
@@ -635,7 +603,14 @@
     elif arch == 'arm':
       name = 'dart-arm'
     elif arch == 'arm64':
-      name = 'dart-arm'
+      name = 'dart-arm64'
+    elif arch == 'armv5te':
+      # TODO(zra): This binary does not exist, yet. Check one in once we have
+      # sufficient stability.
+      name = 'dart-armv5te'
+    elif arch == 'armv6':
+      # TODO(zra): Ditto.
+      name = 'dart-armv6'
   return os.path.join(CheckedInSdkPath(), 'bin', name)