Version 1.17.0-dev.0.0

Merge a47eb0f59e5fb8e59cc9cb994fecd7f474c16018 into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index af5ee69..b247533 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,15 +1,109 @@
-## 1.16.0
+## 1.17.0
+
+### Core library changes
+* `dart:core`
+  * `Uri.replace` supports iterables as values for the query parameters.
+  * `Uri.parseIPv6Address` returns a `Uint8List`.
+
+* `dart:io`
+  * Added `NetworkInterface.listSupported`, which is `true` when
+    `NetworkInterface.list` is supported, and `false` otherwise. Currently,
+    `NetworkInterface.list` is not supported on Android.
+
+## 1.16.0 - 2016-04-26
 
 ### Core library changes
 
 * `dart:convert`
   * Added `BASE64URL` codec and corresponding `Base64Codec.urlSafe` constructor.
+
+  * Introduce `ChunkedConverter` and deprecate chunked methods on `Converter`.
+
+* `dart:html`
+
+  There have been a number of **BREAKING** changes to align APIs with recent
+  changes in Chrome. These include:
+
+  * Chrome's `ShadowRoot` interface no longer has the methods `getElementById`,
+    `getElementsByClassName`, and `getElementsByTagName`, e.g.,
+
+    ```dart
+    elem.shadowRoot.getElementsByClassName('clazz')
+    ```
+
+    should become:
+
+    ```dart
+    elem.shadowRoot.querySelectorAll('.clazz')
+    ```
+
+  * The `clipboardData` property has been removed from `KeyEvent`
+    and `Event`. It has been moved to the new `ClipboardEvent` class, which is
+    now used by `copy`, `cut`, and `paste` events.
+
+  * The `layer` property has been removed from `KeyEvent` and
+    `UIEvent`. It has been moved to `MouseEvent`.
+
+  * The `Point get page` property has been removed from `UIEvent`.
+    It still exists on `MouseEvent` and `Touch`.
+
+  There have also been a number of other additions and removals to `dart:html`,
+  `dart:indexed_db`, `dart:svg`, `dart:web_audio`, and `dart:web_gl` that
+  correspond to changes to Chrome APIs between v39 and v45. Many of the breaking
+  changes represent APIs that would have caused runtime exceptions when compiled
+  to Javascript and run on recent Chrome releases.
+
 * `dart:io`
   * Added `SecurityContext.alpnSupported`, which is true if a platform
     supports ALPN, and false otherwise.
 
-* `dart:convert`
-  * Introduce `ChunkedConverter` and deprecate chunked methods on `Converter`.
+### JavaScript interop
+
+For performance reasons, a potentially **BREAKING** change was added for
+libraries that use JS interop.
+Any Dart file that uses `@JS` annotations on declarations (top-level functions,
+classes or class members) to interop with JavaScript code will require that the
+file have the annotation `@JS()` on a library directive.
+
+```dart
+@JS()
+library my_library;
+```
+
+The analyzer will enforce this by generating the error:
+
+The `@JS()` annotation can only be used if it is also declared on the library
+directive.
+
+If part file uses the `@JS()` annotation, the library that uses the part should
+have the `@JS()` annotation e.g.,
+
+```dart
+// library_1.dart
+@JS()
+library library_1;
+
+import 'package:js/js.dart';
+
+part 'part_1.dart';
+```
+
+```dart
+// part_1.dart
+part of library_1;
+
+@JS("frameworkStabilizers")
+external List<FrameworkStabilizer> get frameworkStabilizers;
+```
+
+If your library already has a JS module e.g.,
+
+```dart
+@JS('array.utils')
+library my_library;
+```
+
+Then your library will work without any additional changes.
 
 ### Analyzer
 
diff --git a/DEPS b/DEPS
index 1f50fd4..c4bf8bb 100644
--- a/DEPS
+++ b/DEPS
@@ -31,7 +31,11 @@
   # Revisions of /third_party/* dependencies.
   "args_tag": "@0.13.4",
   "async_tag": "@1.9.0",
+  "barback-0.13.0_rev": "@34853",
+  "barback-0.14.0_rev": "@36398",
+  "barback-0.14.1_rev": "@38525",
   "barback_tag" : "@0.15.2+7",
+  "bazel_worker_tag": "@v0.1.0",
   "boolean_selector_tag" : "@1.0.0",
   "boringssl_rev" : "@daeafc22c66ad48f6b32fc8d3362eb9ba31b774e",
   "charcode_tag": "@1.1.0",
@@ -39,24 +43,26 @@
   "cli_util_tag" : "@0.0.1+2",
   "collection_rev": "@f6135e6350c63eb3f4dd12953b8d4363faff16fc",
   "convert_tag": "@1.0.0",
-  "crypto_rev" : "@2df57a1e26dd88e8d0614207d4b062c73209917d",
+  "crypto_tag" : "@1.1.0",
   "csslib_tag" : "@0.12.0",
   "dart2js_info_rev" : "@0a221eaf16aec3879c45719de656680ccb80d8a1",
-  "dartdoc_tag" : "@v0.9.0",
   "dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
   "dart_style_tag": "@0.2.4",
-  "dev_compiler_rev": "@0c5dd2d1e999c421d978a478e267aac6279e087a",
+  "dartdoc_tag" : "@v0.9.0",
+  "dev_compiler_rev": "@0ed6aeca35fa0e618ad0f7f19f3eba64afdd80c4",
+  "fixnum_tag": "@0.10.4",
+  "func_rev": "@8d4aea75c21be2179cb00dc2b94a71414653094e",
   "glob_rev": "@704cf75e4f26b417505c5c611bdaacd8808467dd",
   "html_tag" : "@0.12.1+1",
-  "http_tag" : "@0.11.3+3",
   "http_multi_server_tag" : "@2.0.0",
   "http_parser_tag" : "@1.1.0",
+  "http_tag" : "@0.11.3+3",
   "http_throttle_rev" : "@a81f08be942cdd608883c7b67795c12226abc235",
   "idl_parser_rev": "@7fbe68cab90c38147dee4f48c30ad0d496c17915",
   "intl_rev": "@a8b480b9c436f6c0ec16730804c914bdb4e30d53",
   "jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_tag": "@2.0.0",
-  "linter_rev": "@bcd4cf615665a80edf3f9a924388e59644a667cd",
+  "linter_rev": "@6d3bdf09b4326a411e44ff472953edd9003bc33a",
   "logging_rev": "@85d83e002670545e9039ad3985f0018ab640e597",
   "markdown_rev": "@4aaadf3d940bb172e1f6285af4d2b1710d309982",
   "matcher_tag": "@0.12.0",
@@ -64,49 +70,46 @@
   "mime_rev": "@75890811d4af5af080351ba8a2853ad4c8df98dd",
   "mustache4dart_rev" : "@5724cfd85151e5b6b53ddcd3380daf188fe47f92",
   "oauth2_tag": "@1.0.0",
-  "observe_rev": "@eee2b8ec34236fa46982575fbccff84f61202ac6",
   "observatory_pub_packages_rev": "@cf90eb9077177d3d6b3fd5e8289477c2385c026a",
+  "observe_rev": "@eee2b8ec34236fa46982575fbccff84f61202ac6",
   "package_config_rev": "@0.1.3",
   "path_tag": "@1.3.6",
-  "ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
   "plugin_tag": "@0.1.0",
+  "ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_tag": "@1.2.1",
-  "protobuf_tag": "@0.5.0+1",
-  "pub_rev": "@04ff0cc2cb6a3b698159b1aeef14cd3d7c90e287",
+  "protobuf_tag": "@0.5.1+1",
   "pub_cache_tag": "@v0.1.0",
+  "pub_rev": "@217fc8ae2bdee58ebf4b11a6fa3d49624d90c0c4",
   "pub_semver_tag": "@1.2.1",
   "quiver_tag": "@0.21.4",
   "resource_rev":"@a49101ba2deb29c728acba6fb86000a8f730f4b1",
   "root_certificates_rev": "@aed07942ce98507d2be28cbd29e879525410c7fc",
   "scheduled_test_tag": "@0.12.5+2",
-  "shelf_tag": "@0.6.5",
-  "smoke_rev" : "@f3361191cc2a85ebc1e4d4c33aec672d7915aba9",
-  "source_maps_tag": "@0.10.1",
   "shelf_static_tag": "@0.2.3+1",
+  "shelf_tag": "@0.6.5",
   "shelf_web_socket_tag": "@0.2.0",
+  "smoke_rev" : "@f3361191cc2a85ebc1e4d4c33aec672d7915aba9",
   "source_map_stack_trace_tag": "@1.0.4",
+  "source_maps-0.9.4_rev": "@38524",
+  "source_maps_tag": "@0.10.1",
   "source_span_tag": "@1.2.0",
   "stack_trace_tag": "@1.4.2",
   "stream_channel_tag": "@1.3.1",
   "string_scanner_tag": "@0.1.4",
   "sunflower_rev": "@879b704933413414679396b129f5dfa96f7a0b1e",
-  "test_tag": "@0.12.12",
   "test_reflective_loader_tag": "@0.0.3",
+  "test_tag": "@0.12.12",
   "typed_data_tag": "@1.1.2",
-  "utf_rev": "@1f55027068759e2d52f2c12de6a57cce5f3c5ee6",
   "usage_rev": "@b5080dac0d26a5609b266f8fdb0d053bc4c1c638",
+  "utf_rev": "@1f55027068759e2d52f2c12de6a57cce5f3c5ee6",
   "watcher_tag": "@0.9.7",
-  "when_tag": "@0.2.0+2",
-  "which_tag": "@0.1.3+1",
   "web_components_rev": "@6349e09f9118dce7ae1b309af5763745e25a9d61",
   "web_socket_channel_tag": "@1.0.0",
   "WebCore_rev": "@a86fe28efadcfc781f836037a80f27e22a5dad17",
+  "when_tag": "@0.2.0+2",
+  "which_tag": "@0.1.3+1",
   "yaml_tag": "@2.1.5",
   "zlib_rev": "@c3d0a6190f2f8c924a05ab6cc97b8f975bddd33f",
-  "barback-0.13.0_rev": "@34853",
-  "barback-0.14.0_rev": "@36398",
-  "barback-0.14.1_rev": "@38525",
-  "source_maps-0.9.4_rev": "@38524",
 }
 
 deps = {
@@ -150,6 +153,8 @@
       (Var("github_mirror") % "async") + Var("async_tag"),
   Var("dart_root") + "/third_party/pkg/barback":
       (Var("github_mirror") % "barback") + Var("barback_tag"),
+  Var("dart_root") + "/third_party/pkg/bazel_worker":
+      (Var("github_dartlang") % "bazel_worker") + Var("bazel_worker_tag"),
   Var("dart_root") + "/third_party/pkg/boolean_selector":
       (Var("github_dartlang") % "boolean_selector") +
       Var("boolean_selector_tag"),
@@ -162,7 +167,7 @@
   Var("dart_root") + "/third_party/pkg/convert":
       "https://github.com/dart-lang/convert.git" + Var("convert_tag"),
   Var("dart_root") + "/third_party/pkg/crypto":
-      (Var("github_mirror") % "crypto") + Var("crypto_rev"),
+      (Var("github_mirror") % "crypto") + Var("crypto_tag"),
   Var("dart_root") + "/third_party/pkg/csslib":
       (Var("github_mirror") % "csslib") + Var("csslib_tag"),
   Var("dart_root") + "/third_party/dart-services":
@@ -176,6 +181,10 @@
       (Var("github_mirror") % "dartdoc") + Var("dartdoc_tag"),
   Var("dart_root") + "/third_party/pkg/dev_compiler":
       (Var("github_mirror") % "dev_compiler") + Var("dev_compiler_rev"),
+  Var("dart_root") + "/third_party/pkg/func":
+      (Var("github_dartlang") % "func") + Var("func_rev"),
+  Var("dart_root") + "/third_party/pkg/fixnum":
+      "https://github.com/dart-lang/fixnum.git" + Var("fixnum_tag"),
   Var("dart_root") + "/third_party/pkg/glob":
       (Var("github_mirror") % "glob") + Var("glob_rev"),
   Var("dart_root") + "/third_party/pkg/html":
diff --git a/dart.gyp b/dart.gyp
index b8d3e43f..b942371 100644
--- a/dart.gyp
+++ b/dart.gyp
@@ -26,9 +26,35 @@
       'type': 'none',
       'dependencies': [
         'runtime/dart-runtime.gyp:dart',
-        'runtime/dart-runtime.gyp:dart_noopt',
+        'runtime/dart-runtime.gyp:dart_bootstrap#host',
+        'runtime/dart-runtime.gyp:run_vm_tests',
+        'runtime/dart-runtime.gyp:process_test',
+        'packages',
+        'runtime/dart-runtime.gyp:test_extension',
+        'runtime/dart-runtime.gyp:sample_extension',
+      ],
+    },
+    {
+      # This is the target that is built on the VM build bots.  It
+      # must depend on anything that is required by the VM test
+      # suites.
+      'target_name': 'runtime_precompiled',
+      'type': 'none',
+      'dependencies': [
         'runtime/dart-runtime.gyp:dart_precompiled_runtime',
-        'runtime/dart-runtime.gyp:dart_product',
+        'runtime/dart-runtime.gyp:dart_bootstrap#host',
+        'packages',
+      ],
+    },
+    {
+      # This is the target that is built on the VM build bots.  It
+      # must depend on anything that is required by the VM test
+      # suites.
+      'target_name': 'runtime_and_noopt',
+      'type': 'none',
+      'dependencies': [
+        'runtime/dart-runtime.gyp:dart',
+        'runtime/dart-runtime.gyp:dart_noopt',
         'runtime/dart-runtime.gyp:dart_bootstrap#host',
         'runtime/dart-runtime.gyp:run_vm_tests',
         'runtime/dart-runtime.gyp:process_test',
diff --git a/pkg/analysis_server/lib/plugin/analysis/navigation/navigation_core.dart b/pkg/analysis_server/lib/plugin/analysis/navigation/navigation_core.dart
index dea288b..52eb74c 100644
--- a/pkg/analysis_server/lib/plugin/analysis/navigation/navigation_core.dart
+++ b/pkg/analysis_server/lib/plugin/analysis/navigation/navigation_core.dart
@@ -5,7 +5,7 @@
 library analysis_server.plugin.analysis.navigation.navigation_core;
 
 import 'package:analysis_server/plugin/protocol/protocol.dart'
-    show ElementKind, Location, NavigationRegion, NavigationTarget;
+    show ElementKind, Location;
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
 import 'package:analyzer/src/generated/source.dart' show Source;
 
diff --git a/pkg/analysis_server/lib/plugin/analysis/occurrences/occurrences_core.dart b/pkg/analysis_server/lib/plugin/analysis/occurrences/occurrences_core.dart
index ac56afd..cab96a9 100644
--- a/pkg/analysis_server/lib/plugin/analysis/occurrences/occurrences_core.dart
+++ b/pkg/analysis_server/lib/plugin/analysis/occurrences/occurrences_core.dart
@@ -4,8 +4,7 @@
 
 library analysis_server.plugin.analysis.occurrences.occurrences_core;
 
-import 'package:analysis_server/plugin/protocol/protocol.dart'
-    show Element, Occurrences;
+import 'package:analysis_server/plugin/protocol/protocol.dart' show Occurrences;
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
 import 'package:analyzer/src/generated/source.dart' show Source;
 
diff --git a/pkg/analysis_server/lib/src/analysis_manager.dart b/pkg/analysis_server/lib/src/analysis_manager.dart
index 2e9924c..126dbb8 100644
--- a/pkg/analysis_server/lib/src/analysis_manager.dart
+++ b/pkg/analysis_server/lib/src/analysis_manager.dart
@@ -36,11 +36,12 @@
    * Otherwise there was no attached process or the signal could not be sent,
    * usually meaning that the process is already dead.
    */
-  Future<bool> stop() {
+  Future<bool> stop() async {
     if (process == null) {
-      return channel.close().then((_) => false);
+      await channel.close();
+      return false;
     }
-    return channel
+    int result = await channel
         .sendRequest(new ServerShutdownParams().toRequest('0'))
         .timeout(new Duration(seconds: 2), onTimeout: () {
       print('Expected shutdown response');
@@ -49,12 +50,11 @@
     }).timeout(new Duration(seconds: 2), onTimeout: () {
       print('Expected server to shutdown');
       process.kill();
-    }).then((int result) {
-      if (result != null && result != 0) {
-        exitCode = result;
-      }
-      return true;
     });
+    if (result != null && result != 0) {
+      exitCode = result;
+    }
+    return true;
   }
 
   /**
@@ -102,7 +102,7 @@
   /**
    * Open a connection to the analysis server using the given URL.
    */
-  Future<AnalysisManager> _openConnection(String serverUrl) {
+  Future<AnalysisManager> _openConnection(String serverUrl) async {
     Function onError = (error) {
       exitCode = 1;
       if (process != null) {
@@ -111,13 +111,9 @@
       throw 'Failed to connect to analysis server at $serverUrl\n  $error';
     };
     try {
-      return WebSocket
-          .connect(serverUrl)
-          .catchError(onError)
-          .then((WebSocket socket) {
-        this.channel = new WebSocketClientChannel(socket);
-        return this;
-      });
+      WebSocket socket = await WebSocket.connect(serverUrl).catchError(onError);
+      this.channel = new WebSocketClientChannel(socket);
+      return this;
     } catch (error) {
       onError(error);
     }
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 6bda5f9..5a06a6e 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -22,6 +22,7 @@
 import 'package:analysis_server/src/services/index/index.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analysis_server/src/services/search/search_engine_internal.dart';
+import 'package:analysis_server/src/single_context_manager.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/file_system/file_system.dart';
@@ -312,8 +313,9 @@
       this.options,
       this.defaultSdkCreator,
       this.instrumentationService,
-      {ResolverProvider packageResolverProvider: null,
-      EmbeddedResolverProvider embeddedResolverProvider: null,
+      {EmbeddedResolverProvider embeddedResolverProvider: null,
+      ResolverProvider packageResolverProvider: null,
+      bool useSingleContextManager: false,
       this.rethrowExceptions: true})
       : index = _index,
         searchEngine = _index != null ? new SearchEngineImpl(_index) : null {
@@ -326,15 +328,20 @@
     defaultContextOptions.generateImplicitErrors = false;
     operationQueue = new ServerOperationQueue();
     sdkManager = new DartSdkManager(defaultSdkCreator);
-    contextManager = new ContextManagerImpl(
-        resourceProvider,
-        sdkManager,
-        packageResolverProvider,
-        embeddedResolverProvider,
-        packageMapProvider,
-        analyzedFilesGlobs,
-        instrumentationService,
-        defaultContextOptions);
+    if (useSingleContextManager) {
+      contextManager = new SingleContextManager(resourceProvider, sdkManager,
+          () => packageResolverProvider(null), analyzedFilesGlobs);
+    } else {
+      contextManager = new ContextManagerImpl(
+          resourceProvider,
+          sdkManager,
+          packageResolverProvider,
+          embeddedResolverProvider,
+          packageMapProvider,
+          analyzedFilesGlobs,
+          instrumentationService,
+          defaultContextOptions);
+    }
     ServerContextManagerCallbacks contextManagerCallbacks =
         new ServerContextManagerCallbacks(this, resourceProvider);
     contextManager.callbacks = contextManagerCallbacks;
@@ -1583,6 +1590,13 @@
       analysisServer._computingPackageMap(computing);
 
   @override
+  void moveContext(Folder from, Folder to) {
+    // There is nothing to do.
+    // This method is mostly for tests.
+    // Context managers manage folders and contexts themselves.
+  }
+
+  @override
   void removeContext(Folder folder, List<String> flushedFiles) {
     AnalysisContext context = analysisServer.folderMap.remove(folder);
     sendAnalysisNotificationFlushResults(analysisServer, flushedFiles);
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 3afe0f2..a87fdc5 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -335,6 +335,12 @@
   void computingPackageMap(bool computing);
 
   /**
+   * Called when the context manager changes the folder with which a context is
+   * associated. Currently this is mostly FYI, and used only in tests.
+   */
+  void moveContext(Folder from, Folder to);
+
+  /**
    * Remove the context associated with the given [folder].  [flushedFiles] is
    * a list of the files which will be "orphaned" by removing this context
    * (they will no longer be analyzed by any context).
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index df307fb..6dc2c43 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -14,10 +14,7 @@
 import 'package:analysis_server/src/context_manager.dart';
 import 'package:analysis_server/src/domains/analysis/navigation.dart';
 import 'package:analysis_server/src/operation/operation_analysis.dart'
-    show
-        NavigationOperation,
-        OccurrencesOperation,
-        sendAnalysisNotificationNavigation;
+    show NavigationOperation, OccurrencesOperation;
 import 'package:analysis_server/src/protocol/protocol_internal.dart';
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/services/dependencies/library_dependencies.dart';
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 6bdf510..97a162e 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
@@ -20,6 +20,7 @@
 const int DART_RELEVANCE_COMMON_USAGE = 1200;
 const int DART_RELEVANCE_DEFAULT = 1000;
 const int DART_RELEVANCE_HIGH = 2000;
+const int DART_RELEVANCE_INCREMENT = 20;
 const int DART_RELEVANCE_INHERITED_ACCESSOR = 1057;
 const int DART_RELEVANCE_INHERITED_FIELD = 1058;
 const int DART_RELEVANCE_INHERITED_METHOD = 1057;
@@ -114,7 +115,17 @@
    * Any information obtained from [target] prior to calling this method
    * should be discarded as it may have changed.
    */
-  Future resolveExpression(Expression expression);
+  Future resolveContainingExpression(AstNode node);
+
+  /**
+   * Return a [Future] that completes when the element associated with
+   * the given [statement] in the target compilation unit is available.
+   * It may also complete if the statement cannot be resolved
+   * (e.g. unknown identifier, completion aborted, etc).
+   * Any information obtained from [target] prior to calling this method
+   * should be discarded as it may have changed.
+   */
+  Future resolveContainingStatement(AstNode node);
 
   /**
      * Return a [Future] that completes with a list of [ImportElement]s
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_plugin.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_plugin.dart
index ea6b489..cf34c94 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_plugin.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_plugin.dart
@@ -24,6 +24,7 @@
 import 'package:analysis_server/src/services/completion/dart/static_member_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/type_member_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/uri_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/variable_name_contributor.dart';
 import 'package:plugin/plugin.dart';
 
 /**
@@ -115,6 +116,8 @@
         () => new TypeMemberContributor());
     registerExtension(DART_COMPLETION_CONTRIBUTOR_EXTENSION_POINT_ID,
         () => new UriContributor());
+    registerExtension(DART_COMPLETION_CONTRIBUTOR_EXTENSION_POINT_ID,
+        () => new VariableNameContributor());
   }
 
   /**
diff --git a/pkg/analysis_server/lib/src/search/element_references.dart b/pkg/analysis_server/lib/src/search/element_references.dart
index 74c72ef..30ae422 100644
--- a/pkg/analysis_server/lib/src/search/element_references.dart
+++ b/pkg/analysis_server/lib/src/search/element_references.dart
@@ -64,12 +64,10 @@
   /**
    * Returns a [Future] completing with a [List] of references to [element].
    */
-  Future<List<SearchResult>> _findSingleElementReferences(Element element) {
-    Future<List<SearchMatch>> matchesFuture =
-        searchEngine.searchReferences(element);
-    return matchesFuture.then((List<SearchMatch> matches) {
-      return matches.map(toResult).toList();
-    });
+  Future<List<SearchResult>> _findSingleElementReferences(
+      Element element) async {
+    List<SearchMatch> matches = await searchEngine.searchReferences(element);
+    return matches.map(toResult).toList();
   }
 
   /**
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index f04824f..a5af1b22 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -310,6 +310,14 @@
   ResolverProvider packageResolverProvider;
 
   /**
+   * If this flag is `true`, then single analysis context should be used for
+   * analysis of multiple analysis roots, special files that could otherwise
+   * cause creating additional contexts, such as `pubspec.yaml`, or `.packages`,
+   * or `.analysis_options` are ignored.
+   */
+  bool useSingleContextManager = false;
+
+  /**
    * The plugins that are defined outside the analysis_server package.
    */
   List<Plugin> _userDefinedPlugins = <Plugin>[];
@@ -436,8 +444,9 @@
         defaultSdk,
         service,
         serverPlugin,
+        embeddedUriResolverProvider,
         packageResolverProvider,
-        embeddedUriResolverProvider);
+        useSingleContextManager);
     httpServer = new HttpAnalysisServer(socketServer);
     stdioServer = new StdioAnalysisServer(socketServer);
     socketServer.userDefinedPlugins = _userDefinedPlugins;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
index 54529b8..f29e7a6 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
@@ -181,7 +181,7 @@
     }
 
     // Resolve the target expression to determine the arguments
-    await request.resolveExpression(targetId);
+    await request.resolveContainingExpression(targetId);
     // Gracefully degrade if the element could not be resolved
     // e.g. target changed, completion aborted
     targetId = _getTargetId(request.target.containingNode);
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 21ba3c7..7be86e4 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
@@ -23,10 +23,9 @@
 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/context/context.dart' show AnalysisFutureHelper;
 import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/generated/engine.dart' hide AnalysisContextImpl;
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/dart.dart';
@@ -226,11 +225,24 @@
   }
 
   @override
-  Future resolveExpression(Expression expression) async {
+  Future resolveContainingExpression(AstNode node) async {
+    // TODO When an Expression can be resolved instead of just an entire unit,
+    // this will be revisited with code searching up the parent until an
+    // Expression is found.
+
+    return resolveContainingStatement(node);
+  }
+
+  @override
+  Future resolveContainingStatement(AstNode node) async {
+    // TODO When a Statement can be resolved instead of just an entire unit,
+    // this will be revisited with code searching up the parent until a
+    // Statement is found.
+
     checkAborted();
 
     // Return immediately if the expression has already been resolved
-    if (expression.propagatedType != null) {
+    if (node is Expression && node.propagatedType != null) {
       return;
     }
 
@@ -241,7 +253,7 @@
 
     // Resolve declarations in the target unit
     // TODO(danrubel) resolve the expression or containing method
-    // rather than the entire complilation unit
+    // rather than the entire compilation unit
     CompilationUnit resolvedUnit = await _computeAsync(
         this,
         new LibrarySpecificUnit(librarySource, source),
@@ -400,7 +412,7 @@
       if (node is Expression) {
         const FUNCTIONAL_ARG_TAG = 'resolve expression for isFunctionalArg';
         performance.logStartTime(FUNCTIONAL_ARG_TAG);
-        await dartRequest.resolveExpression(node);
+        await dartRequest.resolveContainingExpression(node);
         performance.logElapseTime(FUNCTIONAL_ARG_TAG);
         dartRequest.checkAborted();
       }
@@ -472,18 +484,15 @@
       }
       if (token is StringToken) {
         SimpleStringLiteral uri = new SimpleStringLiteral(token, token.lexeme);
-        Token previous = token.previous;
-        if (previous is KeywordToken) {
-          Keyword keyword = previous.keyword;
-          if (keyword == Keyword.IMPORT ||
-              keyword == Keyword.EXPORT ||
-              keyword == Keyword.PART) {
-            int start = uri.contentsOffset;
-            var end = uri.contentsEnd;
-            if (start <= requestOffset && requestOffset <= end) {
-              // Replacement range for import URI
-              return new ReplacementRange(start, end - start);
-            }
+        Keyword keyword = token.previous?.keyword;
+        if (keyword == Keyword.IMPORT ||
+            keyword == Keyword.EXPORT ||
+            keyword == Keyword.PART) {
+          int start = uri.contentsOffset;
+          var end = uri.contentsEnd;
+          if (start <= requestOffset && requestOffset <= end) {
+            // Replacement range for import URI
+            return new ReplacementRange(start, end - start);
           }
         }
       }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart
index 43514fb..62bda0c 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart
@@ -36,6 +36,10 @@
     // Compute the list of fields already referenced in the constructor
     List<String> referencedFields = new List<String>();
     for (FormalParameter param in constructorDecl.parameters.parameters) {
+      if (param is DefaultFormalParameter &&
+          param.parameter is FieldFormalParameter) {
+        param = (param as DefaultFormalParameter).parameter;
+      }
       if (param is FieldFormalParameter) {
         SimpleIdentifier fieldId = param.identifier;
         if (fieldId != null && fieldId != request.target.entity) {
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 4651491..89dd436 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
@@ -14,8 +14,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 
-import '../../../protocol_server.dart'
-    show CompletionSuggestion, CompletionSuggestionKind;
+import '../../../protocol_server.dart' show CompletionSuggestion;
 
 List<String> hiddenNamesIn(ImportElement importElem) {
   for (NamespaceCombinator combinator in importElem.combinators) {
@@ -58,10 +57,7 @@
     // then resolve the outermost/entire expression
     AstNode node = request.target.containingNode;
     if (node is Expression) {
-      while (node.parent is Expression) {
-        node = node.parent;
-      }
-      await request.resolveExpression(node);
+      await request.resolveContainingExpression(node);
 
       // Discard any cached target information
       // because it may have changed as a result of the resolution
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 4587864..12692c0 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
@@ -28,7 +28,7 @@
     }
 
     // Resolve the expression and the containing library
-    await request.resolveExpression(request.dotTarget);
+    await request.resolveContainingExpression(request.dotTarget);
 
     // Recompute the target since resolution may have changed it
     Expression targetId = request.dotTarget;
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 eb527a4..8778f6c 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
@@ -165,8 +165,16 @@
     List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
     if (!optype.isPrefixed) {
       if (optype.includeConstructorSuggestions) {
-        _Visitor visitor = new _Visitor(request, suggestions);
-        visitor.visit(request.target.containingNode);
+        AstNode node = request.target.containingNode;
+
+        await request.resolveContainingStatement(node);
+
+        // Discard any cached target information
+        // because it may have changed as a result of the resolution
+        node = request.target.containingNode;
+
+        _Visitor visitor = new _Visitor(request, suggestions, optype);
+        visitor.visit(node);
       }
     }
     return suggestions;
@@ -178,9 +186,10 @@
  */
 class _Visitor extends LocalDeclarationVisitor {
   final DartCompletionRequest request;
+  final OpType optype;
   final List<CompletionSuggestion> suggestions;
 
-  _Visitor(DartCompletionRequest request, this.suggestions)
+  _Visitor(DartCompletionRequest request, this.suggestions, this.optype)
       : request = request,
         super(request.offset);
 
@@ -237,6 +246,12 @@
     String completion = classDecl.name.name;
     SimpleIdentifier elemId;
 
+    int relevance = optype.constructorSuggestionsFilter(
+        classDecl.element?.type, DART_RELEVANCE_DEFAULT);
+    if (relevance == null) {
+      return;
+    }
+
     // Build a suggestion for explicitly declared constructor
     if (constructorDecl != null) {
       elemId = constructorDecl.name;
@@ -248,8 +263,8 @@
         }
       }
       if (elem != null) {
-        CompletionSuggestion suggestion =
-            createSuggestion(elem, completion: completion);
+        CompletionSuggestion suggestion = createSuggestion(elem,
+            completion: completion, relevance: relevance);
         if (suggestion != null) {
           suggestions.add(suggestion);
         }
@@ -264,7 +279,7 @@
       element.returnType = classDecl.name.name;
       CompletionSuggestion suggestion = new CompletionSuggestion(
           CompletionSuggestionKind.INVOCATION,
-          DART_RELEVANCE_DEFAULT,
+          relevance,
           completion,
           completion.length,
           0,
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 68beb6a..5c10beb 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,6 +11,7 @@
 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/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/visitor.dart';
@@ -45,13 +46,18 @@
   void visitClassElement(ClassElement element) {
     if (optype.includeTypeNameSuggestions) {
       // if includeTypeNameSuggestions, then use the filter
-      if (optype.typeNameSuggestionsFilter(element.type)) {
-        addSuggestion(element,
-            prefix: prefix, relevance: DART_RELEVANCE_DEFAULT);
+      int relevance = optype.typeNameSuggestionsFilter(
+          element.type, DART_RELEVANCE_DEFAULT);
+      if (relevance != null) {
+        addSuggestion(element, prefix: prefix, relevance: relevance);
       }
     }
     if (optype.includeConstructorSuggestions) {
-      _addConstructorSuggestions(element, DART_RELEVANCE_DEFAULT);
+      int relevance = optype.constructorSuggestionsFilter(
+          element.type, DART_RELEVANCE_DEFAULT);
+      if (relevance != null) {
+        _addConstructorSuggestions(element, relevance);
+      }
     }
   }
 
@@ -171,6 +177,16 @@
       return EMPTY_LIST;
     }
 
+    AstNode node = request.target.containingNode;
+
+    // If the target is in an expression
+    // then resolve the outermost/entire expression
+    await request.resolveContainingExpression(node);
+
+    // Discard any cached target information
+    // because it may have changed as a result of the resolution
+    node = request.target.containingNode;
+
     OpType optype = (request as DartCompletionRequestImpl).opType;
     LibraryElementSuggestionBuilder visitor =
         new LibraryElementSuggestionBuilder(request, optype);
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 8d613ce..750e623 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
@@ -160,11 +160,9 @@
         // If the target is in an expression
         // then resolve the outermost/entire expression
         AstNode node = request.target.containingNode;
+
         if (node is Expression) {
-          while (node.parent is Expression) {
-            node = node.parent;
-          }
-          await request.resolveExpression(node);
+          await request.resolveContainingExpression(node);
 
           // Discard any cached target information
           // because it may have changed as a result of the resolution
@@ -236,7 +234,7 @@
   @override
   void declaredClass(ClassDeclaration declaration) {
     if (optype.includeTypeNameSuggestions) {
-      _addLocalSuggestion(
+      _addLocalSuggestion_includeTypeNameSuggestions(
           declaration.name, NO_RETURN_TYPE, protocol.ElementKind.CLASS,
           isAbstract: declaration.isAbstract,
           isDeprecated: _isDeprecated(declaration));
@@ -246,8 +244,8 @@
   @override
   void declaredClassTypeAlias(ClassTypeAlias declaration) {
     if (optype.includeTypeNameSuggestions) {
-      _addLocalSuggestion(declaration.name, NO_RETURN_TYPE,
-          protocol.ElementKind.CLASS_TYPE_ALIAS,
+      _addLocalSuggestion_includeTypeNameSuggestions(declaration.name,
+          NO_RETURN_TYPE, protocol.ElementKind.CLASS_TYPE_ALIAS,
           isAbstract: true, isDeprecated: _isDeprecated(declaration));
     }
   }
@@ -255,7 +253,7 @@
   @override
   void declaredEnum(EnumDeclaration declaration) {
     if (optype.includeTypeNameSuggestions) {
-      _addLocalSuggestion(
+      _addLocalSuggestion_includeTypeNameSuggestions(
           declaration.name, NO_RETURN_TYPE, protocol.ElementKind.ENUM,
           isDeprecated: _isDeprecated(declaration));
     }
@@ -267,7 +265,8 @@
         (!optype.inStaticMethodBody || fieldDecl.isStatic)) {
       bool deprecated = _isDeprecated(fieldDecl) || _isDeprecated(varDecl);
       TypeName typeName = fieldDecl.fields.type;
-      _addLocalSuggestion(varDecl.name, typeName, protocol.ElementKind.FIELD,
+      _addLocalSuggestion_includeReturnValueSuggestions(
+          varDecl.name, typeName, protocol.ElementKind.FIELD,
           isDeprecated: deprecated,
           relevance: DART_RELEVANCE_LOCAL_FIELD,
           classDecl: fieldDecl.parent);
@@ -298,7 +297,8 @@
         elemKind = protocol.ElementKind.FUNCTION;
         relevance = DART_RELEVANCE_LOCAL_FUNCTION;
       }
-      _addLocalSuggestion(declaration.name, typeName, elemKind,
+      _addLocalSuggestion_includeReturnValueSuggestions(
+          declaration.name, typeName, elemKind,
           isDeprecated: _isDeprecated(declaration),
           param: declaration.functionExpression.parameters,
           relevance: relevance);
@@ -309,8 +309,8 @@
   void declaredFunctionTypeAlias(FunctionTypeAlias declaration) {
     if (optype.includeTypeNameSuggestions) {
       // TODO (danrubel) determine parameters and return type
-      _addLocalSuggestion(declaration.name, declaration.returnType,
-          protocol.ElementKind.FUNCTION_TYPE_ALIAS,
+      _addLocalSuggestion_includeTypeNameSuggestions(declaration.name,
+          declaration.returnType, protocol.ElementKind.FUNCTION_TYPE_ALIAS,
           isAbstract: true, isDeprecated: _isDeprecated(declaration));
     }
   }
@@ -323,7 +323,8 @@
   @override
   void declaredLocalVar(SimpleIdentifier id, TypeName typeName) {
     if (optype.includeReturnValueSuggestions) {
-      _addLocalSuggestion(id, typeName, protocol.ElementKind.LOCAL_VARIABLE,
+      _addLocalSuggestion_includeReturnValueSuggestions(
+          id, typeName, protocol.ElementKind.LOCAL_VARIABLE,
           relevance: DART_RELEVANCE_LOCAL_VARIABLE);
     }
   }
@@ -356,7 +357,8 @@
         param = declaration.parameters;
         relevance = DART_RELEVANCE_LOCAL_METHOD;
       }
-      _addLocalSuggestion(declaration.name, typeName, elemKind,
+      _addLocalSuggestion_includeReturnValueSuggestions(
+          declaration.name, typeName, elemKind,
           isAbstract: declaration.isAbstract,
           isDeprecated: _isDeprecated(declaration),
           classDecl: declaration.parent,
@@ -368,7 +370,8 @@
   @override
   void declaredParam(SimpleIdentifier id, TypeName typeName) {
     if (optype.includeReturnValueSuggestions) {
-      _addLocalSuggestion(id, typeName, protocol.ElementKind.PARAMETER,
+      _addLocalSuggestion_includeReturnValueSuggestions(
+          id, typeName, protocol.ElementKind.PARAMETER,
           relevance: DART_RELEVANCE_PARAMETER);
     }
   }
@@ -377,13 +380,51 @@
   void declaredTopLevelVar(
       VariableDeclarationList varList, VariableDeclaration varDecl) {
     if (optype.includeReturnValueSuggestions) {
-      _addLocalSuggestion(
+      _addLocalSuggestion_includeReturnValueSuggestions(
           varDecl.name, varList.type, protocol.ElementKind.TOP_LEVEL_VARIABLE,
           isDeprecated: _isDeprecated(varList) || _isDeprecated(varDecl),
           relevance: DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE);
     }
   }
 
+  void _addLocalSuggestion_includeTypeNameSuggestions(
+      SimpleIdentifier id, TypeName typeName, protocol.ElementKind elemKind,
+      {bool isAbstract: false,
+      bool isDeprecated: false,
+      ClassDeclaration classDecl,
+      FormalParameterList param,
+      int relevance: DART_RELEVANCE_DEFAULT}) {
+    relevance = optype.typeNameSuggestionsFilter(
+        _staticTypeOfIdentifier(id), relevance);
+    if (relevance != null) {
+      _addLocalSuggestion(id, typeName, elemKind,
+          isAbstract: isAbstract,
+          isDeprecated: isDeprecated,
+          classDecl: classDecl,
+          param: param,
+          relevance: relevance);
+    }
+  }
+
+  void _addLocalSuggestion_includeReturnValueSuggestions(
+      SimpleIdentifier id, TypeName typeName, protocol.ElementKind elemKind,
+      {bool isAbstract: false,
+      bool isDeprecated: false,
+      ClassDeclaration classDecl,
+      FormalParameterList param,
+      int relevance: DART_RELEVANCE_DEFAULT}) {
+    relevance = optype.returnValueSuggestionsFilter(
+        _staticTypeOfIdentifier(id), relevance);
+    if (relevance != null) {
+      _addLocalSuggestion(id, typeName, elemKind,
+          isAbstract: isAbstract,
+          isDeprecated: isDeprecated,
+          classDecl: classDecl,
+          param: param,
+          relevance: relevance);
+    }
+  }
+
   void _addLocalSuggestion(
       SimpleIdentifier id, TypeName typeName, protocol.ElementKind elemKind,
       {bool isAbstract: false,
@@ -402,14 +443,7 @@
           suggestion.completion.startsWith('_')) {
         suggestion.relevance = privateMemberRelevance;
       }
-      // if includeTypeNameSuggestions, then use the filter
-      if (optype.includeTypeNameSuggestions) {
-        if (optype.typeNameSuggestionsFilter(_staticTypeOfIdentifier(id))) {
-          suggestionMap.putIfAbsent(suggestion.completion, () => suggestion);
-        }
-      } else {
-        suggestionMap.putIfAbsent(suggestion.completion, () => suggestion);
-      }
+      suggestionMap.putIfAbsent(suggestion.completion, () => suggestion);
       suggestion.element = _createLocalElement(request.source, elemKind, id,
           isAbstract: isAbstract,
           isDeprecated: isDeprecated,
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
index 3314403..fdeca37 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
@@ -39,7 +39,7 @@
     }
 
     // Resolve the target to determine the type
-    await request.resolveExpression(targetId);
+    await request.resolveContainingExpression(targetId);
 
     // Recompute the target since resolution may have changed it
     AstNode node = request.target.containingNode;
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 d5f206c..e8cc82d 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
@@ -5,6 +5,7 @@
 library services.completion.dart.optype;
 
 import 'package:analysis_server/src/protocol_server.dart' hide Element;
+import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/provisional/completion/dart/completion_target.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -14,6 +15,8 @@
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
+typedef int SuggestionsFilter(DartType dartType, int relevance);
+
 /**
  * An [AstVisitor] for determining whether top level suggestions or invocation
  * suggestions should be made based upon the type of node in which the
@@ -26,16 +29,27 @@
   bool includeConstructorSuggestions = false;
 
   /**
+   * If [includeConstructorSuggestions] is set to true, then this function may
+   * be set to a non-default function to filter out potential suggestions (null)
+   * based on their static [DartType], or change the relative relevance by
+   * returning a higher or lower relevance.
+   */
+  SuggestionsFilter constructorSuggestionsFilter =
+      (DartType _, int relevance) => relevance;
+
+  /**
    * Indicates whether type names should be suggested.
    */
   bool includeTypeNameSuggestions = false;
 
   /**
-   * If [includeTypeNameSuggestions] is set to true, then this function may be
-   * set to the non-default function to filter out potential suggestions based
-   * on their static [DartType].
+   * If [includeTypeNameSuggestions] is set to true, then this function may
+   * be set to a non-default function to filter out potential suggestions (null)
+   * based on their static [DartType], or change the relative relevance by
+   * returning a higher or lower relevance.
    */
-  Function typeNameSuggestionsFilter = (DartType _) => true;
+  SuggestionsFilter typeNameSuggestionsFilter =
+      (DartType _, int relevance) => relevance;
 
   /**
    * Indicates whether setters along with methods and functions that
@@ -50,6 +64,15 @@
   bool includeReturnValueSuggestions = false;
 
   /**
+   * If [includeReturnValueSuggestions] is set to true, then this function may
+   * be set to a non-default function to filter out potential suggestions (null)
+   * based on their static [DartType], or change the relative relevance by
+   * returning a higher or lower relevance.
+   */
+  SuggestionsFilter returnValueSuggestionsFilter =
+      (DartType _, int relevance) => relevance;
+
+  /**
    * Indicates whether named arguments should be suggested.
    */
   bool includeNamedArgumentSuggestions = false;
@@ -65,6 +88,11 @@
   bool includeCaseLabelSuggestions = false;
 
   /**
+   * Indicates whether variable names should be suggested.
+   */
+  bool includeVarNameSuggestions = false;
+
+  /**
    * Indicates whether the completion location is in the body of a static method.
    */
   bool inStaticMethodBody = false;
@@ -99,18 +127,18 @@
   /**
    * Indicate whether only type names should be suggested
    */
-  bool get includeOnlyTypeNameSuggestions =>
-      includeTypeNameSuggestions &&
-      !includeNamedArgumentSuggestions &&
+  bool get includeOnlyNamedArgumentSuggestions =>
+      includeNamedArgumentSuggestions &&
+      !includeTypeNameSuggestions &&
       !includeReturnValueSuggestions &&
       !includeVoidReturnSuggestions;
 
   /**
    * Indicate whether only type names should be suggested
    */
-  bool get includeOnlyNamedArgumentSuggestions =>
-      includeNamedArgumentSuggestions &&
-      !includeTypeNameSuggestions &&
+  bool get includeOnlyTypeNameSuggestions =>
+      includeTypeNameSuggestions &&
+      !includeNamedArgumentSuggestions &&
       !includeReturnValueSuggestions &&
       !includeVoidReturnSuggestions;
 }
@@ -181,10 +209,14 @@
   void visitAsExpression(AsExpression node) {
     if (identical(entity, node.type)) {
       optype.includeTypeNameSuggestions = true;
-      optype.typeNameSuggestionsFilter = (DartType dartType) {
+      optype.typeNameSuggestionsFilter = (DartType dartType, int relevance) {
         DartType staticType = node.expression.staticType;
-        return staticType.isDynamic ||
-            (dartType.isSubtypeOf(staticType) && dartType != staticType);
+        if (staticType.isDynamic ||
+            (dartType.isSubtypeOf(staticType) && dartType != staticType)) {
+          return relevance;
+        } else {
+          return null;
+        }
       };
     }
   }
@@ -353,6 +385,10 @@
         optype.includeReturnValueSuggestions = true;
         optype.includeTypeNameSuggestions = true;
       }
+      if ((token.isSynthetic || token.lexeme == ';') &&
+          node.expression is Identifier) {
+        optype.includeVarNameSuggestions = true;
+      }
     }
   }
 
@@ -433,7 +469,7 @@
     optype.includeVoidReturnSuggestions = true;
     // TODO (danrubel) void return suggestions only belong after
     // the 2nd semicolon.  Return value suggestions only belong after the
-    // e1st or second semicolon.
+    // first or second semicolon.
   }
 
   @override
@@ -486,6 +522,29 @@
   void visitInstanceCreationExpression(InstanceCreationExpression node) {
     if (identical(entity, node.constructorName)) {
       optype.includeConstructorSuggestions = true;
+      optype.constructorSuggestionsFilter = (DartType dartType, int relevance) {
+        DartType localTypeAssertion = null;
+        if (node.parent is VariableDeclaration) {
+          VariableDeclaration varDeclaration =
+              node.parent as VariableDeclaration;
+          localTypeAssertion = varDeclaration.element.type;
+        } else if (node.parent is AssignmentExpression) {
+          AssignmentExpression assignmentExpression =
+              node.parent as AssignmentExpression;
+          localTypeAssertion = assignmentExpression.leftHandSide.staticType;
+        }
+        if (localTypeAssertion == null ||
+            dartType == null ||
+            localTypeAssertion.isDynamic) {
+          return relevance;
+        } else if (localTypeAssertion == dartType) {
+          return relevance + DART_RELEVANCE_INCREMENT;
+        } else if (dartType.isSubtypeOf(localTypeAssertion)) {
+          return relevance;
+        } else {
+          return null;
+        }
+      };
     }
   }
 
@@ -503,10 +562,14 @@
   void visitIsExpression(IsExpression node) {
     if (identical(entity, node.type)) {
       optype.includeTypeNameSuggestions = true;
-      optype.typeNameSuggestionsFilter = (DartType dartType) {
+      optype.typeNameSuggestionsFilter = (DartType dartType, int relevance) {
         DartType staticType = node.expression.staticType;
-        return staticType.isDynamic ||
-            (dartType.isSubtypeOf(staticType) && dartType != staticType);
+        if (staticType.isDynamic ||
+            (dartType.isSubtypeOf(staticType) && dartType != staticType)) {
+          return relevance;
+        } else {
+          return null;
+        }
       };
     }
   }
@@ -548,6 +611,18 @@
   void visitNamedExpression(NamedExpression node) {
     if (identical(entity, node.expression)) {
       optype.includeReturnValueSuggestions = true;
+      optype.returnValueSuggestionsFilter = (DartType dartType, int relevance) {
+        DartType type = node.element?.type;
+        if (type != null &&
+            dartType != null &&
+            !type.isDynamic &&
+            dartType.isSubtypeOf(type)) {
+          // is correct type
+          return relevance + DART_RELEVANCE_INCREMENT;
+        } else {
+          return relevance;
+        }
+      };
       optype.includeTypeNameSuggestions = true;
     }
   }
@@ -732,13 +807,26 @@
 
   @override
   void visitVariableDeclarationList(VariableDeclarationList node) {
-    if ((node.keyword == null || node.keyword.lexeme != 'var') &&
-        (node.type == null || identical(entity, node.type))) {
-      optype.includeTypeNameSuggestions = true;
+    if (node.keyword == null || node.keyword.lexeme != 'var') {
+      if (node.type == null || identical(entity, node.type)) {
+        optype.includeTypeNameSuggestions = true;
+      } else if (node.type != null && entity is VariableDeclaration) {
+        optype.includeVarNameSuggestions = true;
+      }
     }
   }
 
   @override
+  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+   if (entity is Token) {
+     Token token = entity;
+     if (token.isSynthetic || token.lexeme == ';') {
+       optype.includeVarNameSuggestions = true;
+     }
+   }
+  }
+
+  @override
   void visitVariableDeclarationStatement(VariableDeclarationStatement node) {}
 
   @override
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
index d950448..0fcb490 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
@@ -7,7 +7,7 @@
 import 'dart:async';
 
 import 'package:analysis_server/src/protocol_server.dart'
-    show CompletionSuggestion, CompletionSuggestionKind, SourceChange;
+    show CompletionSuggestion, CompletionSuggestionKind;
 import 'package:analysis_server/src/protocol_server.dart' as protocol
     hide CompletionSuggestion, CompletionSuggestionKind;
 import 'package:analysis_server/src/provisional/completion/completion_core.dart';
@@ -15,7 +15,7 @@
 import 'package:analysis_server/src/provisional/completion/dart/completion_target.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/dart/resolver/inheritance_manager.dart';
 import 'package:analyzer/src/generated/source.dart';
 
 /**
@@ -39,13 +39,14 @@
     // Generate a collection of inherited members
     ClassElement classElem = classDecl.element;
     InheritanceManager manager = new InheritanceManager(classElem.library);
-    MemberMap map = manager.getMapOfMembersInheritedFromInterfaces(classElem);
+    Map<String, ExecutableElement> map =
+        manager.getMembersInheritedFromInterfaces(classElem);
     List<String> memberNames = _computeMemberNames(map, classElem);
 
     // Build suggestions
     List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
     for (String memberName in memberNames) {
-      ExecutableElement element = map.get(memberName);
+      ExecutableElement element = map[memberName];
       // Gracefully degrade if the overridden element has not been resolved.
       if (element.returnType != null) {
         CompletionSuggestion suggestion =
@@ -106,11 +107,10 @@
    * implemented members of the class represented by the given [element].
    * The [map] is used to find all of the members that are inherited.
    */
-  List<String> _computeMemberNames(MemberMap map, ClassElement element) {
+  List<String> _computeMemberNames(
+      Map<String, ExecutableElement> map, ClassElement element) {
     List<String> memberNames = <String>[];
-    int count = map.size;
-    for (int i = 0; i < count; i++) {
-      String memberName = map.getKey(i);
+    for (String memberName in map.keys) {
       if (!_hasMember(element, memberName)) {
         memberNames.add(memberName);
       }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
index d7687f9..f280cb3 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
@@ -12,8 +12,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/visitor.dart';
 
-import '../../../protocol_server.dart'
-    show CompletionSuggestion, CompletionSuggestionKind;
+import '../../../protocol_server.dart' show CompletionSuggestion;
 
 /**
  * A contributor for calculating static member invocation / access suggestions
@@ -30,7 +29,7 @@
     }
 
     // Resolve the expression and the containing library
-    await request.resolveExpression(request.dotTarget);
+    await request.resolveContainingExpression(request.dotTarget);
 
     // Recompute the target since resolution may have changed it
     Expression targetId = request.dotTarget;
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 cd9dfc0..0cf9318 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
@@ -14,8 +14,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 
-import '../../../protocol_server.dart'
-    show CompletionSuggestion, CompletionSuggestionKind;
+import '../../../protocol_server.dart' show CompletionSuggestion;
 
 /**
  * A contributor for calculating instance invocation / access suggestions
@@ -33,7 +32,7 @@
     }
 
     // Resolve the expression and the containing library
-    await request.resolveExpression(parsedExpression);
+    await request.resolveContainingExpression(parsedExpression);
     LibraryElement containingLibrary = request.libraryElement;
     // Gracefully degrade if the library element could not be resolved
     // e.g. detached part file or source change
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
new file mode 100644
index 0000000..71ac473
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
@@ -0,0 +1,94 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library services.completion.contributor.dart.variableName;
+
+import 'dart:async';
+
+import 'package:analysis_server/src/protocol_server.dart'
+    show CompletionSuggestion, CompletionSuggestionKind;
+import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
+import 'package:analysis_server/src/services/completion/dart/completion_manager.dart'
+    show DartCompletionRequestImpl;
+import 'package:analysis_server/src/services/completion/dart/optype.dart';
+import 'package:analysis_server/src/services/correction/name_suggestion.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+
+CompletionSuggestion _createNameSuggestion(String name) {
+  if (name == null || name.isEmpty) {
+    return null;
+  }
+  return new CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER,
+      DART_RELEVANCE_DEFAULT, name, name.length, 0, false, false);
+}
+
+String _getStringName(Identifier id) {
+  if (id == null) {
+    return null;
+  }
+  if (id is SimpleIdentifier) {
+    return id.name;
+  } else if (id is PrefixedIdentifier) {
+    return id.identifier.name;
+  }
+  return id.name;
+}
+
+/**
+ * A contributor for calculating suggestions for variable names.
+ */
+class VariableNameContributor extends DartCompletionContributor {
+  @override
+  Future<List<CompletionSuggestion>> computeSuggestions(
+      DartCompletionRequest request) async {
+    OpType optype = (request as DartCompletionRequestImpl).opType;
+
+    // Collect suggestions from the specific child [AstNode] that contains
+    // the completion offset and all of its parents recursively.
+    if (optype.includeVarNameSuggestions) {
+      // Resolution not needed for this completion
+
+      AstNode node = request.target.containingNode;
+      String strName = null;
+      if (node is ExpressionStatement) {
+        if (node.expression is Identifier) {
+          strName = _getStringName(node.expression as Identifier);
+        }
+      } else if (node is VariableDeclarationList) {
+        strName = _getStringName(node.type.name);
+      } else if (node is TopLevelVariableDeclaration) {
+        // The parser parses 'Foo ' and 'Foo ;' differently, resulting in the
+        // following.
+        // 'Foo ': handled above
+        // 'Foo ;': TopLevelVariableDeclaration with type null, and a first
+        // variable of 'Foo'
+        VariableDeclarationList varDeclarationList = node.variables;
+        if (varDeclarationList.type != null) {
+          strName = _getStringName(varDeclarationList.type.name);
+        } else {
+          NodeList<VariableDeclaration> varDeclarations =
+              varDeclarationList.variables;
+          if (varDeclarations.length == 1) {
+            VariableDeclaration varDeclaration = varDeclarations.first;
+            strName = _getStringName(varDeclaration.name);
+          }
+        }
+      }
+      if (strName == null) {
+        return EMPTY_LIST;
+      }
+
+      List<String> variableNameSuggestions = getCamelWordCombinations(strName);
+      List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
+      for (String varName in variableNameSuggestions) {
+        CompletionSuggestion suggestion = _createNameSuggestion(varName);
+        if (suggestion != null) {
+          suggestions.add(suggestion);
+        }
+      }
+      return suggestions;
+    }
+    return EMPTY_LIST;
+  }
+}
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 fbbd9a8..244fb3d 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -234,7 +234,7 @@
     }
     // add edit
     Token keyword = declaredIdentifier.keyword;
-    if (keyword is KeywordToken && keyword.keyword == Keyword.VAR) {
+    if (keyword.keyword == Keyword.VAR) {
       SourceRange range = rangeToken(keyword);
       _addReplaceEdit(range, typeSource);
     } else {
@@ -338,7 +338,7 @@
     }
     // add edit
     Token keyword = declarationList.keyword;
-    if (keyword is KeywordToken && keyword.keyword == Keyword.VAR) {
+    if (keyword.keyword == Keyword.VAR) {
       SourceRange range = rangeToken(keyword);
       _addReplaceEdit(range, typeSource);
     } else {
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 6c3a1e6..b1dd15b 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -1647,7 +1647,6 @@
           VariableDeclarationList declarationList = variable.parent;
           Token keywordToken = declarationList.keyword;
           if (declarationList.variables.length == 1 &&
-              keywordToken is KeywordToken &&
               keywordToken.keyword == Keyword.FINAL) {
             if (declarationList.type != null) {
               SourceRange range =
diff --git a/pkg/analysis_server/lib/src/services/correction/name_suggestion.dart b/pkg/analysis_server/lib/src/services/correction/name_suggestion.dart
index c28dae5..12d8c29 100644
--- a/pkg/analysis_server/lib/src/services/correction/name_suggestion.dart
+++ b/pkg/analysis_server/lib/src/services/correction/name_suggestion.dart
@@ -12,6 +12,21 @@
 List<String> _KNOWN_METHOD_NAME_PREFIXES = ['get', 'is', 'to'];
 
 /**
+ * Returns all variants of names by removing leading words one by one.
+ */
+List<String> getCamelWordCombinations(String name) {
+  List<String> result = [];
+  List<String> parts = getCamelWords(name);
+  for (int i = 0; i < parts.length; i++) {
+    var s1 = parts[i].toLowerCase();
+    var s2 = parts.skip(i + 1).join();
+    String suggestion = '$s1$s2';
+    result.add(suggestion);
+  }
+  return result;
+}
+
+/**
  * Returns possible names for a variable with the given expected type and
  * expression assigned.
  */
@@ -23,12 +38,12 @@
     String nameFromExpression = _getBaseNameFromExpression(assignedExpression);
     if (nameFromExpression != null) {
       nameFromExpression = removeStart(nameFromExpression, '_');
-      _addAll(excluded, res, _getCamelWordCombinations(nameFromExpression));
+      _addAll(excluded, res, getCamelWordCombinations(nameFromExpression));
     }
     String nameFromParent =
         _getBaseNameFromLocationInParent(assignedExpression);
     if (nameFromParent != null) {
-      _addAll(excluded, res, _getCamelWordCombinations(nameFromParent));
+      _addAll(excluded, res, getCamelWordCombinations(nameFromParent));
     }
   }
   // use type
@@ -41,7 +56,7 @@
     } else if ('String' == typeName) {
       _addSingleCharacterName(excluded, res, 0x73);
     } else {
-      _addAll(excluded, res, _getCamelWordCombinations(typeName));
+      _addAll(excluded, res, getCamelWordCombinations(typeName));
     }
     res.remove(typeName);
   }
@@ -80,7 +95,7 @@
   }
   // split camel-case into separate suggested names
   Set<String> res = new Set();
-  _addAll(excluded, res, _getCamelWordCombinations(text));
+  _addAll(excluded, res, getCamelWordCombinations(text));
   return new List.from(res);
 }
 
@@ -200,18 +215,3 @@
   // unknown
   return null;
 }
-
-/**
- * Returns all variants of names by removing leading words one by one.
- */
-List<String> _getCamelWordCombinations(String name) {
-  List<String> result = [];
-  List<String> parts = getCamelWords(name);
-  for (int i = 0; i < parts.length; i++) {
-    var s1 = parts[i].toLowerCase();
-    var s2 = parts.skip(i + 1).join();
-    String suggestion = '$s1$s2';
-    result.add(suggestion);
-  }
-  return result;
-}
diff --git a/pkg/analysis_server/lib/src/services/correction/namespace.dart b/pkg/analysis_server/lib/src/services/correction/namespace.dart
index 9a83cb2..b0058aa 100644
--- a/pkg/analysis_server/lib/src/services/correction/namespace.dart
+++ b/pkg/analysis_server/lib/src/services/correction/namespace.dart
@@ -6,7 +6,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/dart/resolver/scope.dart';
 
 /**
  * Returns the [Element] exported from the given [LibraryElement].
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index 1603ef3..ca38579 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -17,7 +17,6 @@
 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/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
@@ -1413,16 +1412,13 @@
  */
 class TokenUtils {
   /**
-   * @return the first [KeywordToken] with given [Keyword], may be <code>null</code> if
-   *         not found.
+   * Return the first token in the list of [tokens] representing the given
+   * [keyword], or `null` if there is no such token.
    */
-  static KeywordToken findKeywordToken(List<Token> tokens, Keyword keyword) {
+  static Token findKeywordToken(List<Token> tokens, Keyword keyword) {
     for (Token token in tokens) {
-      if (token is KeywordToken) {
-        KeywordToken keywordToken = token;
-        if (keywordToken.keyword == keyword) {
-          return keywordToken;
-        }
+      if (token.keyword == keyword) {
+        return token;
       }
     }
     return null;
diff --git a/pkg/analysis_server/lib/src/single_context_manager.dart b/pkg/analysis_server/lib/src/single_context_manager.dart
new file mode 100644
index 0000000..bdc3a67
--- /dev/null
+++ b/pkg/analysis_server/lib/src/single_context_manager.dart
@@ -0,0 +1,504 @@
+// 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.
+
+library analysis_server.src.single_context_manager;
+
+import 'dart:async';
+import 'dart:core' hide Resource;
+import 'dart:math' as math;
+
+import 'package:analysis_server/src/context_manager.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/util/glob.dart';
+import 'package:path/path.dart' as path;
+import 'package:watcher/watcher.dart';
+
+/**
+ * A function that will return a [UriResolver] that can be used to resolve
+ * `package:` URIs in [SingleContextManager].
+ */
+typedef UriResolver PackageResolverProvider();
+
+/**
+ * Implementation of [ContextManager] that supports only one [AnalysisContext].
+ * So, sources from all analysis roots are added to this single context. All
+ * features that could otherwise cause creating additional contexts, such as
+ * presence of `pubspec.yaml` or `.packages` files, or `.analysis_options` files
+ * are ignored.
+ */
+class SingleContextManager implements ContextManager {
+  /**
+   * The [ResourceProvider] using which paths are converted into [Resource]s.
+   */
+  final ResourceProvider resourceProvider;
+
+  /**
+   * The context used to work with file system paths.
+   */
+  path.Context pathContext;
+
+  /**
+   * The manager used to access the SDK that should be associated with a
+   * particular context.
+   */
+  final DartSdkManager sdkManager;
+
+  /**
+   * A function that will return a [UriResolver] that can be used to resolve
+   * `package:` URIs.
+   */
+  final PackageResolverProvider packageResolverProvider;
+
+  /**
+   * A list of the globs used to determine which files should be analyzed.
+   */
+  final List<Glob> analyzedFilesGlobs;
+
+  /**
+   * The list of included paths (folders and files) most recently passed to
+   * [setRoots].
+   */
+  List<String> includedPaths = <String>[];
+
+  /**
+   * The list of excluded paths (folders and files) most recently passed to
+   * [setRoots].
+   */
+  List<String> excludedPaths = <String>[];
+
+  /**
+   * The map of package roots most recently passed to [setRoots].
+   */
+  Map<String, String> packageRoots = <String, String>{};
+
+  /**
+   * Same as [packageRoots], except that source folders have been normalized
+   * and non-folders have been removed.
+   */
+  Map<String, String> normalizedPackageRoots = <String, String>{};
+
+  @override
+  ContextManagerCallbacks callbacks;
+
+  /**
+   * The context in which everything is being analyzed.
+   */
+  AnalysisContext context;
+
+  /**
+   * The folder associated with the context.
+   */
+  Folder contextFolder;
+
+  /**
+   * The current watch subscriptions.
+   */
+  Map<String, StreamSubscription<WatchEvent>> watchSubscriptions =
+      new Map<String, StreamSubscription<WatchEvent>>();
+
+  /**
+   * The [packageResolverProvider] must not be `null`.
+   */
+  SingleContextManager(this.resourceProvider, this.sdkManager,
+      this.packageResolverProvider, this.analyzedFilesGlobs) {
+    pathContext = resourceProvider.pathContext;
+  }
+
+  @override
+  Iterable<AnalysisContext> get analysisContexts =>
+      context == null ? <AnalysisContext>[] : <AnalysisContext>[context];
+
+  @override
+  Map<Folder, AnalysisContext> get folderMap => {contextFolder: context};
+
+  @override
+  List<AnalysisContext> contextsInAnalysisRoot(Folder analysisRoot) {
+    if (context == null || !includedPaths.contains(analysisRoot.path)) {
+      return <AnalysisContext>[];
+    }
+    return <AnalysisContext>[context];
+  }
+
+  @override
+  AnalysisContext getContextFor(String path) {
+    if (context == null) {
+      return null;
+    } else if (_isContainedIn(includedPaths, path)) {
+      return context;
+    }
+    return null;
+  }
+
+  @override
+  bool isIgnored(String path) {
+    return !_isContainedIn(includedPaths, path) || _isExcludedPath(path);
+  }
+
+  @override
+  bool isInAnalysisRoot(String path) {
+    return _isContainedIn(includedPaths, path) &&
+        !_isContainedIn(excludedPaths, path);
+  }
+
+  @override
+  void refresh(List<Resource> roots) {
+    if (context != null) {
+      callbacks.removeContext(contextFolder, null);
+      context.dispose();
+      context = null;
+      contextFolder = null;
+      _cancelCurrentWatchSubscriptions();
+      setRoots(includedPaths, excludedPaths, packageRoots);
+    }
+  }
+
+  @override
+  void setRoots(List<String> includedPaths, List<String> excludedPaths,
+      Map<String, String> packageRoots) {
+    includedPaths = _nonOverlappingPaths(includedPaths);
+    excludedPaths = _nonOverlappingPaths(excludedPaths);
+    this.packageRoots = packageRoots;
+    _updateNormalizedPackageRoots();
+    // Update context path.
+    {
+      String contextPath = _commonPrefix(includedPaths);
+      Folder contextFolder = resourceProvider.getFolder(contextPath);
+      if (contextFolder != this.contextFolder) {
+        if (context != null) {
+          callbacks.moveContext(this.contextFolder, contextFolder);
+        }
+        this.contextFolder = contextFolder;
+      }
+    }
+    // Start new watchers and cancel old ones.
+    {
+      Map<String, StreamSubscription<WatchEvent>> newSubscriptions =
+          new Map<String, StreamSubscription<WatchEvent>>();
+      for (String includedPath in includedPaths) {
+        Resource resource = resourceProvider.getResource(includedPath);
+        if (resource is Folder) {
+          // Extract the existing subscription or create a new one.
+          StreamSubscription<WatchEvent> subscription =
+              watchSubscriptions.remove(includedPath);
+          if (subscription == null) {
+            subscription = resource.changes.listen(_handleWatchEvent);
+          }
+          // Remember the subscription.
+          newSubscriptions[includedPath] = subscription;
+        }
+        _cancelCurrentWatchSubscriptions();
+        this.watchSubscriptions = newSubscriptions;
+      }
+    }
+    // Create or update the analysis context.
+    if (context == null) {
+      UriResolver packageResolver = packageResolverProvider();
+      context = callbacks.addContext(contextFolder, new AnalysisOptionsImpl(),
+          new CustomPackageResolverDisposition(packageResolver));
+      ChangeSet changeSet =
+          _buildChangeSet(added: _includedFiles(includedPaths, excludedPaths));
+      callbacks.applyChangesToContext(contextFolder, changeSet);
+    } else {
+      // TODO(brianwilkerson) Optimize this.
+      List<File> oldFiles =
+          _includedFiles(this.includedPaths, this.excludedPaths);
+      List<File> newFiles = _includedFiles(includedPaths, excludedPaths);
+      ChangeSet changeSet = _buildChangeSet(
+          added: _diff(newFiles, oldFiles), removed: _diff(oldFiles, newFiles));
+      callbacks.applyChangesToContext(contextFolder, changeSet);
+    }
+    this.includedPaths = includedPaths;
+    this.excludedPaths = excludedPaths;
+  }
+
+  /**
+   * Recursively add the given [resource] (if it's a file) or its children (if
+   * it's a folder) to the [addedFiles].
+   */
+  void _addFilesInResource(
+      List<File> addedFiles, Resource resource, List<String> excludedPaths) {
+    if (_isImplicitlyExcludedResource(resource)) {
+      return;
+    }
+    String path = resource.path;
+    if (_isEqualOrWithinAny(excludedPaths, path)) {
+      return;
+    }
+    if (resource is File) {
+      if (_matchesAnyAnalyzedFilesGlob(path) && resource.exists) {
+        addedFiles.add(resource);
+      }
+    } else if (resource is Folder) {
+      for (Resource child in _getChildrenSafe(resource)) {
+        _addFilesInResource(addedFiles, child, excludedPaths);
+      }
+    }
+  }
+
+  ChangeSet _buildChangeSet({List<File> added, List<File> removed}) {
+    ChangeSet changeSet = new ChangeSet();
+    if (added != null) {
+      for (File file in added) {
+        Source source = createSourceInContext(context, file);
+        changeSet.addedSource(source);
+      }
+    }
+    if (removed != null) {
+      for (File file in removed) {
+        Source source = createSourceInContext(context, file);
+        changeSet.removedSource(source);
+      }
+    }
+    return changeSet;
+  }
+
+  void _cancelCurrentWatchSubscriptions() {
+    for (StreamSubscription<WatchEvent> subscription
+        in watchSubscriptions.values) {
+      subscription.cancel();
+    }
+    watchSubscriptions.clear();
+  }
+
+  String _commonPrefix(List<String> paths) {
+    if (paths.isEmpty) {
+      return '';
+    }
+    List<String> left = pathContext.split(paths[0]);
+    int count = left.length;
+    for (int i = 1; i < paths.length; i++) {
+      List<String> right = pathContext.split(paths[i]);
+      count = _commonComponents(left, count, right);
+    }
+    return pathContext.joinAll(left.sublist(0, count));
+  }
+
+  List<Resource> _existingResources(List<String> pathList) {
+    List<Resource> resources = <Resource>[];
+    for (String path in pathList) {
+      Resource resource = resourceProvider.getResource(path);
+      if (resource is Folder) {
+        resources.add(resource);
+      } else if (!resource.exists) {
+        // Non-existent resources are ignored.  TODO(paulberry): we should set
+        // up a watcher to ensure that if the resource appears later, we will
+        // begin analyzing it.
+      } else if (resource is File) {
+        resources.add(resource);
+      } else {
+        throw new UnimplementedError('$path is not a folder. '
+            'Only support for file and folder analysis is implemented.');
+      }
+    }
+    return resources;
+  }
+
+  void _handleWatchEvent(WatchEvent event) {
+    String path = event.path;
+    // Ignore if excluded.
+    if (_isExcludedPath(path)) {
+      return;
+    }
+    // Ignore if not in a root.
+    if (!_isContainedIn(includedPaths, path)) {
+      return;
+    }
+    // Handle the change.
+    switch (event.type) {
+      case ChangeType.ADD:
+        Resource resource = resourceProvider.getResource(path);
+        if (resource is File) {
+          if (_matchesAnyAnalyzedFilesGlob(path)) {
+            callbacks.applyChangesToContext(
+                contextFolder, _buildChangeSet(added: <File>[resource]));
+          }
+        }
+        break;
+      case ChangeType.REMOVE:
+        List<Source> sources = context.getSourcesWithFullName(path);
+        if (!sources.isEmpty) {
+          ChangeSet changeSet = new ChangeSet();
+          sources.forEach(changeSet.removedSource);
+          callbacks.applyChangesToContext(contextFolder, changeSet);
+        }
+        break;
+      case ChangeType.MODIFY:
+        List<Source> sources = context.getSourcesWithFullName(path);
+        if (!sources.isEmpty) {
+          ChangeSet changeSet = new ChangeSet();
+          sources.forEach(changeSet.changedSource);
+          callbacks.applyChangesToContext(contextFolder, changeSet);
+        }
+        break;
+    }
+  }
+
+  List<File> _includedFiles(
+      List<String> includedPaths, List<String> excludedPaths) {
+    List<Resource> includedResources = _existingResources(includedPaths);
+    List<File> includedFiles = <File>[];
+    for (Resource resource in includedResources) {
+      _addFilesInResource(includedFiles, resource, excludedPaths);
+    }
+    return includedFiles;
+  }
+
+  bool _isContainedIn(List<String> pathList, String path) {
+    for (String pathInList in pathList) {
+      if (_isEqualOrWithin(pathInList, path)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  bool _isEqualOrWithin(String parent, String child) {
+    return child == parent || pathContext.isWithin(parent, child);
+  }
+
+  bool _isEqualOrWithinAny(List<String> parents, String child) {
+    for (String parent in parents) {
+      if (_isEqualOrWithin(parent, child)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Return `true` if the given [path] should be excluded, using explicit
+   * or implicit rules.
+   */
+  bool _isExcludedPath(String path) {
+    List<String> parts = resourceProvider.pathContext.split(path);
+    // Implicit rules.
+    for (String part in parts) {
+      if (part.startsWith('.')) {
+        return true;
+      }
+    }
+    // Explicitly excluded paths.
+    if (_isEqualOrWithinAny(excludedPaths, path)) {
+      return true;
+    }
+    // OK
+    return false;
+  }
+
+  /**
+   * Return `true` if the given [resource] and children should be excluded
+   * because of some implicit exclusion rules, e.g. `.name`.
+   */
+  bool _isImplicitlyExcludedResource(Resource resource) {
+    String shortName = resource.shortName;
+    if (shortName.startsWith('.')) {
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Return `true` if the given [path] matches one of the [analyzedFilesGlobs].
+   */
+  bool _matchesAnyAnalyzedFilesGlob(String path) {
+    for (Glob glob in analyzedFilesGlobs) {
+      if (glob.matches(path)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Return a list consisting of the elements from [pathList] that describe the
+   * minimal set of directories that include everything in the original list of
+   * paths and nothing more. In particular:
+   *
+   *  * if a path is in the input list multiple times it will appear at most
+   *    once in the output list, and
+   *  * if a directory D and a subdirectory of it are both in the input list
+   *    then only the directory D will be in the output list.
+   *
+   * The original list is not modified.
+   */
+  List<String> _nonOverlappingPaths(List<String> pathList) {
+    List<String> sortedPaths = new List<String>.from(pathList);
+    sortedPaths.sort((a, b) => a.length - b.length);
+    int pathCount = sortedPaths.length;
+    for (int i = pathCount - 1; i > 0; i--) {
+      String path = sortedPaths[i];
+      for (int j = 0; j < i; j++) {
+        if (_isEqualOrWithin(path, sortedPaths[j])) {
+          sortedPaths.removeAt(i);
+          break;
+        }
+      }
+    }
+    return sortedPaths;
+  }
+
+  /**
+   *  Normalize all package root sources by mapping them to folders on the
+   * filesystem.  Ignore any package root sources that aren't folders.
+   */
+  void _updateNormalizedPackageRoots() {
+    normalizedPackageRoots = <String, String>{};
+    packageRoots.forEach((String sourcePath, String targetPath) {
+      Resource resource = resourceProvider.getResource(sourcePath);
+      if (resource is Folder) {
+        normalizedPackageRoots[resource.path] = targetPath;
+      }
+    });
+  }
+
+  /**
+   * Create and return a source representing the given [file] within the given
+   * [context].
+   */
+  static Source createSourceInContext(AnalysisContext context, File file) {
+    // TODO(brianwilkerson) Optimize this, by allowing support for source
+    // factories to restore URI's from a file path rather than a source.
+    Source source = file.createSource();
+    if (context == null) {
+      return source;
+    }
+    Uri uri = context.sourceFactory.restoreUri(source);
+    return file.createSource(uri);
+  }
+
+  static int _commonComponents(
+      List<String> left, int count, List<String> right) {
+    int max = math.min(count, right.length);
+    for (int i = 0; i < max; i++) {
+      if (left[i] != right[i]) {
+        return i;
+      }
+    }
+    return max;
+  }
+
+  /**
+   * Return a list of all the files in the [left] that are not in the [right].
+   */
+  static List<File> _diff(List<File> left, List<File> right) {
+    List<File> diff = new List.from(left);
+    for (File file in right) {
+      diff.remove(file);
+    }
+    return diff;
+  }
+
+  static List<Resource> _getChildrenSafe(Folder folder) {
+    try {
+      return folder.getChildren();
+    } on FileSystemException {
+      // The folder either doesn't exist or cannot be read.
+      // Either way, there are no children.
+      return const <Resource>[];
+    }
+  }
+}
diff --git a/pkg/analysis_server/lib/src/socket_server.dart b/pkg/analysis_server/lib/src/socket_server.dart
index c3f3fac..1da32a1 100644
--- a/pkg/analysis_server/lib/src/socket_server.dart
+++ b/pkg/analysis_server/lib/src/socket_server.dart
@@ -37,6 +37,7 @@
   final ServerPlugin serverPlugin;
   final EmbeddedResolverProvider embeddedResolverProvider;
   final ResolverProvider packageResolverProvider;
+  final bool useSingleContextManager;
 
   /**
    * The analysis server that was created when a client established a
@@ -55,8 +56,9 @@
       this.defaultSdk,
       this.instrumentationService,
       this.serverPlugin,
+      this.embeddedResolverProvider,
       this.packageResolverProvider,
-      this.embeddedResolverProvider);
+      this.useSingleContextManager);
 
   /**
    * Create an analysis server which will communicate with the client using the
@@ -98,8 +100,9 @@
         analysisServerOptions,
         defaultSdkCreator,
         instrumentationService,
-        packageResolverProvider: packageResolverProvider,
         embeddedResolverProvider: embeddedResolverProvider,
+        packageResolverProvider: packageResolverProvider,
+        useSingleContextManager: useSingleContextManager,
         rethrowExceptions: false);
     analysisServer.userDefinedPlugins = userDefinedPlugins;
   }
diff --git a/pkg/analysis_server/lib/src/watch_manager.dart b/pkg/analysis_server/lib/src/watch_manager.dart
index d4df4d5..04973b9 100644
--- a/pkg/analysis_server/lib/src/watch_manager.dart
+++ b/pkg/analysis_server/lib/src/watch_manager.dart
@@ -176,12 +176,12 @@
   /**
    * The parent of this node.
    */
-  WatchNode parent;
+  WatchNode<T> parent;
 
   /**
    * The information for the children of this node.
    */
-  final List<WatchNode> _children = <WatchNode>[];
+  final List<WatchNode<T>> _children = <WatchNode<T>>[];
 
   /**
    * The tokens that were used to register interest in watching this folder.
@@ -203,7 +203,7 @@
   /**
    * Return a list containing the children of this node.
    */
-  Iterable<WatchNode> get children => _children;
+  Iterable<WatchNode<T>> get children => _children;
 
   /**
    * Remove this node from the tree of watched folders.
@@ -220,11 +220,11 @@
    * [filePath]. If no other node is found, return this node, even if this node
    * does not contain the path.
    */
-  WatchNode findParent(String filePath) {
+  WatchNode<T> findParent(String filePath) {
     if (_children == null) {
       return this;
     }
-    for (WatchNode childNode in _children) {
+    for (WatchNode<T> childNode in _children) {
       if (childNode.folder.isOrContains(filePath)) {
         return childNode.findParent(filePath);
       }
@@ -237,8 +237,8 @@
    * of this node or as a descendent of one of this node's children. Return the
    * immediate parent of the newly added node.
    */
-  WatchNode insert(WatchNode node) {
-    WatchNode parentNode = findParent(node.folder.path);
+  WatchNode<T> insert(WatchNode<T> node) {
+    WatchNode<T> parentNode = findParent(node.folder.path);
     parentNode._addChild(node, true);
     return parentNode;
   }
@@ -256,11 +256,11 @@
    * existing children of this node should now be children of the new child, and
    * if so, move them.
    */
-  void _addChild(WatchNode newChild, bool checkChildren) {
+  void _addChild(WatchNode<T> newChild, bool checkChildren) {
     if (checkChildren) {
       Folder folder = newChild.folder;
       for (int i = _children.length - 1; i >= 0; i--) {
-        WatchNode existingChild = _children[i];
+        WatchNode<T> existingChild = _children[i];
         if (folder.contains(existingChild.folder.path)) {
           newChild._addChild(existingChild, false);
           _children.removeAt(i);
@@ -275,10 +275,10 @@
    * Remove the given [node] from the list of children of this node. Any
    * children of the [node] will become children of this node.
    */
-  void _removeChild(WatchNode child) {
+  void _removeChild(WatchNode<T> child) {
     _children.remove(child);
-    Iterable<WatchNode> grandchildren = child.children;
-    for (WatchNode grandchild in grandchildren) {
+    Iterable<WatchNode<T>> grandchildren = child.children;
+    for (WatchNode<T> grandchild in grandchildren) {
       grandchild.parent = this;
       _children.add(grandchild);
     }
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 123cabe..d20e599 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -2373,6 +2373,11 @@
    */
   final ResourceProvider resourceProvider;
 
+  /**
+   * The list of `flushedFiles` in the last [removeContext] invocation.
+   */
+  List<String> lastFlushedFiles;
+
   TestContextManagerCallbacks(this.resourceProvider);
 
   /**
@@ -2448,12 +2453,28 @@
   }
 
   @override
+  void moveContext(Folder from, Folder to) {
+    String path = from.path;
+    String path2 = to.path;
+    expect(currentContextFilePaths, contains(path));
+    expect(currentContextTimestamps, contains(path));
+    expect(currentContextSources, contains(path));
+    expect(currentContextFilePaths, isNot(contains(path2)));
+    expect(currentContextTimestamps, isNot(contains(path2)));
+    expect(currentContextSources, isNot(contains(path2)));
+    currentContextFilePaths[path2] = currentContextFilePaths.remove(path);
+    currentContextTimestamps[path2] = currentContextTimestamps.remove(path);
+    currentContextSources[path2] = currentContextSources.remove(path);
+  }
+
+  @override
   void removeContext(Folder folder, List<String> flushedFiles) {
     String path = folder.path;
     expect(currentContextPaths, contains(path));
     currentContextTimestamps.remove(path);
     currentContextFilePaths.remove(path);
     currentContextSources.remove(path);
+    lastFlushedFiles = flushedFiles;
   }
 
   @override
diff --git a/pkg/analysis_server/test/mocks.dart b/pkg/analysis_server/test/mocks.dart
index d47638f..4547bcc 100644
--- a/pkg/analysis_server/test/mocks.dart
+++ b/pkg/analysis_server/test/mocks.dart
@@ -6,8 +6,6 @@
 
 import 'dart:async';
 import 'dart:io';
-@MirrorsUsed(targets: 'mocks', override: '*')
-import 'dart:mirrors';
 
 import 'package:analysis_server/plugin/protocol/protocol.dart'
     hide Element, ElementKind;
@@ -283,15 +281,15 @@
  * A mock [WebSocket] for testing.
  */
 class MockSocket<T> implements WebSocket {
-  StreamController controller = new StreamController();
-  MockSocket twin;
-  Stream stream;
+  StreamController<T> controller = new StreamController<T>();
+  MockSocket<T> twin;
+  Stream<T> stream;
 
   MockSocket();
 
   factory MockSocket.pair() {
-    MockSocket socket1 = new MockSocket();
-    MockSocket socket2 = new MockSocket();
+    MockSocket<T> socket1 = new MockSocket<T>();
+    MockSocket<T> socket2 = new MockSocket<T>();
     socket1.twin = socket2;
     socket2.twin = socket1;
     socket1.stream = socket2.controller.stream;
@@ -315,7 +313,7 @@
 
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 
-  Stream<T> where(bool test(T)) => stream.where(test);
+  Stream<T> where(bool test(T t)) => stream.where(test);
 }
 
 class MockSource extends StringTypedMock implements Source {
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 72a57c7..dc011c1 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
@@ -369,6 +369,23 @@
     return cs;
   }
 
+  CompletionSuggestion assertSuggestName(
+      String name,
+      {int relevance: DART_RELEVANCE_DEFAULT,
+      String importUri,
+      CompletionSuggestionKind kind: CompletionSuggestionKind.IDENTIFIER,
+      bool isDeprecated: false}) {
+    CompletionSuggestion cs = assertSuggest(name,
+        csKind: kind,
+        relevance: relevance,
+        importUri: importUri,
+        isDeprecated: isDeprecated);
+    expect(cs.completion, equals(name));
+    expect(cs.element, isNull);
+    assertHasNoParameterInfo(cs);
+    return cs;
+  }
+
   CompletionSuggestion assertSuggestSetter(String name,
       {int relevance: DART_RELEVANCE_DEFAULT,
       String importUri,
diff --git a/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
index 2f39159..cc4d6f8 100644
--- a/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
@@ -164,4 +164,36 @@
     assertNotSuggested('Object');
     assertNotSuggested('==');
   }
+
+  test_ThisExpression_constructor_param_optional() async {
+    // SimpleIdentifier  FieldFormalParameter  FormalParameterList
+    addTestSource('''
+        main() { }
+        class Point {
+          int x;
+          int y;
+          Point({this.x, this.^}) {}
+          ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestField('y', 'int', relevance: DART_RELEVANCE_LOCAL_FIELD);
+    assertNotSuggested('x');
+  }
+
+  test_ThisExpression_constructor_param_positional() async {
+    // SimpleIdentifier  FieldFormalParameter  FormalParameterList
+    addTestSource('''
+        main() { }
+        class Point {
+          int x;
+          int y;
+          Point({this.x, this.^}) {}
+          ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestField('y', 'int', relevance: DART_RELEVANCE_LOCAL_FIELD);
+    assertNotSuggested('x');
+  }
 }
diff --git a/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart
index 172d767..0d1b13d 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart
@@ -2449,6 +2449,80 @@
     assertNotSuggested('Foo');
   }
 
+  test_InstanceCreationExpression_variable_declaration_filter() async {
+    addTestSource('''
+class A {} class B extends A {} class C implements A {} class D {}
+main() {
+  A a = new ^
+}''');
+    await computeSuggestions();
+
+    assertSuggestConstructor('A',
+        elemOffset: -1,
+        relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_INCREMENT);
+    assertSuggestConstructor('B',
+        elemOffset: -1, relevance: DART_RELEVANCE_DEFAULT);
+    assertSuggestConstructor('C',
+        elemOffset: -1, relevance: DART_RELEVANCE_DEFAULT);
+    assertNotSuggested('D');
+  }
+
+  test_InstanceCreationExpression_variable_declaration_filter2() async {
+    addTestSource('''
+class A {} class B extends A {} class C implements A {} class D {}
+main() {
+  A a = new ^;
+}''');
+    await computeSuggestions();
+
+    assertSuggestConstructor('A',
+        elemOffset: -1,
+        relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_INCREMENT);
+    assertSuggestConstructor('B',
+        elemOffset: -1, relevance: DART_RELEVANCE_DEFAULT);
+    assertSuggestConstructor('C',
+        elemOffset: -1, relevance: DART_RELEVANCE_DEFAULT);
+    assertNotSuggested('D');
+  }
+
+  test_InstanceCreationExpression_assignment_expression_filter() async {
+    addTestSource('''
+class A {} class B extends A {} class C implements A {} class D {}
+main() {
+  A a;
+  a = new ^
+}''');
+    await computeSuggestions();
+
+    assertSuggestConstructor('A',
+        elemOffset: -1,
+        relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_INCREMENT);
+    assertSuggestConstructor('B',
+        elemOffset: -1, relevance: DART_RELEVANCE_DEFAULT);
+    assertSuggestConstructor('C',
+        elemOffset: -1, relevance: DART_RELEVANCE_DEFAULT);
+    assertNotSuggested('D');
+  }
+
+  test_InstanceCreationExpression_assignment_expression_filter2() async {
+    addTestSource('''
+class A {} class B extends A {} class C implements A {} class D {}
+main() {
+  A a;
+  a = new ^;
+}''');
+    await computeSuggestions();
+
+    assertSuggestConstructor('A',
+        elemOffset: -1,
+        relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_INCREMENT);
+    assertSuggestConstructor('B',
+        elemOffset: -1, relevance: DART_RELEVANCE_DEFAULT);
+    assertSuggestConstructor('C',
+        elemOffset: -1, relevance: DART_RELEVANCE_DEFAULT);
+    assertNotSuggested('D');
+  }
+
   test_InterpolationExpression() async {
     // SimpleIdentifier  InterpolationExpression  StringInterpolation
     addSource(
diff --git a/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart
index eeab8d7..a53e433 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart
@@ -103,6 +103,114 @@
     assertNotSuggested('m');
   }
 
+  test_partFile_InstanceCreationExpression_variable_declaration_filter() async {
+    // ConstructorName  InstanceCreationExpression  VariableDeclarationList
+    addSource(
+        '/testB.dart',
+        '''
+        lib B;
+        int T1;
+        F1() { }
+        class X {X.c(); X._d(); z() {}}''');
+    addSource(
+        '/testA.dart',
+        '''
+        part of libA;
+        class A {} class B extends A {} class C implements A {} class D {}
+        ''');
+    addTestSource('''
+        library libA;
+        import "/testB.dart";
+        part "/testA.dart";
+        class Local { }
+        main() {
+          A a = new ^
+        }
+        var m;''');
+    await computeLibrariesContaining();
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    // A is suggested with a higher relevance
+    assertSuggestConstructor('A',
+        elemOffset: -1,
+        relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_INCREMENT);
+    assertSuggestConstructor('B',
+        elemOffset: -1, relevance: DART_RELEVANCE_DEFAULT);
+    assertSuggestConstructor('C',
+        elemOffset: -1, relevance: DART_RELEVANCE_DEFAULT);
+    // D is sorted out
+    assertNotSuggested('D');
+
+    // Suggested by ConstructorContributor
+    assertNotSuggested('Local');
+
+    // Suggested by ImportedReferenceContributor
+    assertNotSuggested('Object');
+    assertNotSuggested('X.c');
+    assertNotSuggested('X._d');
+    assertNotSuggested('F1');
+    assertNotSuggested('T1');
+    assertNotSuggested('_d');
+    assertNotSuggested('z');
+    assertNotSuggested('m');
+  }
+
+  test_partFile_InstanceCreationExpression_assignment_filter() async {
+    // ConstructorName  InstanceCreationExpression  VariableDeclarationList
+    addSource(
+        '/testB.dart',
+        '''
+        lib B;
+        int T1;
+        F1() { }
+        class X {X.c(); X._d(); z() {}}''');
+    addSource(
+        '/testA.dart',
+        '''
+        part of libA;
+        class A {} class B extends A {} class C implements A {} class D {}
+        ''');
+    addTestSource('''
+        library libA;
+        import "/testB.dart";
+        part "/testA.dart";
+        class Local { }
+        main() {
+          A a;
+          // FAIL:
+          a = new ^
+        }
+        var m;''');
+    await computeLibrariesContaining();
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    // A is suggested with a higher relevance
+    assertSuggestConstructor('A',
+        elemOffset: -1,
+        relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_INCREMENT);
+    assertSuggestConstructor('B',
+        elemOffset: -1, relevance: DART_RELEVANCE_DEFAULT);
+    assertSuggestConstructor('C',
+        elemOffset: -1, relevance: DART_RELEVANCE_DEFAULT);
+    // D is sorted out
+    assertNotSuggested('D');
+
+    // Suggested by ConstructorContributor
+    assertNotSuggested('Local');
+
+    // Suggested by ImportedReferenceContributor
+    assertNotSuggested('Object');
+    assertNotSuggested('X.c');
+    assertNotSuggested('X._d');
+    assertNotSuggested('F1');
+    assertNotSuggested('T1');
+    assertNotSuggested('_d');
+    assertNotSuggested('z');
+    assertNotSuggested('m');
+  }
+
   test_partFile_TypeName() async {
     addSource(
         '/testB.dart',
diff --git a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
index e617931..a61c9da 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
@@ -331,6 +331,45 @@
     assertNotSuggested('main');
   }
 
+  test_ArgumentList_namedParam_filter() async {
+    // SimpleIdentifier  NamedExpression  ArgumentList
+    // InstanceCreationExpression
+    addTestSource('''
+        class A {}
+        class B extends A {}
+        class C implements A {}
+        class D {}
+        class E {
+          A a;
+          E({A someA});
+        }
+        A a = new A();
+        B b = new B();
+        C c = new C();
+        D d = new D();
+        E e = new E(someA: ^);
+  ''');
+    await computeSuggestions();
+
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestTopLevelVar('a', 'A',
+        relevance:
+        DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE + DART_RELEVANCE_INCREMENT);
+    assertSuggestTopLevelVar('b', 'B',
+        relevance:
+        DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE + DART_RELEVANCE_INCREMENT);
+    assertSuggestTopLevelVar('c', 'C',
+        relevance:
+        DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE + DART_RELEVANCE_INCREMENT);
+    assertSuggestTopLevelVar('d', 'D',
+        relevance: DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE);
+    assertSuggestTopLevelVar('e', 'E',
+        relevance: DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE);
+  }
+
+
+
   test_AsExpression_type() async {
     // SimpleIdentifier  TypeName  AsExpression
     addTestSource('''
@@ -362,7 +401,7 @@
     assertNotSuggested('Object');
   }
 
-  test_IsExpression_type_filter_implements() async {
+  test_AsExpression_type_filter_implements() async {
     // SimpleIdentifier  TypeName  AsExpression
     addTestSource('''
 class A {} class B implements A {} class C implements A {} class D {}
@@ -378,6 +417,18 @@
     assertNotSuggested('Object');
   }
 
+  test_AsExpression_type_filter_undefined_type() async {
+    // SimpleIdentifier  TypeName  AsExpression
+    addTestSource('''
+class A {}
+f(U u){ (u as ^) }''');
+    await computeSuggestions();
+
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestClass('A');
+  }
+
   test_AssignmentExpression_name() async {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // VariableDeclarationStatement  Block
@@ -2767,21 +2818,6 @@
     assertNotSuggested('Object');
   }
 
-  test_IsExpression_type_partial() async {
-    // SimpleIdentifier  TypeName  IsExpression  IfStatement
-    addTestSource('''
-class A {int x; int y() => 0;}
-main(){var a; if (a is Obj^)}''');
-    await computeSuggestions();
-
-    expect(replacementOffset, completionOffset - 3);
-    expect(replacementLength, 3);
-    assertNotSuggested('a');
-    assertNotSuggested('main');
-    assertSuggestClass('A');
-    assertNotSuggested('Object');
-  }
-
   test_IsExpression_type_filter_extends() async {
     // SimpleIdentifier  TypeName  IsExpression  IfStatement
     addTestSource('''
@@ -2798,10 +2834,10 @@
     assertNotSuggested('Object');
   }
 
-  test_IsExpression_type_subtype_implements_filter() async {
+  test_IsExpression_type_filter_implements() async {
     // SimpleIdentifier  TypeName  IsExpression  IfStatement
     addTestSource('''
-class A {} class B extends A {} class C implements A {} class D {}
+class A {} class B implements A {} class C implements A {} class D {}
 f(A a){ if (a is ^) {}}''');
     await computeSuggestions();
 
@@ -2814,6 +2850,33 @@
     assertNotSuggested('Object');
   }
 
+  test_IsExpression_type_filter_undefined_type() async {
+    // SimpleIdentifier  TypeName  AsExpression
+    addTestSource('''
+class A {}
+f(U u){ (u as ^) }''');
+    await computeSuggestions();
+
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestClass('A');
+  }
+
+  test_IsExpression_type_partial() async {
+    // SimpleIdentifier  TypeName  IsExpression  IfStatement
+    addTestSource('''
+class A {int x; int y() => 0;}
+main(){var a; if (a is Obj^)}''');
+    await computeSuggestions();
+
+    expect(replacementOffset, completionOffset - 3);
+    expect(replacementLength, 3);
+    assertNotSuggested('a');
+    assertNotSuggested('main');
+    assertSuggestClass('A');
+    assertNotSuggested('Object');
+  }
+
   test_keyword() async {
     addSource(
         '/testB.dart',
@@ -4050,7 +4113,7 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    // Contributed by FieldFormalConstructorContributor
+    // Contributed by FieldFormalContributor
     assertNotSuggested('b');
     assertNotSuggested('_c');
     assertNotSuggested('sb');
@@ -4088,7 +4151,7 @@
 
     expect(replacementOffset, completionOffset - 1);
     expect(replacementLength, 1);
-    // Contributed by FieldFormalConstructorContributor
+    // Contributed by FieldFormalContributor
     assertNotSuggested('b');
     assertNotSuggested('_c');
     assertNotSuggested('d');
@@ -4125,7 +4188,7 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 1);
-    // Contributed by FieldFormalConstructorContributor
+    // Contributed by FieldFormalContributor
     assertNotSuggested('b');
     assertNotSuggested('_c');
     assertNotSuggested('d');
@@ -4163,7 +4226,7 @@
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
     assertNotSuggested('b');
-    // Contributed by FieldFormalConstructorContributor
+    // Contributed by FieldFormalContributor
     assertNotSuggested('_c');
     assertNotSuggested('d');
     assertNotSuggested('_e');
diff --git a/pkg/analysis_server/test/services/completion/dart/optype_test.dart b/pkg/analysis_server/test/services/completion/dart/optype_test.dart
index 455495c..f5c89bb 100644
--- a/pkg/analysis_server/test/services/completion/dart/optype_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/optype_test.dart
@@ -54,6 +54,7 @@
       bool statementLabel: false,
       bool staticMethodBody: false,
       bool typeNames: false,
+      bool varNames: false,
       bool voidReturn: false,
       CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION}) {
     expect(visitor.includeCaseLabelSuggestions, caseLabel, reason: 'caseLabel');
@@ -66,6 +67,7 @@
     expect(visitor.includeStatementLabelSuggestions, statementLabel,
         reason: 'statementLabel');
     expect(visitor.includeTypeNameSuggestions, typeNames, reason: 'typeNames');
+    expect(visitor.includeVarNameSuggestions, varNames, reason: 'varNames');
     expect(visitor.includeVoidReturnSuggestions, voidReturn,
         reason: 'voidReturn');
     expect(visitor.inStaticMethodBody, staticMethodBody,
@@ -149,7 +151,7 @@
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // VariableDeclarationStatement  Block
     addTestSource('class A {} main() {int a; int ^b = 1;}');
-    assertOpType();
+    assertOpType(varNames: true);
   }
 
   test_AssignmentExpression_RHS() {
@@ -544,7 +546,25 @@
   test_ExpressionStatement_name() {
     // ExpressionStatement  Block  BlockFunctionBody  MethodDeclaration
     addTestSource('class C {a() {C ^}}');
-    assertOpType();
+    assertOpType(varNames: true);
+  }
+
+  test_ExpressionStatement_name_semicolon() {
+    // ExpressionStatement  Block  BlockFunctionBody  MethodDeclaration
+    addTestSource('class C {a() {C ^;}}');
+    assertOpType(varNames: true);
+  }
+
+  test_ExpressionStatement_prefixed_name() {
+    // ExpressionStatement  Block  BlockFunctionBody  MethodDeclaration
+    addTestSource('class C {a() {x.Y ^}}');
+    assertOpType(varNames: true);
+  }
+
+  test_ExpressionStatement_prefixed_name_semicolon() {
+    // ExpressionStatement  Block  BlockFunctionBody  MethodDeclaration
+    addTestSource('class C {a() {x.Y ^;}}');
+    assertOpType(varNames: true);
   }
 
   test_ExtendsClause() {
@@ -557,7 +577,7 @@
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // FieldDeclaration
     addTestSource('class C {A ^}');
-    assertOpType();
+    assertOpType(varNames: true);
   }
 
   test_FieldDeclaration_name_var() {
@@ -1407,8 +1427,19 @@
   test_TopLevelVariableDeclaration_typed_name() {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // TopLevelVariableDeclaration
+    // _OpTypeAstVisitor.visitVariableDeclarationList is executed with this
+    // source, but _OpTypeAstVisitor.visitTopLevelVariableDeclaration is called
+    // for test_TopLevelVariableDeclaration_typed_name_semicolon
     addTestSource('class A {} B ^');
-    assertOpType();
+    assertOpType(varNames: true);
+  }
+
+  test_TopLevelVariableDeclaration_typed_name_semicolon() {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // TopLevelVariableDeclaration
+    // See comment in test_TopLevelVariableDeclaration_typed_name
+    addTestSource('class A {} B ^;');
+    assertOpType(varNames: true);
   }
 
   test_TopLevelVariableDeclaration_untyped_name() {
@@ -1453,14 +1484,14 @@
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // VariableDeclarationStatement  Block
     addTestSource('main() {List<int> m^}');
-    assertOpType();
+    assertOpType(varNames: true);
   }
 
   test_VariableDeclaration_name_hasSome_simpleType() {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // VariableDeclarationStatement  Block
     addTestSource('main() {String m^}');
-    assertOpType();
+    assertOpType(varNames: true);
   }
 
   test_VariableDeclarationList_final() {
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 1d395ac..e9fb6c5 100644
--- a/pkg/analysis_server/test/services/completion/dart/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/dart/test_all.dart
@@ -28,6 +28,7 @@
 import 'static_member_contributor_test.dart' as static_contributor_test;
 import 'type_member_contributor_test.dart' as type_member_contributor_test;
 import 'uri_contributor_test.dart' as uri_contributor_test;
+import 'variable_name_contributor_test.dart' as variable_name_contributor_test;
 
 /// Utility for manually running all tests.
 main() {
@@ -54,5 +55,6 @@
     static_contributor_test.main();
     type_member_contributor_test.main();
     uri_contributor_test.main();
+    variable_name_contributor_test.main();
   });
 }
diff --git a/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
new file mode 100644
index 0000000..72a4cab
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
@@ -0,0 +1,199 @@
+// 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.variableName;
+
+import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
+import 'package:analysis_server/src/services/completion/dart/variable_name_contributor.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../../utils.dart';
+import 'completion_contributor_util.dart';
+
+main() {
+  initializeTestEnvironment();
+  defineReflectiveTests(VariableNameContributorTest);
+}
+
+@reflectiveTest
+class VariableNameContributorTest extends DartCompletionContributorTest {
+  @override
+  DartCompletionContributor createContributor() {
+    return new VariableNameContributor();
+  }
+
+  test_ExpressionStatement_short() async {
+    addTestSource('''
+    f() { A ^ }
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestName('a');
+  }
+
+  test_ExpressionStatement_short_semicolon() async {
+    addTestSource('''
+    f() { A ^; }
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestName('a');
+  }
+
+  test_ExpressionStatement_long() async {
+    addTestSource('''
+    f() { AbstractCrazyNonsenseClassName ^ }
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestName('abstractCrazyNonsenseClassName');
+    assertSuggestName('crazyNonsenseClassName');
+    assertSuggestName('nonsenseClassName');
+    assertSuggestName('className');
+    assertSuggestName('name');
+  }
+
+  test_ExpressionStatement_long_semicolon() async {
+    addTestSource('''
+    f() { AbstractCrazyNonsenseClassName ^; }
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestName('abstractCrazyNonsenseClassName');
+    assertSuggestName('crazyNonsenseClassName');
+    assertSuggestName('nonsenseClassName');
+    assertSuggestName('className');
+    assertSuggestName('name');
+  }
+
+  test_ExpressionStatement_prefixed() async {
+    addTestSource('''
+    f() { prefix.AbstractCrazyNonsenseClassName ^ }
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestName('abstractCrazyNonsenseClassName');
+    assertSuggestName('crazyNonsenseClassName');
+    assertSuggestName('nonsenseClassName');
+    assertSuggestName('className');
+    assertSuggestName('name');
+  }
+
+  test_ExpressionStatement_prefixed_semicolon() async {
+    addTestSource('''
+    f() { prefix.AbstractCrazyNonsenseClassName ^; }
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestName('abstractCrazyNonsenseClassName');
+    assertSuggestName('crazyNonsenseClassName');
+    assertSuggestName('nonsenseClassName');
+    assertSuggestName('className');
+    assertSuggestName('name');
+  }
+
+  test_ExpressionStatement_top_level_short() async {
+    addTestSource('''
+    A ^
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestName('a');
+  }
+
+  test_ExpressionStatement_top_level_short_semicolon() async {
+    addTestSource('''
+    A ^;
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestName('a');
+  }
+
+  test_ExpressionStatement_top_level_long() async {
+    addTestSource('''
+    AbstractCrazyNonsenseClassName ^
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestName('abstractCrazyNonsenseClassName');
+    assertSuggestName('crazyNonsenseClassName');
+    assertSuggestName('nonsenseClassName');
+    assertSuggestName('className');
+    assertSuggestName('name');
+  }
+
+  test_ExpressionStatement_top_level_long_semicolon() async {
+    addTestSource('''
+    AbstractCrazyNonsenseClassName ^;
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestName('abstractCrazyNonsenseClassName');
+    assertSuggestName('crazyNonsenseClassName');
+    assertSuggestName('nonsenseClassName');
+    assertSuggestName('className');
+    assertSuggestName('name');
+  }
+
+  test_ExpressionStatement_top_level_prefixed() async {
+    addTestSource('''
+    prefix.AbstractCrazyNonsenseClassName ^
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestName('abstractCrazyNonsenseClassName');
+    assertSuggestName('crazyNonsenseClassName');
+    assertSuggestName('nonsenseClassName');
+    assertSuggestName('className');
+    assertSuggestName('name');
+  }
+
+  test_ExpressionStatement_top_level_prefixed_semicolon() async {
+    addTestSource('''
+    prefix.AbstractCrazyNonsenseClassName ^;
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestName('abstractCrazyNonsenseClassName');
+    assertSuggestName('crazyNonsenseClassName');
+    assertSuggestName('nonsenseClassName');
+    assertSuggestName('className');
+    assertSuggestName('name');
+  }
+
+  test_VariableDeclaration_short() async {
+    addTestSource('''
+    AAA a^
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset-1);
+    expect(replacementLength, 1);
+    assertSuggestName('aaa');
+  }
+
+  test_VariableDeclaration_short_semicolon() async {
+    addTestSource('''
+    AAA a^;
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset-1);
+    expect(replacementLength, 1);
+    assertSuggestName('aaa');
+  }
+
+}
diff --git a/pkg/analysis_server/test/services/refactoring/rename_unit_member_test.dart b/pkg/analysis_server/test/services/refactoring/rename_unit_member_test.dart
index 78a5cd4..3715ced 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_unit_member_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_unit_member_test.dart
@@ -496,6 +496,44 @@
 ''');
   }
 
+  test_createChange_FunctionElement_imported() async {
+    indexUnit(
+        '/foo.dart',
+        r'''
+test() {}
+foo() {}
+''');
+    indexTestUnit('''
+import 'foo.dart';
+main() {
+  print(test);
+  print(test());
+  foo();
+}
+''');
+    // configure refactoring
+    createRenameRefactoringAtString('test);');
+    expect(refactoring.refactoringName, 'Rename Top-Level Function');
+    expect(refactoring.elementKindName, 'function');
+    expect(refactoring.oldName, 'test');
+    refactoring.newName = 'newName';
+    // validate change
+    await assertSuccessfulRefactoring('''
+import 'foo.dart';
+main() {
+  print(newName);
+  print(newName());
+  foo();
+}
+''');
+    assertFileChangeResult(
+        '/foo.dart',
+        '''
+newName() {}
+foo() {}
+''');
+  }
+
   test_createChange_PropertyAccessorElement_getter_declaration() {
     return _test_createChange_PropertyAccessorElement("test {}");
   }
diff --git a/pkg/analysis_server/test/single_context_manager_test.dart b/pkg/analysis_server/test/single_context_manager_test.dart
new file mode 100644
index 0000000..f436006
--- /dev/null
+++ b/pkg/analysis_server/test/single_context_manager_test.dart
@@ -0,0 +1,539 @@
+// 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.
+
+library test.analysis_server.src.single_context_manager;
+
+import 'dart:core' hide Resource;
+
+import 'package:analysis_server/src/single_context_manager.dart';
+import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/java_io.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/util/glob.dart';
+import 'package:linter/src/plugin/linter_plugin.dart';
+import 'package:path/path.dart';
+import 'package:plugin/manager.dart';
+import 'package:plugin/plugin.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'package:unittest/unittest.dart';
+
+import 'context_manager_test.dart' show TestContextManagerCallbacks;
+import 'mock_sdk.dart';
+import 'mocks.dart';
+import 'utils.dart';
+
+main() {
+  initializeTestEnvironment();
+  defineReflectiveTests(SingleContextManagerTest);
+}
+
+@reflectiveTest
+class SingleContextManagerTest {
+  MemoryResourceProvider resourceProvider = new MemoryResourceProvider();
+
+  TestUriResolver packageResolver;
+  TestContextManagerCallbacks callbacks;
+  SingleContextManager manager;
+
+  List<Glob> get analysisFilesGlobs {
+    List<String> patterns = <String>[
+      '**/*.${AnalysisEngine.SUFFIX_DART}',
+      '**/*.${AnalysisEngine.SUFFIX_HTML}',
+    ];
+    return patterns
+        .map((pattern) => new Glob(JavaFile.pathContext.separator, pattern))
+        .toList();
+  }
+
+  String newFile(List<String> pathComponents, [String content = '']) {
+    String filePath = posix.joinAll(pathComponents);
+    resourceProvider.newFile(filePath, content);
+    return filePath;
+  }
+
+  String newFolder(List<String> pathComponents) {
+    String folderPath = posix.joinAll(pathComponents);
+    resourceProvider.newFolder(folderPath);
+    return folderPath;
+  }
+
+  void setUp() {
+    packageResolver = new TestUriResolver();
+
+    _processRequiredPlugins();
+    DartSdkManager sdkManager = new DartSdkManager((_) {
+      return new MockSdk();
+    });
+    manager = new SingleContextManager(resourceProvider, sdkManager,
+        () => packageResolver, analysisFilesGlobs);
+    callbacks = new TestContextManagerCallbacks(resourceProvider);
+    manager.callbacks = callbacks;
+  }
+
+  void test_isIgnored_false() {
+    String project = '/project';
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    expect(manager.isIgnored('$project/file.dart'), isFalse);
+  }
+
+  void test_isIgnored_true_inDotFolder() {
+    String project = '/project';
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    expect(manager.isIgnored('$project/foo/.bar/file.dart'), isTrue);
+  }
+
+  void test_isIgnored_true_inExcludedPath() {
+    String project = '/project';
+    String excludedPath = '/project/excluded';
+    manager.setRoots(
+        <String>[project], <String>[excludedPath], <String, String>{});
+    expect(manager.isIgnored('$excludedPath/file.dart'), isTrue);
+  }
+
+  void test_isIgnored_true_notInRoot() {
+    String root1 = '/context/root1';
+    String root2 = '/context/root2';
+    manager.setRoots(<String>[root1, root2], <String>[], <String, String>{});
+    expect(manager.isIgnored('$context/root3/file.dart'), isTrue);
+  }
+
+  void test_isInAnalysisRoot_false_inExcludedPath() {
+    String project = '/project';
+    String excludedPath = '/project/excluded';
+    manager.setRoots(
+        <String>[project], <String>[excludedPath], <String, String>{});
+    expect(manager.isInAnalysisRoot('$excludedPath/file.dart'), isFalse);
+  }
+
+  void test_isInAnalysisRoot_false_notInRoot() {
+    String root1 = '/context/root1';
+    String root2 = '/context/root2';
+    manager.setRoots(<String>[root1, root2], <String>[], <String, String>{});
+    expect(manager.isInAnalysisRoot('$context/root3/file.dart'), isFalse);
+  }
+
+  void test_isInAnalysisRoot_true() {
+    String project = '/project';
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    expect(manager.isInAnalysisRoot('$project/file.dart'), isTrue);
+  }
+
+  void test_refresh() {
+    String project = '/project';
+    String file1 = '$project/file1.dart';
+    String file2 = '$project/file2.dart';
+    // create files
+    resourceProvider.newFile(file1, '');
+    resourceProvider.newFile(file2, '');
+    // set roots
+    manager.setRoots(<String>[project], <String>[file2], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file1]);
+    // refresh
+    manager.refresh([]);
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file1]);
+  }
+
+  void test_setRoots_addFolderWithDartFile() {
+    String project = '/project';
+    String file = '$project/lib/foo.dart';
+    resourceProvider.newFile(file, '');
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    // verify
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file]);
+  }
+
+  void test_setRoots_addFolderWithDartFileInSubfolder() {
+    String project = '/project';
+    String file = '$project/foo/bar.dart';
+    resourceProvider.newFile(file, '');
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    // verify
+    callbacks.assertContextFiles(project, [file]);
+  }
+
+  void test_setRoots_addFolderWithDummyLink() {
+    String project = '/project';
+    String file = '$project/foo.dart';
+    resourceProvider.newDummyLink(file);
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    // verify
+    callbacks.assertContextFiles(project, []);
+  }
+
+  void test_setRoots_exclude_newRoot_withExcludedFile() {
+    String project = '/project';
+    String file1 = '$project/file1.dart';
+    String file2 = '$project/file2.dart';
+    // create files
+    resourceProvider.newFile(file1, '');
+    resourceProvider.newFile(file2, '');
+    // set roots
+    manager.setRoots(<String>[project], <String>[file1], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file2]);
+  }
+
+  void test_setRoots_exclude_newRoot_withExcludedFolder() {
+    String project = '/project';
+    String folderA = '$project/aaa';
+    String folderB = '$project/bbb';
+    String fileA = '$folderA/a.dart';
+    String fileB = '$folderB/b.dart';
+    // create files
+    resourceProvider.newFile(fileA, '');
+    resourceProvider.newFile(fileB, '');
+    // set roots
+    manager.setRoots(<String>[project], <String>[folderB], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [fileA]);
+  }
+
+  void test_setRoots_exclude_sameRoot_addExcludedFile() {
+    String project = '/project';
+    String file1 = '$project/file1.dart';
+    String file2 = '$project/file2.dart';
+    // create files
+    resourceProvider.newFile(file1, '');
+    resourceProvider.newFile(file2, '');
+    // set roots
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file1, file2]);
+    // exclude "2"
+    manager.setRoots(<String>[project], <String>[file2], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file1]);
+  }
+
+  void test_setRoots_exclude_sameRoot_addExcludedFolder() {
+    String project = '/project';
+    String folderA = '$project/aaa';
+    String folderB = '$project/bbb';
+    String fileA = '$folderA/a.dart';
+    String fileB = '$folderB/b.dart';
+    // create files
+    resourceProvider.newFile(fileA, 'library a;');
+    resourceProvider.newFile(fileB, 'library b;');
+    // initially both "aaa/a" and "bbb/b" are included
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [fileA, fileB]);
+    // exclude "bbb/"
+    manager.setRoots(<String>[project], <String>[folderB], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [fileA]);
+  }
+
+  void test_setRoots_exclude_sameRoot_removeExcludedFile() {
+    String project = '/project';
+    String file1 = '$project/file1.dart';
+    String file2 = '$project/file2.dart';
+    // create files
+    resourceProvider.newFile(file1, '// 1');
+    resourceProvider.newFile(file2, '// 2');
+    // set roots
+    manager.setRoots(<String>[project], <String>[file2], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file1]);
+    // stop excluding "2"
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file1, file2]);
+  }
+
+  void test_setRoots_exclude_sameRoot_removeExcludedFile_inFolder() {
+    String project = '/project';
+    String file1 = '$project/bin/file1.dart';
+    String file2 = '$project/bin/file2.dart';
+    // create files
+    resourceProvider.newFile(file1, '// 1');
+    resourceProvider.newFile(file2, '// 2');
+    // set roots
+    manager.setRoots(<String>[project], <String>[file2], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file1]);
+    // stop excluding "2"
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file1, file2]);
+  }
+
+  void test_setRoots_exclude_sameRoot_removeExcludedFolder() {
+    String project = '/project';
+    String folderA = '$project/aaa';
+    String folderB = '$project/bbb';
+    String fileA = '$folderA/a.dart';
+    String fileB = '$folderB/b.dart';
+    // create files
+    resourceProvider.newFile(fileA, 'library a;');
+    resourceProvider.newFile(fileB, 'library b;');
+    // exclude "bbb/"
+    manager.setRoots(<String>[project], <String>[folderB], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [fileA]);
+    // stop excluding "bbb/"
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [fileA, fileB]);
+  }
+
+  void test_setRoots_ignoreGlobs() {
+    String project = '/project';
+    String file1 = '$project/file.dart';
+    String file2 = '$project/file.foo';
+    // create files
+    resourceProvider.newFile(file1, '');
+    resourceProvider.newFile(file2, '');
+    // set roots
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [file1]);
+  }
+
+  void test_setRoots_newContextFolder_coverNewRoot() {
+    String contextPath = '/context';
+    String root1 = '$contextPath/root1';
+    String file1 = '$root1/file1.dart';
+    String root2 = '$contextPath/root2';
+    String file2 = '$root2/file1.dart';
+    // create files
+    resourceProvider.newFile(file1, '');
+    resourceProvider.newFile(file2, '');
+    // cover single root '/context/root1'
+    manager.setRoots(<String>[root1], <String>[], <String, String>{});
+    callbacks.assertContextPaths([root1]);
+    callbacks.assertContextFiles(root1, [file1]);
+    // cover two roots
+    manager.setRoots(<String>[root1, root2], <String>[], <String, String>{});
+    callbacks.assertContextPaths([contextPath]);
+    callbacks.assertContextFiles(contextPath, [file1, file2]);
+    // cover single root '/context/root2'
+    manager.setRoots(<String>[root2], <String>[], <String, String>{});
+    callbacks.assertContextPaths([root2]);
+    callbacks.assertContextFiles(root2, [file2]);
+  }
+
+  void test_setRoots_newContextFolder_replace() {
+    String contextPath1 = '/context1';
+    String root11 = '$contextPath1/root1';
+    String root12 = '$contextPath1/root2';
+    String file11 = '$root11/file1.dart';
+    String file12 = '$root12/file2.dart';
+    String contextPath2 = '/context2';
+    String root21 = '$contextPath2/root1';
+    String root22 = '$contextPath2/root2';
+    String file21 = '$root21/file1.dart';
+    String file22 = '$root22/file2.dart';
+    // create files
+    resourceProvider.newFile(file11, '');
+    resourceProvider.newFile(file12, '');
+    resourceProvider.newFile(file21, '');
+    resourceProvider.newFile(file22, '');
+    // set roots in '/context1'
+    manager.setRoots(<String>[root11, root12], <String>[], <String, String>{});
+    callbacks.assertContextPaths([contextPath1]);
+    callbacks.assertContextFiles(contextPath1, [file11, file12]);
+    // set roots in '/context2'
+    manager.setRoots(<String>[root21, root22], <String>[], <String, String>{});
+    callbacks.assertContextPaths([contextPath2]);
+    callbacks.assertContextFiles(contextPath2, [file21, file22]);
+  }
+
+  void test_setRoots_pathContainsDotFile() {
+    // If the path to a file (relative to the context root) contains a folder
+    // whose name begins with '.', then the file is ignored.
+    String project = '/project';
+    String fileA = '$project/foo.dart';
+    String fileB = '$project/.pub/bar.dart';
+    resourceProvider.newFile(fileA, '');
+    resourceProvider.newFile(fileB, '');
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [fileA]);
+  }
+
+  void test_setRoots_rootPathContainsDotFile() {
+    // If the path to the context root itself contains a folder whose name
+    // begins with '.', then that is not sufficient to cause any files in the
+    // context to be ignored.
+    String project = '/.pub/project';
+    String fileA = '$project/foo.dart';
+    resourceProvider.newFile(fileA, '');
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [fileA]);
+  }
+
+  test_watch_addFile() async {
+    String project = '/project';
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    // empty folder initially
+    callbacks.assertContextFiles(project, []);
+    // add file
+    String file = '$project/foo.dart';
+    resourceProvider.newFile(file, 'contents');
+    // the file was added
+    await pumpEventQueue();
+    callbacks.assertContextFiles(project, [file]);
+  }
+
+  test_watch_addFile_afterChangingRoots() async {
+    String contextPath = '/context';
+    String root1 = '$contextPath/root1';
+    String root2 = '$contextPath/root2';
+    String file1 = '$root1/file1.dart';
+    String file2 = '$root2/file2.dart';
+    manager.setRoots(<String>[root1], <String>[], <String, String>{});
+    manager.setRoots(<String>[root2], <String>[], <String, String>{});
+    manager.setRoots(<String>[root1, root2], <String>[], <String, String>{});
+    manager.setRoots(<String>[root2], <String>[], <String, String>{});
+    // empty folder initially
+    callbacks.assertContextFiles(root2, []);
+    // add files
+    resourceProvider.newFile(file1, '');
+    resourceProvider.newFile(file2, '');
+    // the file was added
+    await pumpEventQueue();
+    callbacks.assertContextFiles(root2, [file2]);
+  }
+
+  test_watch_addFile_excluded() async {
+    String project = '/project';
+    String folderA = '$project/aaa';
+    String folderB = '$project/bbb';
+    String fileA = '$folderA/a.dart';
+    String fileB = '$folderB/b.dart';
+    // create files
+    resourceProvider.newFile(fileA, 'library a;');
+    // set roots
+    manager.setRoots(<String>[project], <String>[folderB], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [fileA]);
+    // add a file, ignored as excluded
+    resourceProvider.newFile(fileB, 'library b;');
+    await pumpEventQueue();
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [fileA]);
+  }
+
+  test_watch_addFile_notInRoot() async {
+    String contextPath = '/roots';
+    String root1 = '$contextPath/root1';
+    String root2 = '$contextPath/root2';
+    String root3 = '$contextPath/root3';
+    String file1 = '$root1/file1.dart';
+    String file2 = '$root2/file2.dart';
+    String file3 = '$root3/file3.dart';
+    // create files
+    resourceProvider.newFile(file1, '');
+    resourceProvider.newFile(file2, '');
+    // set roots
+    manager.setRoots(<String>[root1, root2], <String>[], <String, String>{});
+    callbacks.assertContextPaths([contextPath]);
+    callbacks.assertContextFiles(contextPath, [file1, file2]);
+    // add a file, not in a root - ignored
+    resourceProvider.newFile(file3, '');
+    await pumpEventQueue();
+    callbacks.assertContextPaths([contextPath]);
+    callbacks.assertContextFiles(contextPath, [file1, file2]);
+  }
+
+  test_watch_addFile_pathContainsDotFile() async {
+    // If a file is added and the absolute path to it contains a folder whose
+    // name begins with '.', then the file is ignored.
+    String project = '/project';
+    String fileA = '$project/foo.dart';
+    String fileB = '$project/.pub/bar.dart';
+    resourceProvider.newFile(fileA, '');
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [fileA]);
+    resourceProvider.newFile(fileB, '');
+    await pumpEventQueue();
+    callbacks.assertContextPaths([project]);
+    callbacks.assertContextFiles(project, [fileA]);
+  }
+
+  test_watch_addFileInSubfolder() async {
+    String project = '/project';
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    // empty folder initially
+    callbacks.assertContextFiles(project, []);
+    // add file in subfolder
+    String file = '$project/foo/bar.dart';
+    resourceProvider.newFile(file, 'contents');
+    // the file was added
+    await pumpEventQueue();
+    callbacks.assertContextFiles(project, [file]);
+  }
+
+  test_watch_deleteFile() async {
+    String project = '/project';
+    String file = '$project/foo.dart';
+    // add root with a file
+    resourceProvider.newFile(file, 'contents');
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    // the file was added
+    callbacks.assertContextFiles(project, [file]);
+    // delete the file
+    resourceProvider.deleteFile(file);
+    await pumpEventQueue();
+    callbacks.assertContextFiles(project, []);
+  }
+
+  test_watch_deleteFolder() async {
+    String project = '/project';
+    String file = '$project/foo.dart';
+    // add root with a file
+    resourceProvider.newFile(file, 'contents');
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    // the file was added
+    callbacks.assertContextFiles(project, [file]);
+    // delete the folder
+    resourceProvider.deleteFolder(project);
+    await pumpEventQueue();
+    callbacks.assertContextFiles(project, []);
+  }
+
+  test_watch_modifyFile() async {
+    String project = '/project';
+    String file = '$project/foo.dart';
+    // add root with a file
+    resourceProvider.newFile(file, 'contents');
+    manager.setRoots(<String>[project], <String>[], <String, String>{});
+    // the file was added
+    Map<String, int> filePaths = callbacks.currentContextFilePaths[project];
+    expect(filePaths, hasLength(1));
+    expect(filePaths, contains(file));
+    expect(filePaths[file], equals(callbacks.now));
+    // update the file
+    callbacks.now++;
+    resourceProvider.modifyFile(file, 'new contents');
+    await pumpEventQueue();
+    return expect(filePaths[file], equals(callbacks.now));
+  }
+
+  void _processRequiredPlugins() {
+    List<Plugin> plugins = <Plugin>[];
+    plugins.addAll(AnalysisEngine.instance.requiredPlugins);
+    plugins.add(AnalysisEngine.instance.commandLinePlugin);
+    plugins.add(AnalysisEngine.instance.optionsPlugin);
+    plugins.add(linterPlugin);
+    ExtensionManager manager = new ExtensionManager();
+    manager.processPlugins(plugins);
+  }
+}
+
+class TestUriResolver extends UriResolver {
+  @override
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
+    return null;
+  }
+}
diff --git a/pkg/analysis_server/test/socket_server_test.dart b/pkg/analysis_server/test/socket_server_test.dart
index 395072a..4ff5ea7 100644
--- a/pkg/analysis_server/test/socket_server_test.dart
+++ b/pkg/analysis_server/test/socket_server_test.dart
@@ -121,7 +121,8 @@
         InstrumentationService.NULL_SERVICE,
         serverPlugin,
         null,
-        null);
+        null,
+        false);
   }
 }
 
diff --git a/pkg/analysis_server/test/test_all.dart b/pkg/analysis_server/test/test_all.dart
index 994f5ef..e830864 100644
--- a/pkg/analysis_server/test/test_all.dart
+++ b/pkg/analysis_server/test/test_all.dart
@@ -22,6 +22,7 @@
 import 'search/test_all.dart' as search_all;
 import 'server_options_test.dart' as server_options;
 import 'services/test_all.dart' as services_all;
+import 'single_context_manager_test.dart' as single_context_manager_test;
 import 'socket_server_test.dart' as socket_server_test;
 import 'source/test_all.dart' as source_all;
 import 'src/test_all.dart' as src_all;
@@ -51,6 +52,7 @@
     search_all.main();
     server_options.main();
     services_all.main();
+    single_context_manager_test.main();
     socket_server_test.main();
     source_all.main();
     src_all.main();
diff --git a/pkg/analyzer/doc/tasks.html b/pkg/analyzer/doc/tasks.html
index 2224724..5e242a5 100644
--- a/pkg/analyzer/doc/tasks.html
+++ b/pkg/analyzer/doc/tasks.html
@@ -177,7 +177,10 @@
   LINTS [shape=box]
   LibraryErrorsReadyTask -> LIBRARY_ERRORS_READY
   LibraryUnitErrorsTask -> LIBRARY_UNIT_ERRORS
+  MODIFICATION_TIME -> BuildDirectiveElementsTask
   MODIFICATION_TIME -> ParseDartTask
+  MODIFICATION_TIME -> ScanDartTask
+  MODIFICATION_TIME -> VerifyUnitTask
   MODIFICATION_TIME [shape=box]
   PARSED_UNIT -> BuildCompilationUnitElementTask
   PARSED_UNIT -> DartErrorsTask
@@ -198,6 +201,7 @@
   ParseDartTask -> LIBRARY_SPECIFIC_UNITS
   ParseDartTask -> PARSED_UNIT
   ParseDartTask -> PARSE_ERRORS
+  ParseDartTask -> REFERENCED_SOURCES
   ParseDartTask -> SOURCE_KIND
   ParseDartTask -> UNITS
   PartiallyResolveUnitReferencesTask -> CREATED_RESOLVED_UNIT6
@@ -222,6 +226,9 @@
   READY_RESOLVED_UNIT -> VerifyUnitTask
   READY_RESOLVED_UNIT [shape=box]
   REFERENCED_NAMES [shape=box]
+  REFERENCED_SOURCES -> BuildDirectiveElementsTask
+  REFERENCED_SOURCES -> VerifyUnitTask
+  REFERENCED_SOURCES [shape=box]
   RESOLVED_UNIT -> GenerateHintsTask
   RESOLVED_UNIT -> GenerateLintsTask
   RESOLVED_UNIT -> ReadyResolvedUnitTask
diff --git a/pkg/analyzer/lib/dart/ast/token.dart b/pkg/analyzer/lib/dart/ast/token.dart
index 6560a8e..77226be 100644
--- a/pkg/analyzer/lib/dart/ast/token.dart
+++ b/pkg/analyzer/lib/dart/ast/token.dart
@@ -250,6 +250,11 @@
   bool get isUserDefinableOperator;
 
   /**
+   * Return the keyword, if a keyword token, or `null` otherwise.
+   */
+  Keyword get keyword;
+
+  /**
    * Return the number of characters in the node's source range.
    */
   int get length;
diff --git a/pkg/analyzer/lib/instrumentation/instrumentation.dart b/pkg/analyzer/lib/instrumentation/instrumentation.dart
index fe58cdb..92638f7 100644
--- a/pkg/analyzer/lib/instrumentation/instrumentation.dart
+++ b/pkg/analyzer/lib/instrumentation/instrumentation.dart
@@ -106,10 +106,8 @@
    */
   void logAnalysisTask(String context, AnalysisTask task) {
     if (_instrumentationServer != null) {
-      String description =
-          (task is AnalysisTask) ? task.description : task.toString();
       _instrumentationServer
-          .log(_join([TAG_ANALYSIS_TASK, context, description]));
+          .log(_join([TAG_ANALYSIS_TASK, context, task.description]));
     }
   }
 
diff --git a/pkg/analyzer/lib/plugin/resolver_provider.dart b/pkg/analyzer/lib/plugin/resolver_provider.dart
index 1172372..ed0e366 100644
--- a/pkg/analyzer/lib/plugin/resolver_provider.dart
+++ b/pkg/analyzer/lib/plugin/resolver_provider.dart
@@ -9,6 +9,10 @@
 
 /**
  * A function that will return a [UriResolver] that can be used to resolve a
- * specific kind of URI within the analysis context rooted at the given folder.
+ * specific kind of URI within the analysis context rooted at the given
+ * [folder].
+ *
+ * The given [folder] may be `null` if analysis is performed in an environment
+ * where URI resolution is always the same in any folder.
  */
 typedef UriResolver ResolverProvider(Folder folder);
diff --git a/pkg/analyzer/lib/source/analysis_options_provider.dart b/pkg/analyzer/lib/source/analysis_options_provider.dart
index 3e15c64..600dffc 100644
--- a/pkg/analyzer/lib/source/analysis_options_provider.dart
+++ b/pkg/analyzer/lib/source/analysis_options_provider.dart
@@ -38,19 +38,21 @@
   /// Provide the options found in [optionsSource].
   /// Return an empty options map if the source is null.
   Map<String, YamlNode> getOptionsFromString(String optionsSource) {
-    var options = <String, YamlNode>{};
+    Map<String, YamlNode> options = <String, YamlNode>{};
     if (optionsSource == null) {
       return options;
     }
 
-    YamlNode doc;
-    try {
-      doc = loadYamlNode(optionsSource);
-    } on YamlException catch (e) {
-      throw new OptionsFormatException(e.message, e.span);
-    } catch (e) {
-      throw new OptionsFormatException('Unable to parse YAML document.');
+    YamlNode safelyLoadYamlNode() {
+      try {
+        return loadYamlNode(optionsSource);
+      } on YamlException catch (e) {
+        throw new OptionsFormatException(e.message, e.span);
+      } catch (e) {
+        throw new OptionsFormatException('Unable to parse YAML document.');
+      }
     }
+    YamlNode doc = safelyLoadYamlNode();
 
     // Empty options.
     if (doc is YamlScalar && doc.value == null) {
@@ -62,7 +64,7 @@
           doc.span);
     }
     if (doc is YamlMap) {
-      (doc as YamlMap).nodes.forEach((k, v) {
+      doc.nodes.forEach((k, YamlNode v) {
         var key;
         if (k is YamlScalar) {
           key = k.value;
diff --git a/pkg/analyzer/lib/source/embedder.dart b/pkg/analyzer/lib/source/embedder.dart
index b55f5d9..78ba661 100644
--- a/pkg/analyzer/lib/source/embedder.dart
+++ b/pkg/analyzer/lib/source/embedder.dart
@@ -211,11 +211,9 @@
     if (embedded_libs == null) {
       return;
     }
-    if (embedded_libs is! YamlMap) {
-      return;
+    if (embedded_libs is YamlMap) {
+      embedded_libs.forEach((k, v) => _processEmbeddedLibs(k, v, libDir));
     }
-    (embedded_libs as YamlMap)
-        .forEach((k, v) => _processEmbeddedLibs(k, v, libDir));
   }
 }
 
diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart
index 8be0a41..7e6e0a0 100644
--- a/pkg/analyzer/lib/src/context/cache.dart
+++ b/pkg/analyzer/lib/src/context/cache.dart
@@ -315,9 +315,7 @@
       new HashMap<ResultDescriptor, ResultData>();
 
   CacheEntry(this.target) {
-    if (target is ElementImpl) {
-      (target as ElementImpl).setModifier(Modifier.CACHE_KEY, true);
-    }
+    _markAsCacheKey(target);
   }
 
   /**
@@ -361,8 +359,9 @@
       }
     });
     _resultMap.clear();
-    if (target is ElementImpl) {
-      (target as ElementImpl).setModifier(Modifier.CACHE_KEY, false);
+    AnalysisTarget oldTarget = target;
+    if (oldTarget is ElementImpl) {
+      oldTarget.setModifier(Modifier.CACHE_KEY, false);
     }
   }
 
@@ -632,6 +631,15 @@
   }
 
   /**
+   * If the given `target` is an element, mark it as being a cache key.
+   */
+  void _markAsCacheKey(AnalysisTarget target) {
+    if (target is ElementImpl) {
+      target.setModifier(Modifier.CACHE_KEY, true);
+    }
+  }
+
+  /**
    * Set the [dependedOn] on which this result depends.
    */
   void _setDependedOnResults(ResultData thisData, TargetedResult thisResult,
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 1603fac..7815864 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -269,8 +269,6 @@
             options.enableStrictCallChecks ||
         this._options.enableGenericMethods != options.enableGenericMethods ||
         this._options.enableAsync != options.enableAsync ||
-        this._options.enableConditionalDirectives !=
-            options.enableConditionalDirectives ||
         this._options.enableSuperMixins != options.enableSuperMixins;
     int cacheSize = options.cacheSize;
     if (this._options.cacheSize != cacheSize) {
@@ -285,8 +283,6 @@
     this._options.enableAssertMessage = options.enableAssertMessage;
     this._options.enableStrictCallChecks = options.enableStrictCallChecks;
     this._options.enableAsync = options.enableAsync;
-    this._options.enableConditionalDirectives =
-        options.enableConditionalDirectives;
     this._options.enableSuperMixins = options.enableSuperMixins;
     this._options.enableTiming = options.enableTiming;
     this._options.hint = options.hint;
@@ -378,8 +374,7 @@
     List<Source> sources = <Source>[];
     for (Source source in _cache.sources) {
       CacheEntry entry = _cache.get(source);
-      if (source is Source &&
-          entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY &&
+      if (entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY &&
           !source.isInSystemLibrary &&
           isServerLibrary(source)) {
         sources.add(source);
@@ -813,13 +808,14 @@
     CacheEntry entry = _cache.get(target);
     if (entry == null) {
       entry = new CacheEntry(target);
+      ImplicitAnalysisEvent event = null;
       if (target is Source) {
         entry.modificationTime = getModificationStamp(target);
+        event = new ImplicitAnalysisEvent(target, true);
       }
       _cache.put(entry);
-      if (target is Source) {
-        _implicitAnalysisEventsController
-            .add(new ImplicitAnalysisEvent(target, true));
+      if (event != null) {
+        _implicitAnalysisEventsController.add(event);
       }
     }
     return entry;
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 4555a80..78daa6f 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -766,17 +766,14 @@
     if (propagatedElement != null) {
       executableElement = propagatedElement;
     } else {
-      if (_leftHandSide is Identifier) {
-        Identifier identifier = _leftHandSide as Identifier;
-        Element leftElement = identifier.propagatedElement;
+      Expression left = _leftHandSide;
+      if (left is Identifier) {
+        Element leftElement = left.propagatedElement;
         if (leftElement is ExecutableElement) {
           executableElement = leftElement;
         }
-      }
-      if (_leftHandSide is PropertyAccess) {
-        SimpleIdentifier identifier =
-            (_leftHandSide as PropertyAccess).propertyName;
-        Element leftElement = identifier.propagatedElement;
+      } else if (left is PropertyAccess) {
+        Element leftElement = left.propertyName.propagatedElement;
         if (leftElement is ExecutableElement) {
           executableElement = leftElement;
         }
@@ -803,15 +800,14 @@
     if (staticElement != null) {
       executableElement = staticElement;
     } else {
-      if (_leftHandSide is Identifier) {
-        Element leftElement = (_leftHandSide as Identifier).staticElement;
+      Expression left = _leftHandSide;
+      if (left is Identifier) {
+        Element leftElement = left.staticElement;
         if (leftElement is ExecutableElement) {
           executableElement = leftElement;
         }
-      }
-      if (_leftHandSide is PropertyAccess) {
-        Element leftElement =
-            (_leftHandSide as PropertyAccess).propertyName.staticElement;
+      } else if (left is PropertyAccess) {
+        Element leftElement = left.propertyName.staticElement;
         if (leftElement is ExecutableElement) {
           executableElement = leftElement;
         }
@@ -3228,14 +3224,10 @@
   }
 
   @override
-  bool get isConst =>
-      (keyword is KeywordToken) &&
-      (keyword as KeywordToken).keyword == Keyword.CONST;
+  bool get isConst => keyword?.keyword == Keyword.CONST;
 
   @override
-  bool get isFinal =>
-      (keyword is KeywordToken) &&
-      (keyword as KeywordToken).keyword == Keyword.FINAL;
+  bool get isFinal => keyword?.keyword == Keyword.FINAL;
 
   @override
   TypeName get type => _type;
@@ -3391,8 +3383,7 @@
    * The element associated with this directive, or `null` if the AST structure
    * has not been resolved or if this directive could not be resolved.
    */
-  @override
-  Element element;
+  Element _element;
 
   /**
    * Initialize a newly create directive. Either or both of the [comment] and
@@ -3401,6 +3392,16 @@
    */
   DirectiveImpl(Comment comment, List<Annotation> metadata)
       : super(comment, metadata);
+
+  @override
+  Element get element => _element;
+
+  /**
+   * Set the element associated with this directive to be the given [element].
+   */
+  void set element(Element element) {
+    _element = element;
+  }
 }
 
 /**
@@ -4356,14 +4357,10 @@
   }
 
   @override
-  bool get isConst =>
-      (keyword is KeywordToken) &&
-      (keyword as KeywordToken).keyword == Keyword.CONST;
+  bool get isConst => keyword?.keyword == Keyword.CONST;
 
   @override
-  bool get isFinal =>
-      (keyword is KeywordToken) &&
-      (keyword as KeywordToken).keyword == Keyword.FINAL;
+  bool get isFinal => keyword?.keyword == Keyword.FINAL;
 
   @override
   FormalParameterList get parameters => _parameters;
@@ -5028,14 +5025,10 @@
   }
 
   @override
-  bool get isGetter =>
-      propertyKeyword != null &&
-      (propertyKeyword as KeywordToken).keyword == Keyword.GET;
+  bool get isGetter => propertyKeyword?.keyword == Keyword.GET;
 
   @override
-  bool get isSetter =>
-      propertyKeyword != null &&
-      (propertyKeyword as KeywordToken).keyword == Keyword.SET;
+  bool get isSetter => propertyKeyword?.keyword == Keyword.SET;
 
   @override
   TypeName get returnType => _returnType;
@@ -6117,9 +6110,7 @@
   Token get endToken => _argumentList.endToken;
 
   @override
-  bool get isConst =>
-      keyword is KeywordToken &&
-      (keyword as KeywordToken).keyword == Keyword.CONST;
+  bool get isConst => keyword?.keyword == Keyword.CONST;
 
   @override
   int get precedence => 16;
@@ -7116,22 +7107,16 @@
   }
 
   @override
-  bool get isGetter =>
-      propertyKeyword != null &&
-      (propertyKeyword as KeywordToken).keyword == Keyword.GET;
+  bool get isGetter => propertyKeyword?.keyword == Keyword.GET;
 
   @override
   bool get isOperator => operatorKeyword != null;
 
   @override
-  bool get isSetter =>
-      propertyKeyword != null &&
-      (propertyKeyword as KeywordToken).keyword == Keyword.SET;
+  bool get isSetter => propertyKeyword?.keyword == Keyword.SET;
 
   @override
-  bool get isStatic =>
-      modifierKeyword != null &&
-      (modifierKeyword as KeywordToken).keyword == Keyword.STATIC;
+  bool get isStatic => modifierKeyword?.keyword == Keyword.STATIC;
 
   @override
   SimpleIdentifier get name => _name;
@@ -8248,16 +8233,15 @@
   @override
   bool get isDeferred {
     Element element = _prefix.staticElement;
-    if (element is! PrefixElement) {
-      return false;
+    if (element is PrefixElement) {
+      List<ImportElement> imports =
+          element.enclosingElement.getImportsWithPrefix(element);
+      if (imports.length != 1) {
+        return false;
+      }
+      return imports[0].isDeferred;
     }
-    PrefixElement prefixElement = element as PrefixElement;
-    List<ImportElement> imports =
-        prefixElement.enclosingElement.getImportsWithPrefix(prefixElement);
-    if (imports.length != 1) {
-      return false;
-    }
-    return imports[0].isDeferred;
+    return false;
   }
 
   @override
@@ -8835,14 +8819,10 @@
   Token get endToken => identifier.endToken;
 
   @override
-  bool get isConst =>
-      (keyword is KeywordToken) &&
-      (keyword as KeywordToken).keyword == Keyword.CONST;
+  bool get isConst => keyword?.keyword == Keyword.CONST;
 
   @override
-  bool get isFinal =>
-      (keyword is KeywordToken) &&
-      (keyword as KeywordToken).keyword == Keyword.FINAL;
+  bool get isFinal => keyword?.keyword == Keyword.FINAL;
 
   @override
   TypeName get type => _type;
@@ -8929,11 +8909,9 @@
     AstNode parent = this.parent;
     if (parent is PrefixedIdentifier) {
       return identical(parent.identifier, this);
-    }
-    if (parent is PropertyAccess) {
+    } else if (parent is PropertyAccess) {
       return identical(parent.propertyName, this);
-    }
-    if (parent is MethodInvocation) {
+    } else if (parent is MethodInvocation) {
       MethodInvocation invocation = parent;
       return identical(invocation.methodName, this) &&
           invocation.realTarget != null;
@@ -8976,23 +8954,22 @@
   @override
   bool inGetterContext() {
     // TODO(brianwilkerson) Convert this to a getter.
-    AstNode parent = this.parent;
+    AstNode initialParent = this.parent;
+    AstNode parent = initialParent;
     AstNode target = this;
     // skip prefix
-    if (parent is PrefixedIdentifier) {
-      PrefixedIdentifier prefixed = parent as PrefixedIdentifier;
-      if (identical(prefixed.prefix, this)) {
+    if (initialParent is PrefixedIdentifier) {
+      if (identical(initialParent.prefix, this)) {
         return true;
       }
-      parent = prefixed.parent;
-      target = prefixed;
-    } else if (parent is PropertyAccess) {
-      PropertyAccess access = parent as PropertyAccess;
-      if (identical(access.target, this)) {
+      parent = initialParent.parent;
+      target = initialParent;
+    } else if (initialParent is PropertyAccess) {
+      if (identical(initialParent.target, this)) {
         return true;
       }
-      parent = access.parent;
-      target = access;
+      parent = initialParent.parent;
+      target = initialParent;
     }
     // skip label
     if (parent is Label) {
@@ -9016,24 +8993,23 @@
   @override
   bool inSetterContext() {
     // TODO(brianwilkerson) Convert this to a getter.
-    AstNode parent = this.parent;
+    AstNode initialParent = this.parent;
+    AstNode parent = initialParent;
     AstNode target = this;
     // skip prefix
-    if (parent is PrefixedIdentifier) {
-      PrefixedIdentifier prefixed = parent as PrefixedIdentifier;
+    if (initialParent is PrefixedIdentifier) {
       // if this is the prefix, then return false
-      if (identical(prefixed.prefix, this)) {
+      if (identical(initialParent.prefix, this)) {
         return false;
       }
-      parent = prefixed.parent;
-      target = prefixed;
-    } else if (parent is PropertyAccess) {
-      PropertyAccess access = parent as PropertyAccess;
-      if (identical(access.target, this)) {
+      parent = initialParent.parent;
+      target = initialParent;
+    } else if (initialParent is PropertyAccess) {
+      if (identical(initialParent.target, this)) {
         return false;
       }
-      parent = access.parent;
-      target = access;
+      parent = initialParent.parent;
+      target = initialParent;
     }
     // analyze usage
     if (parent is PrefixExpression) {
@@ -10578,7 +10554,7 @@
       super._childEntities..add(_name)..add(equals)..add(_initializer);
 
   /**
-   * This overridden implementation of getDocumentationComment() looks in the
+   * This overridden implementation of [documentationComment] looks in the
    * grandparent node for Dartdoc comments if no documentation is specifically
    * available on the node.
    */
@@ -10586,11 +10562,9 @@
   Comment get documentationComment {
     Comment comment = super.documentationComment;
     if (comment == null) {
-      if (parent != null && parent.parent != null) {
-        AstNode node = parent.parent;
-        if (node is AnnotatedNode) {
-          return node.documentationComment;
-        }
+      AstNode node = parent?.parent;
+      if (node is AnnotatedNode) {
+        return node.documentationComment;
       }
     }
     return comment;
@@ -10715,14 +10689,10 @@
   }
 
   @override
-  bool get isConst =>
-      keyword is KeywordToken &&
-      (keyword as KeywordToken).keyword == Keyword.CONST;
+  bool get isConst => keyword?.keyword == Keyword.CONST;
 
   @override
-  bool get isFinal =>
-      keyword is KeywordToken &&
-      (keyword as KeywordToken).keyword == Keyword.FINAL;
+  bool get isFinal => keyword?.keyword == Keyword.FINAL;
 
   @override
   TypeName get type => _type;
diff --git a/pkg/analyzer/lib/src/dart/ast/token.dart b/pkg/analyzer/lib/src/dart/ast/token.dart
index 1791990..39a3ab5 100644
--- a/pkg/analyzer/lib/src/dart/ast/token.dart
+++ b/pkg/analyzer/lib/src/dart/ast/token.dart
@@ -142,9 +142,7 @@
  * A token representing a keyword in the language.
  */
 class KeywordToken extends SimpleToken {
-  /**
-   * The keyword being represented by this token.
-   */
+  @override
   final Keyword keyword;
 
   /**
@@ -253,6 +251,9 @@
   bool get isUserDefinableOperator => type.isUserDefinableOperator;
 
   @override
+  Keyword get keyword => null;
+
+  @override
   int get length => lexeme.length;
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index edd0196..a87c085 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -933,9 +933,10 @@
     if (token == null) {
       return;
     }
-    if (token is CommentToken) {
-      token = (token as CommentToken).parent;
+    Token nonComment(Token token) {
+      return token is CommentToken ? token.parent : token;
     }
+    token = nonComment(token);
     if (_lastCloned == null) {
       _lastCloned = new Token(TokenType.EOF, -1);
       _lastCloned.setNext(_lastCloned);
@@ -2268,7 +2269,7 @@
         if (leftOperand is num && rightOperand is num) {
           return leftOperand ~/ rightOperand;
         }
-      } else {}
+      }
       break;
     }
     // TODO(brianwilkerson) This doesn't handle numeric conversions.
@@ -2315,10 +2316,11 @@
     for (MapLiteralEntry entry in node.entries) {
       Object key = entry.key.accept(this);
       Object value = entry.value.accept(this);
-      if (key is! String || identical(value, NOT_A_CONSTANT)) {
+      if (key is String && !identical(value, NOT_A_CONSTANT)) {
+        map[(key as String)] = value;
+      } else {
         return NOT_A_CONSTANT;
       }
-      map[(key as String)] = value;
     }
     return map;
   }
@@ -2411,17 +2413,17 @@
    */
   Object _getConstantValue(Element element) {
     // TODO(brianwilkerson) Implement this
-    if (element is FieldElement) {
-      FieldElement field = element;
-      if (field.isStatic && field.isConst) {
-        //field.getConstantValue();
-      }
-      //    } else if (element instanceof VariableElement) {
-      //      VariableElement variable = (VariableElement) element;
-      //      if (variable.isStatic() && variable.isConst()) {
-      //        //variable.getConstantValue();
-      //      }
-    }
+//    if (element is FieldElement) {
+//      FieldElement field = element;
+//      if (field.isStatic && field.isConst) {
+//        //field.getConstantValue();
+//      }
+//      //    } else if (element instanceof VariableElement) {
+//      //      VariableElement variable = (VariableElement) element;
+//      //      if (variable.isStatic() && variable.isConst()) {
+//      //        //variable.getConstantValue();
+//      //      }
+//    }
     return NOT_A_CONSTANT;
   }
 }
@@ -2504,17 +2506,14 @@
   @override
   Element visitIdentifier(Identifier node) {
     AstNode parent = node.parent;
-    // Type name in Annotation
     if (parent is Annotation) {
-      Annotation annotation = parent;
-      if (identical(annotation.name, node) &&
-          annotation.constructorName == null) {
-        return annotation.element;
+      // Type name in Annotation
+      if (identical(parent.name, node) && parent.constructorName == null) {
+        return parent.element;
       }
-    }
-    // Extra work to map Constructor Declarations to their associated
-    // Constructor Elements
-    if (parent is ConstructorDeclaration) {
+    } else if (parent is ConstructorDeclaration) {
+      // Extra work to map Constructor Declarations to their associated
+      // Constructor Elements
       Identifier returnType = parent.returnType;
       if (identical(returnType, node)) {
         SimpleIdentifier name = parent.name;
@@ -2526,8 +2525,7 @@
           return element.unnamedConstructor;
         }
       }
-    }
-    if (parent is LibraryIdentifier) {
+    } else if (parent is LibraryIdentifier) {
       AstNode grandParent = parent.parent;
       if (grandParent is PartOfDirective) {
         Element element = grandParent.element;
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 2bf03d5..7f0a7b8 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -115,17 +115,18 @@
       return false;
     }
     if (argumentCount == 2) {
-      if (arguments[1] is! NamedExpression) {
-        return false;
-      }
-      if (!((arguments[1] as NamedExpression).name.label.name ==
-          _DEFAULT_VALUE_PARAM)) {
-        return false;
-      }
-      ParameterizedType defaultValueType =
-          namedArgumentValues[_DEFAULT_VALUE_PARAM].type;
-      if (!(identical(defaultValueType, expectedDefaultValueType) ||
-          identical(defaultValueType, typeProvider.nullType))) {
+      Expression secondArgument = arguments[1];
+      if (secondArgument is NamedExpression) {
+        if (!(secondArgument.name.label.name == _DEFAULT_VALUE_PARAM)) {
+          return false;
+        }
+        ParameterizedType defaultValueType =
+            namedArgumentValues[_DEFAULT_VALUE_PARAM].type;
+        if (!(identical(defaultValueType, expectedDefaultValueType) ||
+            identical(defaultValueType, typeProvider.nullType))) {
+          return false;
+        }
+      } else {
         return false;
       }
     }
@@ -620,13 +621,11 @@
     NodeList<Expression> superArguments = null;
     for (ConstructorInitializer initializer in initializers) {
       if (initializer is ConstructorFieldInitializer) {
-        ConstructorFieldInitializer constructorFieldInitializer = initializer;
-        Expression initializerExpression =
-            constructorFieldInitializer.expression;
+        Expression initializerExpression = initializer.expression;
         DartObjectImpl evaluationResult =
             initializerExpression.accept(initializerVisitor);
         if (evaluationResult != null) {
-          String fieldName = constructorFieldInitializer.fieldName.name;
+          String fieldName = initializer.fieldName.name;
           if (fieldMap.containsKey(fieldName)) {
             errorReporter.reportErrorForNode(
                 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
@@ -645,12 +644,11 @@
           }
         }
       } else if (initializer is SuperConstructorInvocation) {
-        SuperConstructorInvocation superConstructorInvocation = initializer;
-        SimpleIdentifier name = superConstructorInvocation.constructorName;
+        SimpleIdentifier name = initializer.constructorName;
         if (name != null) {
           superName = name.name;
         }
-        superArguments = superConstructorInvocation.argumentList.arguments;
+        superArguments = initializer.argumentList.arguments;
       } else if (initializer is RedirectingConstructorInvocation) {
         // This is a redirecting constructor, so just evaluate the constructor
         // it redirects to.
@@ -1333,11 +1331,10 @@
   DartObjectImpl visitMethodInvocation(MethodInvocation node) {
     Element element = node.methodName.staticElement;
     if (element is FunctionElement) {
-      FunctionElement function = element;
-      if (function.name == "identical") {
+      if (element.name == "identical") {
         NodeList<Expression> arguments = node.argumentList.arguments;
         if (arguments.length == 2) {
-          Element enclosingElement = function.enclosingElement;
+          Element enclosingElement = element.enclosingElement;
           if (enclosingElement is CompilationUnitElement) {
             LibraryElement library = enclosingElement.library;
             if (library.isDartCore) {
@@ -1488,17 +1485,15 @@
    * reported.
    */
   DartObjectImpl _getConstantValue(AstNode node, Element element) {
-    if (element is PropertyAccessorElement) {
-      element = (element as PropertyAccessorElement).variable;
-    }
-    if (element is VariableElementImpl) {
-      VariableElementImpl variableElementImpl = element;
-      evaluationEngine.validator.beforeGetEvaluationResult(element);
-      EvaluationResultImpl value = variableElementImpl.evaluationResult;
-      if (variableElementImpl.isConst && value != null) {
+    Element variableElement =
+        element is PropertyAccessorElement ? element.variable : element;
+    if (variableElement is VariableElementImpl) {
+      evaluationEngine.validator.beforeGetEvaluationResult(variableElement);
+      EvaluationResultImpl value = variableElement.evaluationResult;
+      if (variableElement.isConst && value != null) {
         return value.value;
       }
-    } else if (element is ExecutableElement) {
+    } else if (variableElement is ExecutableElement) {
       ExecutableElement function = element;
       if (function.isStatic) {
         ParameterizedType functionType = function.type;
@@ -1507,9 +1502,9 @@
         }
         return new DartObjectImpl(functionType, new FunctionState(function));
       }
-    } else if (element is ClassElement ||
-        element is FunctionTypeAliasElement ||
-        element is DynamicElementImpl) {
+    } else if (variableElement is ClassElement ||
+        variableElement is FunctionTypeAliasElement ||
+        variableElement is DynamicElementImpl) {
       return new DartObjectImpl(_typeProvider.typeType, new TypeState(element));
     }
     // TODO(brianwilkerson) Figure out which error to report.
diff --git a/pkg/analyzer/lib/src/dart/constant/utilities.dart b/pkg/analyzer/lib/src/dart/constant/utilities.dart
index c324d7f..80e736b 100644
--- a/pkg/analyzer/lib/src/dart/constant/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/constant/utilities.dart
@@ -290,10 +290,10 @@
 
   @override
   Object visitSimpleIdentifier(SimpleIdentifier node) {
-    Element element = node.staticElement;
-    if (element is PropertyAccessorElement) {
-      element = (element as PropertyAccessorElement).variable;
-    }
+    Element staticElement = node.staticElement;
+    Element element = staticElement is PropertyAccessorElement
+        ? staticElement.variable
+        : staticElement;
     if (element is VariableElement && element.isConst) {
       _callback(element);
     }
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
index 6ebb45d..a269925 100644
--- a/pkg/analyzer/lib/src/dart/constant/value.dart
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -214,11 +214,10 @@
 
   @override
   bool operator ==(Object object) {
-    if (object is! DartObjectImpl) {
-      return false;
+    if (object is DartObjectImpl) {
+      return type == object.type && _state == object._state;
     }
-    DartObjectImpl dartObject = object as DartObjectImpl;
-    return type == dartObject.type && _state == dartObject._state;
+    return false;
   }
 
   /**
@@ -372,8 +371,9 @@
 
   @override
   DartObject getField(String name) {
-    if (_state is GenericState) {
-      return (_state as GenericState).fields[name];
+    InstanceState state = _state;
+    if (state is GenericState) {
+      return state.fields[name];
     }
     return null;
   }
@@ -652,40 +652,45 @@
 
   @override
   bool toBoolValue() {
-    if (_state is BoolState) {
-      return (_state as BoolState).value;
+    InstanceState state = _state;
+    if (state is BoolState) {
+      return state.value;
     }
     return null;
   }
 
   @override
   double toDoubleValue() {
-    if (_state is DoubleState) {
-      return (_state as DoubleState).value;
+    InstanceState state = _state;
+    if (state is DoubleState) {
+      return state.value;
     }
     return null;
   }
 
   @override
   int toIntValue() {
-    if (_state is IntState) {
-      return (_state as IntState).value;
+    InstanceState state = _state;
+    if (state is IntState) {
+      return state.value;
     }
     return null;
   }
 
   @override
   List<DartObject> toListValue() {
-    if (_state is ListState) {
-      return (_state as ListState)._elements;
+    InstanceState state = _state;
+    if (state is ListState) {
+      return state._elements;
     }
     return null;
   }
 
   @override
   Map<DartObject, DartObject> toMapValue() {
-    if (_state is MapState) {
-      return (_state as MapState)._entries;
+    InstanceState state = _state;
+    if (state is MapState) {
+      return state._entries;
     }
     return null;
   }
@@ -695,24 +700,27 @@
 
   @override
   String toStringValue() {
-    if (_state is StringState) {
-      return (_state as StringState).value;
+    InstanceState state = _state;
+    if (state is StringState) {
+      return state.value;
     }
     return null;
   }
 
   @override
   String toSymbolValue() {
-    if (_state is SymbolState) {
-      return (_state as SymbolState).value;
+    InstanceState state = _state;
+    if (state is SymbolState) {
+      return state.value;
     }
     return null;
   }
 
   @override
   DartType toTypeValue() {
-    if (_state is TypeState) {
-      Element element = (_state as TypeState)._element;
+    InstanceState state = _state;
+    if (state is TypeState) {
+      Element element = state._element;
       if (element is TypeDefiningElement) {
         return element.type;
       }
@@ -1346,24 +1354,23 @@
 
   @override
   bool operator ==(Object object) {
-    if (object is! GenericState) {
-      return false;
-    }
-    GenericState state = object as GenericState;
-    HashSet<String> otherFields =
-        new HashSet<String>.from(state._fieldMap.keys.toSet());
-    for (String fieldName in _fieldMap.keys.toSet()) {
-      if (_fieldMap[fieldName] != state._fieldMap[fieldName]) {
-        return false;
+    if (object is GenericState) {
+      HashSet<String> otherFields =
+          new HashSet<String>.from(object._fieldMap.keys.toSet());
+      for (String fieldName in _fieldMap.keys.toSet()) {
+        if (_fieldMap[fieldName] != object._fieldMap[fieldName]) {
+          return false;
+        }
+        otherFields.remove(fieldName);
       }
-      otherFields.remove(fieldName);
-    }
-    for (String fieldName in otherFields) {
-      if (state._fieldMap[fieldName] != _fieldMap[fieldName]) {
-        return false;
+      for (String fieldName in otherFields) {
+        if (object._fieldMap[fieldName] != _fieldMap[fieldName]) {
+          return false;
+        }
       }
+      return true;
     }
-    return true;
+    return false;
   }
 
   @override
@@ -2299,22 +2306,22 @@
 
   @override
   bool operator ==(Object object) {
-    if (object is! ListState) {
-      return false;
-    }
-    List<DartObjectImpl> otherElements = (object as ListState)._elements;
-    int count = _elements.length;
-    if (otherElements.length != count) {
-      return false;
-    } else if (count == 0) {
+    if (object is ListState) {
+      List<DartObjectImpl> otherElements = object._elements;
+      int count = _elements.length;
+      if (otherElements.length != count) {
+        return false;
+      } else if (count == 0) {
+        return true;
+      }
+      for (int i = 0; i < count; i++) {
+        if (_elements[i] != otherElements[i]) {
+          return false;
+        }
+      }
       return true;
     }
-    for (int i = 0; i < count; i++) {
-      if (_elements[i] != otherElements[i]) {
-        return false;
-      }
-    }
-    return true;
+    return false;
   }
 
   @override
@@ -2381,25 +2388,24 @@
 
   @override
   bool operator ==(Object object) {
-    if (object is! MapState) {
-      return false;
-    }
-    HashMap<DartObjectImpl, DartObjectImpl> otherElements =
-        (object as MapState)._entries;
-    int count = _entries.length;
-    if (otherElements.length != count) {
-      return false;
-    } else if (count == 0) {
+    if (object is MapState) {
+      HashMap<DartObjectImpl, DartObjectImpl> otherElements = object._entries;
+      int count = _entries.length;
+      if (otherElements.length != count) {
+        return false;
+      } else if (count == 0) {
+        return true;
+      }
+      for (DartObjectImpl key in _entries.keys) {
+        DartObjectImpl value = _entries[key];
+        DartObjectImpl otherValue = otherElements[key];
+        if (value != otherValue) {
+          return false;
+        }
+      }
       return true;
     }
-    for (DartObjectImpl key in _entries.keys) {
-      DartObjectImpl value = _entries[key];
-      DartObjectImpl otherValue = otherElements[key];
-      if (value != otherValue) {
-        return false;
-      }
-    }
-    return true;
+    return false;
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index 2803273..08de907 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -74,6 +74,11 @@
   final LibraryElementImpl libraryElement;
 
   /**
+   * Map from sources referenced by this library to their modification times.
+   */
+  final Map<Source, int> sourceModificationTimeMap;
+
+  /**
    * Map from sources imported by this library to their corresponding library
    * elements.
    */
@@ -126,6 +131,7 @@
   DirectiveElementBuilder(
       this.context,
       this.libraryElement,
+      this.sourceModificationTimeMap,
       this.importLibraryMap,
       this.importSourceKindMap,
       this.exportLibraryMap,
@@ -163,7 +169,8 @@
     // Remove previous element. (It will remain null if the target is missing.)
     node.element = null;
     Source exportedSource = node.source;
-    if (exportedSource != null && context.exists(exportedSource)) {
+    int exportedTime = sourceModificationTimeMap[exportedSource] ?? -1;
+    if (exportedTime != -1) {
       // The exported source will be null if the URI in the export
       // directive was invalid.
       LibraryElement exportedLibrary = exportLibraryMap[exportedSource];
@@ -205,7 +212,8 @@
     // Remove previous element. (It will remain null if the target is missing.)
     node.element = null;
     Source importedSource = node.source;
-    if (importedSource != null && context.exists(importedSource)) {
+    int importedTime = sourceModificationTimeMap[importedSource] ?? -1;
+    if (importedTime != -1) {
       // The imported source will be null if the URI in the import
       // directive was invalid.
       LibraryElement importedLibrary = importLibraryMap[importedSource];
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 63528f1b..567c6fe 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -463,29 +463,33 @@
     // expected types.
     //
     for (PropertyAccessorElement accessor in _accessors) {
-      if ((accessor as PropertyAccessorElementImpl).identifier == identifier) {
-        return accessor as PropertyAccessorElementImpl;
+      PropertyAccessorElementImpl accessorImpl = accessor;
+      if (accessorImpl.identifier == identifier) {
+        return accessorImpl;
       }
     }
     for (ConstructorElement constructor in _constructors) {
-      if ((constructor as ConstructorElementImpl).identifier == identifier) {
-        return constructor as ConstructorElementImpl;
+      ConstructorElementImpl constructorImpl = constructor;
+      if (constructorImpl.identifier == identifier) {
+        return constructorImpl;
       }
     }
     for (FieldElement field in _fields) {
-      if ((field as FieldElementImpl).identifier == identifier) {
-        return field as FieldElementImpl;
+      FieldElementImpl fieldImpl = field;
+      if (fieldImpl.identifier == identifier) {
+        return fieldImpl;
       }
     }
     for (MethodElement method in _methods) {
-      if ((method as MethodElementImpl).identifier == identifier) {
-        return method as MethodElementImpl;
+      MethodElementImpl methodImpl = method;
+      if (methodImpl.identifier == identifier) {
+        return methodImpl;
       }
     }
     for (TypeParameterElement typeParameter in _typeParameters) {
-      if ((typeParameter as TypeParameterElementImpl).identifier ==
-          identifier) {
-        return typeParameter as TypeParameterElementImpl;
+      TypeParameterElementImpl typeParameterImpl = typeParameter;
+      if (typeParameterImpl.identifier == identifier) {
+        return typeParameterImpl;
       }
     }
     return null;
@@ -778,11 +782,12 @@
         _internalLookUpSetter(setterName, library, includeThisClass);
     while (setter != null && setter.isAbstract) {
       Element definingClass = setter.enclosingElement;
-      if (definingClass is! ClassElementImpl) {
+      if (definingClass is ClassElementImpl) {
+        setter =
+            definingClass._internalLookUpSetter(setterName, library, false);
+      } else {
         return null;
       }
-      setter = (definingClass as ClassElementImpl)
-          ._internalLookUpSetter(setterName, library, false);
     }
     return setter;
   }
@@ -1154,34 +1159,39 @@
     // expected types.
     //
     for (PropertyAccessorElement accessor in _accessors) {
-      if ((accessor as PropertyAccessorElementImpl).identifier == identifier) {
-        return accessor as PropertyAccessorElementImpl;
+      PropertyAccessorElementImpl accessorImpl = accessor;
+      if (accessorImpl.identifier == identifier) {
+        return accessorImpl;
       }
     }
-    for (VariableElement variable in _variables) {
-      if ((variable as VariableElementImpl).identifier == identifier) {
-        return variable as VariableElementImpl;
+    for (TopLevelVariableElement variable in _variables) {
+      TopLevelVariableElementImpl variableImpl = variable;
+      if (variableImpl.identifier == identifier) {
+        return variableImpl;
       }
     }
-    for (ExecutableElement function in _functions) {
-      if ((function as ExecutableElementImpl).identifier == identifier) {
-        return function as ExecutableElementImpl;
+    for (FunctionElement function in _functions) {
+      FunctionElementImpl functionImpl = function;
+      if (functionImpl.identifier == identifier) {
+        return functionImpl;
       }
     }
     for (FunctionTypeAliasElement typeAlias in _typeAliases) {
-      if ((typeAlias as FunctionTypeAliasElementImpl).identifier ==
-          identifier) {
-        return typeAlias as FunctionTypeAliasElementImpl;
+      FunctionTypeAliasElementImpl typeAliasImpl = typeAlias;
+      if (typeAliasImpl.identifier == identifier) {
+        return typeAliasImpl;
       }
     }
     for (ClassElement type in _types) {
-      if ((type as ClassElementImpl).identifier == identifier) {
-        return type as ClassElementImpl;
+      ClassElementImpl typeImpl = type;
+      if (typeImpl.identifier == identifier) {
+        return typeImpl;
       }
     }
     for (ClassElement type in _enums) {
-      if ((type as ClassElementImpl).identifier == identifier) {
-        return type as ClassElementImpl;
+      ClassElementImpl typeImpl = type;
+      if (typeImpl.identifier == identifier) {
+        return typeImpl;
       }
     }
     return null;
@@ -1718,9 +1728,10 @@
   }
 
   @override
-  bool get isJS => element is ConstructorElement &&
-        element.enclosingElement.name == _JS_CLASS_NAME &&
-        element.library?.name == _JS_LIB_NAME;
+  bool get isJS =>
+      element is ConstructorElement &&
+      element.enclosingElement.name == _JS_CLASS_NAME &&
+      element.library?.name == _JS_LIB_NAME;
 
   @override
   bool get isMustCallSuper =>
@@ -2333,21 +2344,20 @@
     if (identical(this, object)) {
       return true;
     }
-    if (object is! ElementLocationImpl) {
-      return false;
-    }
-    ElementLocationImpl location = object as ElementLocationImpl;
-    List<String> otherComponents = location._components;
-    int length = _components.length;
-    if (otherComponents.length != length) {
-      return false;
-    }
-    for (int i = 0; i < length; i++) {
-      if (_components[i] != otherComponents[i]) {
+    if (object is ElementLocationImpl) {
+      List<String> otherComponents = object._components;
+      int length = _components.length;
+      if (otherComponents.length != length) {
         return false;
       }
+      for (int i = 0; i < length; i++) {
+        if (_components[i] != otherComponents[i]) {
+          return false;
+        }
+      }
+      return true;
     }
-    return true;
+    return false;
   }
 
   @override
@@ -2593,7 +2603,7 @@
         if (i > 0) {
           buffer.write(", ");
         }
-        ParameterElementImpl parameter = _parameters[i] as ParameterElementImpl;
+        ParameterElement parameter = _parameters[i];
         ParameterKind parameterKind = parameter.parameterKind;
         if (parameterKind != kind) {
           if (closing != null) {
@@ -2625,24 +2635,28 @@
 
   @override
   ElementImpl getChild(String identifier) {
-    for (ExecutableElement function in _functions) {
-      if ((function as ExecutableElementImpl).identifier == identifier) {
-        return function as ExecutableElementImpl;
+    for (FunctionElement function in _functions) {
+      FunctionElementImpl functionImpl = function;
+      if (functionImpl.identifier == identifier) {
+        return functionImpl;
       }
     }
     for (LabelElement label in _labels) {
-      if ((label as LabelElementImpl).identifier == identifier) {
-        return label as LabelElementImpl;
+      LabelElementImpl labelImpl = label;
+      if (labelImpl.identifier == identifier) {
+        return labelImpl;
       }
     }
-    for (VariableElement variable in _localVariables) {
-      if ((variable as VariableElementImpl).identifier == identifier) {
-        return variable as VariableElementImpl;
+    for (LocalVariableElement variable in _localVariables) {
+      LocalVariableElementImpl variableImpl = variable;
+      if (variableImpl.identifier == identifier) {
+        return variableImpl;
       }
     }
     for (ParameterElement parameter in _parameters) {
-      if ((parameter as ParameterElementImpl).identifier == identifier) {
-        return parameter as ParameterElementImpl;
+      ParameterElementImpl parameterImpl = parameter;
+      if (parameterImpl.identifier == identifier) {
+        return parameterImpl;
       }
     }
     return null;
@@ -3023,15 +3037,16 @@
 
   @override
   ElementImpl getChild(String identifier) {
-    for (VariableElement parameter in _parameters) {
-      if ((parameter as VariableElementImpl).identifier == identifier) {
-        return parameter as VariableElementImpl;
+    for (ParameterElement parameter in _parameters) {
+      ParameterElementImpl parameterImpl = parameter;
+      if (parameterImpl.identifier == identifier) {
+        return parameterImpl;
       }
     }
     for (TypeParameterElement typeParameter in _typeParameters) {
-      if ((typeParameter as TypeParameterElementImpl).identifier ==
-          identifier) {
-        return typeParameter as TypeParameterElementImpl;
+      TypeParameterElementImpl typeParameterImpl = typeParameter;
+      if (typeParameterImpl.identifier == identifier) {
+        return typeParameterImpl;
       }
     }
     return null;
@@ -3283,18 +3298,18 @@
 
   @override
   int get codeLength {
-    if (_definingCompilationUnit is CompilationUnitElementImpl) {
-      return (_definingCompilationUnit as CompilationUnitElementImpl)
-          .codeLength;
+    CompilationUnitElement unit = _definingCompilationUnit;
+    if (unit is CompilationUnitElementImpl) {
+      return unit.codeLength;
     }
     return null;
   }
 
   @override
   int get codeOffset {
-    if (_definingCompilationUnit is CompilationUnitElementImpl) {
-      return (_definingCompilationUnit as CompilationUnitElementImpl)
-          .codeOffset;
+    CompilationUnitElement unit = _definingCompilationUnit;
+    if (unit is CompilationUnitElementImpl) {
+      return unit.codeOffset;
     }
     return null;
   }
@@ -3596,23 +3611,26 @@
 
   @override
   ElementImpl getChild(String identifier) {
-    if ((_definingCompilationUnit as CompilationUnitElementImpl).identifier ==
-        identifier) {
-      return _definingCompilationUnit as CompilationUnitElementImpl;
+    CompilationUnitElementImpl unitImpl = _definingCompilationUnit;
+    if (unitImpl.identifier == identifier) {
+      return unitImpl;
     }
     for (CompilationUnitElement part in _parts) {
-      if ((part as CompilationUnitElementImpl).identifier == identifier) {
-        return part as CompilationUnitElementImpl;
+      CompilationUnitElementImpl partImpl = part;
+      if (partImpl.identifier == identifier) {
+        return partImpl;
       }
     }
     for (ImportElement importElement in _imports) {
-      if ((importElement as ImportElementImpl).identifier == identifier) {
-        return importElement as ImportElementImpl;
+      ImportElementImpl importElementImpl = importElement;
+      if (importElementImpl.identifier == identifier) {
+        return importElementImpl;
       }
     }
     for (ExportElement exportElement in _exports) {
-      if ((exportElement as ExportElementImpl).identifier == identifier) {
-        return exportElement as ExportElementImpl;
+      ExportElementImpl exportElementImpl = exportElement;
+      if (exportElementImpl.identifier == identifier) {
+        return exportElementImpl;
       }
     }
     return null;
@@ -3684,15 +3702,13 @@
     // are in the case where library cycles have simply never been computed from
     // a newly reachable node.
     Set<LibraryElementImpl> active = new HashSet();
-    void invalidate(LibraryElement library) {
-      if (library is LibraryElementHandle) {
-        library = (library as LibraryElementHandle).actualElement;
-      }
-      LibraryElementImpl libraryImpl = library;
-      if (active.add(libraryImpl)) {
-        if (libraryImpl._libraryCycle != null) {
-          libraryImpl._libraryCycle.forEach(invalidate);
-          libraryImpl._libraryCycle = null;
+    void invalidate(LibraryElement element) {
+      LibraryElementImpl library =
+          element is LibraryElementHandle ? element.actualElement : element;
+      if (active.add(library)) {
+        if (library._libraryCycle != null) {
+          library._libraryCycle.forEach(invalidate);
+          library._libraryCycle = null;
         }
         library.exportedLibraries.forEach(invalidate);
         library.importedLibraries.forEach(invalidate);
@@ -3917,10 +3933,8 @@
   @override
   String get name {
     String name = super.name;
-    if (isOperator && name == "-") {
-      if (parameters.length == 0) {
-        return "unary-";
-      }
+    if (name == '-' && parameters.isEmpty) {
+      return 'unary-';
     }
     return super.name;
   }
@@ -4485,8 +4499,9 @@
   @override
   ElementImpl getChild(String identifier) {
     for (ParameterElement parameter in _parameters) {
-      if ((parameter as ParameterElementImpl).identifier == identifier) {
-        return parameter as ParameterElementImpl;
+      ParameterElementImpl parameterImpl = parameter;
+      if (parameterImpl.identifier == identifier) {
+        return parameterImpl;
       }
     }
     return null;
@@ -4702,8 +4717,7 @@
     }
     if (enclosingElement is ClassElement) {
       return getNodeMatching((node) => node is MethodDeclaration);
-    }
-    if (enclosingElement is CompilationUnitElement) {
+    } else if (enclosingElement is CompilationUnitElement) {
       return getNodeMatching((node) => node is FunctionDeclaration);
     }
     return null;
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 475383e..14e459e 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -68,6 +68,137 @@
 }
 
 /**
+ * The type created internally if a circular reference is ever detected in a
+ * function type.
+ */
+class CircularFunctionTypeImpl extends DynamicTypeImpl
+    implements FunctionTypeImpl {
+  CircularFunctionTypeImpl() : super._circular();
+
+  @override
+  List<ParameterElement> get baseParameters => ParameterElement.EMPTY_LIST;
+
+  @override
+  DartType get baseReturnType => DynamicTypeImpl.instance;
+
+  @override
+  List<TypeParameterElement> get boundTypeParameters =>
+      TypeParameterElement.EMPTY_LIST;
+
+  @override
+  FunctionTypedElement get element => super.element;
+
+  @override
+  bool get isInstantiated => false;
+
+  @override
+  Map<String, DartType> get namedParameterTypes => <String, DartType>{};
+
+  @override
+  List<FunctionTypeAliasElement> get newPrune =>
+      FunctionTypeAliasElement.EMPTY_LIST;
+
+  @override
+  List<String> get normalParameterNames => <String>[];
+
+  @override
+  List<DartType> get normalParameterTypes => DartType.EMPTY_LIST;
+
+  @override
+  List<String> get optionalParameterNames => <String>[];
+
+  @override
+  List<DartType> get optionalParameterTypes => DartType.EMPTY_LIST;
+
+  @override
+  List<ParameterElement> get parameters => ParameterElement.EMPTY_LIST;
+
+  @override
+  List<FunctionTypeAliasElement> get prunedTypedefs =>
+      FunctionTypeAliasElement.EMPTY_LIST;
+
+  @override
+  DartType get returnType => DynamicTypeImpl.instance;
+
+  @override
+  List<DartType> get typeArguments => DartType.EMPTY_LIST;
+
+  @override
+  List<TypeParameterElement> get typeFormals => TypeParameterElement.EMPTY_LIST;
+
+  @override
+  List<TypeParameterElement> get typeParameters =>
+      TypeParameterElement.EMPTY_LIST;
+
+  @override
+  bool get _isInstantiated => false;
+
+  @override
+  List<DartType> get _typeArguments => DartType.EMPTY_LIST;
+
+  @override
+  void set _typeArguments(List<DartType> arguments) {
+    throw new UnsupportedError('Cannot have type arguments');
+  }
+
+  @override
+  List<TypeParameterElement> get _typeParameters =>
+      TypeParameterElement.EMPTY_LIST;
+
+  @override
+  void set _typeParameters(List<TypeParameterElement> parameters) {
+    throw new UnsupportedError('Cannot have type parameters');
+  }
+
+  @override
+  bool operator ==(Object object) => object is CircularFunctionTypeImpl;
+
+  @override
+  void appendTo(StringBuffer buffer) {
+    buffer.write('...');
+  }
+
+  @override
+  FunctionTypeImpl instantiate(List<DartType> argumentTypes) => this;
+
+  @override
+  FunctionTypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
+
+  @override
+  FunctionType substitute2(
+      List<DartType> argumentTypes, List<DartType> parameterTypes,
+      [List<FunctionTypeAliasElement> prune]) {
+    return this;
+  }
+
+  @override
+  FunctionTypeImpl substitute3(List<DartType> argumentTypes) => this;
+
+  @override
+  void _forEachParameterType(
+      ParameterKind kind, callback(String name, DartType type)) {
+    // There are no parameters.
+  }
+
+  @override
+  void _freeVariablesInFunctionType(
+      FunctionType type, Set<TypeParameterType> free) {
+    // There are no free variables
+  }
+
+  @override
+  void _freeVariablesInInterfaceType(
+      InterfaceType type, Set<TypeParameterType> free) {
+    // There are no free variables
+  }
+
+  @override
+  void _freeVariablesInType(DartType type, Set<TypeParameterType> free) {
+    // There are no free variables
+  }
+}
+
+/**
  * Type created internally if a circular reference is ever detected.  Behaves
  * like `dynamic`, except that when converted to a string it is displayed as
  * `...`.
@@ -76,9 +207,6 @@
   CircularTypeImpl() : super._circular();
 
   @override
-  int get hashCode => 1;
-
-  @override
   bool operator ==(Object object) => object is CircularTypeImpl;
 
   @override
@@ -290,15 +418,15 @@
     List<DartType> optionalParameterTypes = this.optionalParameterTypes;
     Iterable<DartType> namedParameterTypes = this.namedParameterTypes.values;
     // Generate the hashCode
-    int code = (returnType as TypeImpl).hashCode;
+    int code = returnType.hashCode;
     for (int i = 0; i < normalParameterTypes.length; i++) {
-      code = (code << 1) + (normalParameterTypes[i] as TypeImpl).hashCode;
+      code = (code << 1) + normalParameterTypes[i].hashCode;
     }
     for (int i = 0; i < optionalParameterTypes.length; i++) {
-      code = (code << 1) + (optionalParameterTypes[i] as TypeImpl).hashCode;
+      code = (code << 1) + optionalParameterTypes[i].hashCode;
     }
     for (DartType type in namedParameterTypes) {
-      code = (code << 1) + (type as TypeImpl).hashCode;
+      code = (code << 1) + type.hashCode;
     }
     return code;
   }
@@ -484,32 +612,30 @@
 
   @override
   bool operator ==(Object object) {
-    if (object is! FunctionTypeImpl) {
-      return false;
-    }
-    FunctionTypeImpl otherType = object as FunctionTypeImpl;
-    if (typeFormals.length != otherType.typeFormals.length) {
-      return false;
-    }
-    // `<T>T -> T` should be equal to `<U>U -> U`
-    // To test this, we instantiate both types with the same (unique) type
-    // variables, and see if the result is equal.
-    if (typeFormals.isNotEmpty) {
-      List<DartType> freshVariables =
-          relateTypeFormals(this, otherType, (t, s) => t == s);
-      if (freshVariables == null) {
+    if (object is FunctionTypeImpl) {
+      if (typeFormals.length != object.typeFormals.length) {
         return false;
       }
-      return instantiate(freshVariables) ==
-          otherType.instantiate(freshVariables);
+      // `<T>T -> T` should be equal to `<U>U -> U`
+      // To test this, we instantiate both types with the same (unique) type
+      // variables, and see if the result is equal.
+      if (typeFormals.isNotEmpty) {
+        List<DartType> freshVariables =
+            relateTypeFormals(this, object, (t, s) => t == s);
+        if (freshVariables == null) {
+          return false;
+        }
+        return instantiate(freshVariables) ==
+            object.instantiate(freshVariables);
+      }
+      return returnType == object.returnType &&
+          TypeImpl.equalArrays(
+              normalParameterTypes, object.normalParameterTypes) &&
+          TypeImpl.equalArrays(
+              optionalParameterTypes, object.optionalParameterTypes) &&
+          _equals(namedParameterTypes, object.namedParameterTypes);
     }
-
-    return returnType == otherType.returnType &&
-        TypeImpl.equalArrays(
-            normalParameterTypes, otherType.normalParameterTypes) &&
-        TypeImpl.equalArrays(
-            optionalParameterTypes, otherType.optionalParameterTypes) &&
-        _equals(namedParameterTypes, otherType.namedParameterTypes);
+    return false;
   }
 
   @override
@@ -675,12 +801,12 @@
   }
 
   @override
-  TypeImpl pruned(List<FunctionTypeAliasElement> prune) {
+  FunctionTypeImpl pruned(List<FunctionTypeAliasElement> prune) {
     if (prune == null) {
       return this;
     } else if (prune.contains(element)) {
       // Circularity found.  Prune the type declaration.
-      return new CircularTypeImpl();
+      return new CircularFunctionTypeImpl();
     } 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
@@ -696,7 +822,7 @@
   }
 
   @override
-  DartType substitute2(
+  FunctionType substitute2(
       List<DartType> argumentTypes, List<DartType> parameterTypes,
       [List<FunctionTypeAliasElement> prune]) {
     // Pruned types should only ever result from performing type variable
@@ -710,7 +836,7 @@
     Element element = this.element;
     if (prune != null && prune.contains(element)) {
       // Circularity found.  Prune the type declaration.
-      return new CircularTypeImpl();
+      return new CircularFunctionTypeImpl();
     }
     if (argumentTypes.length == 0) {
       return this.pruned(prune);
@@ -804,7 +930,7 @@
       FunctionType t,
       DartType other,
       bool parameterRelation(DartType t, DartType s),
-      FunctionType instantiateToBounds(FunctionType t),
+      DartType instantiateToBounds(DartType t),
       {bool returnRelation(DartType t, DartType s)}) {
     returnRelation ??= parameterRelation;
 
@@ -1182,12 +1308,11 @@
     if (identical(object, this)) {
       return true;
     }
-    if (object is! InterfaceTypeImpl) {
-      return false;
+    if (object is InterfaceTypeImpl) {
+      return (element == object.element) &&
+          TypeImpl.equalArrays(typeArguments, object.typeArguments);
     }
-    InterfaceTypeImpl otherType = object as InterfaceTypeImpl;
-    return (element == otherType.element) &&
-        TypeImpl.equalArrays(typeArguments, otherType.typeArguments);
+    return false;
   }
 
   @override
@@ -2104,7 +2229,7 @@
   bool isAssignableTo(DartType type) {
     // An interface type T may be assigned to a type S, written T <=> S, iff
     // either T <: S or S <: T.
-    return isSubtypeOf(type) || (type as TypeImpl).isSubtypeOf(this);
+    return isSubtypeOf(type) || type.isSubtypeOf(this);
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart b/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
new file mode 100644
index 0000000..76cedf7
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
@@ -0,0 +1,1239 @@
+// 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: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/element/element.dart';
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/generated/type_system.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
+
+/**
+ * Instances of the class `InheritanceManager` manage the knowledge of where class members
+ * (methods, getters & setters) are inherited from.
+ */
+class InheritanceManager {
+  /**
+   * The [LibraryElement] that is managed by this manager.
+   */
+  LibraryElement _library;
+
+  /**
+   * This is a mapping between each [ClassElement] and a map between the [String] member
+   * names and the associated [ExecutableElement] in the mixin and superclass chain.
+   */
+  Map<ClassElement, Map<String, ExecutableElement>> _classLookup;
+
+  /**
+   * This is a mapping between each [ClassElement] and a map between the [String] member
+   * names and the associated [ExecutableElement] in the interface set.
+   */
+  Map<ClassElement, Map<String, ExecutableElement>> _interfaceLookup;
+
+  /**
+   * A map between each visited [ClassElement] and the set of [AnalysisError]s found on
+   * the class element.
+   */
+  Map<ClassElement, Set<AnalysisError>> _errorsInClassElement =
+      new HashMap<ClassElement, Set<AnalysisError>>();
+
+  /**
+   * Initialize a newly created inheritance manager.
+   *
+   * @param library the library element context that the inheritance mappings are being generated
+   */
+  InheritanceManager(LibraryElement library) {
+    this._library = library;
+    _classLookup = new HashMap<ClassElement, Map<String, ExecutableElement>>();
+    _interfaceLookup =
+        new HashMap<ClassElement, Map<String, ExecutableElement>>();
+  }
+
+  /**
+   * Set the new library element context.
+   *
+   * @param library the new library element
+   */
+  void set libraryElement(LibraryElement library) {
+    this._library = library;
+  }
+
+  /**
+   * Return the set of [AnalysisError]s found on the passed [ClassElement], or
+   * `null` if there are none.
+   *
+   * @param classElt the class element to query
+   * @return the set of [AnalysisError]s found on the passed [ClassElement], or
+   *         `null` if there are none
+   */
+  Set<AnalysisError> getErrors(ClassElement classElt) =>
+      _errorsInClassElement[classElt];
+
+  /**
+   * Get and return a mapping between the set of all string names of the members inherited from the
+   * passed [ClassElement] superclass hierarchy, and the associated [ExecutableElement].
+   *
+   * @param classElt the class element to query
+   * @return a mapping between the set of all members inherited from the passed [ClassElement]
+   *         superclass hierarchy, and the associated [ExecutableElement]
+   */
+  @deprecated
+  MemberMap getMapOfMembersInheritedFromClasses(ClassElement classElt) =>
+      new MemberMap.fromMap(
+          _computeClassChainLookupMap(classElt, new HashSet<ClassElement>()));
+
+  /**
+   * Get and return a mapping between the set of all string names of the members inherited from the
+   * passed [ClassElement] interface hierarchy, and the associated [ExecutableElement].
+   *
+   * @param classElt the class element to query
+   * @return a mapping between the set of all string names of the members inherited from the passed
+   *         [ClassElement] interface hierarchy, and the associated [ExecutableElement].
+   */
+  @deprecated
+  MemberMap getMapOfMembersInheritedFromInterfaces(ClassElement classElt) =>
+      new MemberMap.fromMap(
+          _computeInterfaceLookupMap(classElt, new HashSet<ClassElement>()));
+
+  /**
+   * Return a table mapping the string names of the members inherited from the
+   * passed [ClassElement]'s superclass hierarchy, and the associated executable
+   * element.
+   */
+  Map<String, ExecutableElement> getMembersInheritedFromClasses(
+          ClassElement classElt) =>
+      _computeClassChainLookupMap(classElt, new HashSet<ClassElement>());
+
+  /**
+   * Return a table mapping the string names of the members inherited from the
+   * passed [ClassElement]'s interface hierarchy, and the associated executable
+   * element.
+   */
+  Map<String, ExecutableElement> getMembersInheritedFromInterfaces(
+          ClassElement classElt) =>
+      _computeInterfaceLookupMap(classElt, new HashSet<ClassElement>());
+
+  /**
+   * Given some [ClassElement] and some member name, this returns the
+   * [ExecutableElement] that the class inherits from the mixins,
+   * superclasses or interfaces, that has the member name, if no member is inherited `null` is
+   * returned.
+   *
+   * @param classElt the class element to query
+   * @param memberName the name of the executable element to find and return
+   * @return the inherited executable element with the member name, or `null` if no such
+   *         member exists
+   */
+  ExecutableElement lookupInheritance(
+      ClassElement classElt, String memberName) {
+    if (memberName == null || memberName.isEmpty) {
+      return null;
+    }
+    ExecutableElement executable = _computeClassChainLookupMap(
+        classElt, new HashSet<ClassElement>())[memberName];
+    if (executable == null) {
+      return _computeInterfaceLookupMap(classElt, new HashSet<ClassElement>())[
+          memberName];
+    }
+    return executable;
+  }
+
+  /**
+   * Given some [ClassElement] and some member name, this returns the
+   * [ExecutableElement] that the class either declares itself, or
+   * inherits, that has the member name, if no member is inherited `null` is returned.
+   *
+   * @param classElt the class element to query
+   * @param memberName the name of the executable element to find and return
+   * @return the inherited executable element with the member name, or `null` if no such
+   *         member exists
+   */
+  ExecutableElement lookupMember(ClassElement classElt, String memberName) {
+    ExecutableElement element = _lookupMemberInClass(classElt, memberName);
+    if (element != null) {
+      return element;
+    }
+    return lookupInheritance(classElt, memberName);
+  }
+
+  /**
+   * Determine the set of methods which is overridden by the given class member. If no member is
+   * inherited, an empty list is returned. If one of the inherited members is a
+   * [MultiplyInheritedExecutableElement], then it is expanded into its constituent inherited
+   * elements.
+   *
+   * @param classElt the class to query
+   * @param memberName the name of the class member to query
+   * @return a list of overridden methods
+   */
+  List<ExecutableElement> lookupOverrides(
+      ClassElement classElt, String memberName) {
+    List<ExecutableElement> result = new List<ExecutableElement>();
+    if (memberName == null || memberName.isEmpty) {
+      return result;
+    }
+    List<Map<String, ExecutableElement>> interfaceMaps =
+        _gatherInterfaceLookupMaps(classElt, new HashSet<ClassElement>());
+    if (interfaceMaps != null) {
+      for (Map<String, ExecutableElement> interfaceMap in interfaceMaps) {
+        ExecutableElement overriddenElement = interfaceMap[memberName];
+        if (overriddenElement != null) {
+          if (overriddenElement is MultiplyInheritedExecutableElement) {
+            for (ExecutableElement element
+                in overriddenElement.inheritedElements) {
+              result.add(element);
+            }
+          } else {
+            result.add(overriddenElement);
+          }
+        }
+      }
+    }
+    return result;
+  }
+
+  /**
+   * This method takes some inherited [FunctionType], and resolves all the parameterized types
+   * in the function type, dependent on the class in which it is being overridden.
+   *
+   * @param baseFunctionType the function type that is being overridden
+   * @param memberName the name of the member, this is used to lookup the inheritance path of the
+   *          override
+   * @param definingType the type that is overriding the member
+   * @return the passed function type with any parameterized types substituted
+   */
+  // TODO(jmesserly): investigate why this is needed in ErrorVerifier's override
+  // checking. There seems to be some rare cases where we get partially
+  // substituted type arguments, and the function types don't compare equally.
+  FunctionType substituteTypeArgumentsInMemberFromInheritance(
+      FunctionType baseFunctionType,
+      String memberName,
+      InterfaceType definingType) {
+    // if the baseFunctionType is null, or does not have any parameters,
+    // return it.
+    if (baseFunctionType == null ||
+        baseFunctionType.typeArguments.length == 0) {
+      return baseFunctionType;
+    }
+    // First, generate the path from the defining type to the overridden member
+    Queue<InterfaceType> inheritancePath = new Queue<InterfaceType>();
+    _computeInheritancePath(inheritancePath, definingType, memberName);
+    if (inheritancePath == null || inheritancePath.isEmpty) {
+      // TODO(jwren) log analysis engine error
+      return baseFunctionType;
+    }
+    FunctionType functionTypeToReturn = baseFunctionType;
+    // loop backward through the list substituting as we go:
+    while (!inheritancePath.isEmpty) {
+      InterfaceType lastType = inheritancePath.removeLast();
+      List<DartType> parameterTypes = lastType.element.type.typeArguments;
+      List<DartType> argumentTypes = lastType.typeArguments;
+      functionTypeToReturn =
+          functionTypeToReturn.substitute2(argumentTypes, parameterTypes);
+    }
+    return functionTypeToReturn;
+  }
+
+  /**
+   * Compute and return a mapping between the set of all string names of the members inherited from
+   * the passed [ClassElement] superclass hierarchy, and the associated
+   * [ExecutableElement].
+   *
+   * @param classElt the class element to query
+   * @param visitedClasses a set of visited classes passed back into this method when it calls
+   *          itself recursively
+   * @return a mapping between the set of all string names of the members inherited from the passed
+   *         [ClassElement] superclass hierarchy, and the associated [ExecutableElement]
+   */
+  Map<String, ExecutableElement> _computeClassChainLookupMap(
+      ClassElement classElt, Set<ClassElement> visitedClasses) {
+    Map<String, ExecutableElement> resultMap = _classLookup[classElt];
+    if (resultMap != null) {
+      return resultMap;
+    } else {
+      resultMap = new Map<String, ExecutableElement>();
+    }
+    ClassElement superclassElt = null;
+    InterfaceType supertype = classElt.supertype;
+    if (supertype != null) {
+      superclassElt = supertype.element;
+    } else {
+      // classElt is Object
+      _classLookup[classElt] = resultMap;
+      return resultMap;
+    }
+    if (superclassElt != null) {
+      if (!visitedClasses.contains(superclassElt)) {
+        visitedClasses.add(superclassElt);
+        try {
+          resultMap = new Map<String, ExecutableElement>.from(
+              _computeClassChainLookupMap(superclassElt, visitedClasses));
+          //
+          // Substitute the super types down the hierarchy.
+          //
+          _substituteTypeParametersDownHierarchy(supertype, resultMap);
+          //
+          // Include the members from the superclass in the resultMap.
+          //
+          _recordMapWithClassMembers(resultMap, supertype, false);
+        } finally {
+          visitedClasses.remove(superclassElt);
+        }
+      } else {
+        // This case happens only when the superclass was previously visited and
+        // not in the lookup, meaning this is meant to shorten the compute for
+        // recursive cases.
+        _classLookup[superclassElt] = resultMap;
+        return resultMap;
+      }
+    }
+    //
+    // Include the members from the mixins in the resultMap.  If there are
+    // multiple mixins, visit them in the order listed so that methods in later
+    // mixins will overwrite identically-named methods in earlier mixins.
+    //
+    List<InterfaceType> mixins = classElt.mixins;
+    for (InterfaceType mixin in mixins) {
+      ClassElement mixinElement = mixin.element;
+      if (mixinElement != null) {
+        if (!visitedClasses.contains(mixinElement)) {
+          visitedClasses.add(mixinElement);
+          try {
+            Map<String, ExecutableElement> map =
+                new Map<String, ExecutableElement>.from(
+                    _computeClassChainLookupMap(mixinElement, visitedClasses));
+            //
+            // Substitute the super types down the hierarchy.
+            //
+            _substituteTypeParametersDownHierarchy(mixin, map);
+            //
+            // Include the members from the superclass in the resultMap.
+            //
+            _recordMapWithClassMembers(map, mixin, false);
+            //
+            // Add the members from map into result map.
+            //
+            for (String memberName in map.keys) {
+              ExecutableElement value = map[memberName];
+              ClassElement definingClass = value
+                  .getAncestor((Element element) => element is ClassElement);
+              if (!definingClass.type.isObject) {
+                ExecutableElement existingValue = resultMap[memberName];
+                if (existingValue == null ||
+                    (existingValue != null && !_isAbstract(value))) {
+                  resultMap[memberName] = value;
+                }
+              }
+            }
+          } finally {
+            visitedClasses.remove(mixinElement);
+          }
+        } else {
+          // This case happens only when the superclass was previously visited
+          // and not in the lookup, meaning this is meant to shorten the compute
+          // for recursive cases.
+          _classLookup[mixinElement] = resultMap;
+          return resultMap;
+        }
+      }
+    }
+    _classLookup[classElt] = resultMap;
+    return resultMap;
+  }
+
+  /**
+   * Compute and return the inheritance path given the context of a type and a member that is
+   * overridden in the inheritance path (for which the type is in the path).
+   *
+   * @param chain the inheritance path that is built up as this method calls itself recursively,
+   *          when this method is called an empty [LinkedList] should be provided
+   * @param currentType the current type in the inheritance path
+   * @param memberName the name of the member that is being looked up the inheritance path
+   */
+  void _computeInheritancePath(Queue<InterfaceType> chain,
+      InterfaceType currentType, String memberName) {
+    // TODO (jwren) create a public version of this method which doesn't require
+    // the initial chain to be provided, then provided tests for this
+    // functionality in InheritanceManagerTest
+    chain.add(currentType);
+    ClassElement classElt = currentType.element;
+    InterfaceType supertype = classElt.supertype;
+    // Base case- reached Object
+    if (supertype == null) {
+      // Looked up the chain all the way to Object, return null.
+      // This should never happen.
+      return;
+    }
+    // If we are done, return the chain
+    // We are not done if this is the first recursive call on this method.
+    if (chain.length != 1) {
+      // We are done however if the member is in this classElt
+      if (_lookupMemberInClass(classElt, memberName) != null) {
+        return;
+      }
+    }
+    // Mixins- note that mixins call lookupMemberInClass, not lookupMember
+    List<InterfaceType> mixins = classElt.mixins;
+    for (int i = mixins.length - 1; i >= 0; i--) {
+      ClassElement mixinElement = mixins[i].element;
+      if (mixinElement != null) {
+        ExecutableElement elt = _lookupMemberInClass(mixinElement, memberName);
+        if (elt != null) {
+          // this is equivalent (but faster than) calling this method
+          // recursively
+          // (return computeInheritancePath(chain, mixins[i], memberName);)
+          chain.add(mixins[i]);
+          return;
+        }
+      }
+    }
+    // Superclass
+    ClassElement superclassElt = supertype.element;
+    if (lookupMember(superclassElt, memberName) != null) {
+      _computeInheritancePath(chain, supertype, memberName);
+      return;
+    }
+    // Interfaces
+    List<InterfaceType> interfaces = classElt.interfaces;
+    for (InterfaceType interfaceType in interfaces) {
+      ClassElement interfaceElement = interfaceType.element;
+      if (interfaceElement != null &&
+          lookupMember(interfaceElement, memberName) != null) {
+        _computeInheritancePath(chain, interfaceType, memberName);
+        return;
+      }
+    }
+  }
+
+  /**
+   * Compute and return a mapping between the set of all string names of the members inherited from
+   * the passed [ClassElement] interface hierarchy, and the associated
+   * [ExecutableElement].
+   *
+   * @param classElt the class element to query
+   * @param visitedInterfaces a set of visited classes passed back into this method when it calls
+   *          itself recursively
+   * @return a mapping between the set of all string names of the members inherited from the passed
+   *         [ClassElement] interface hierarchy, and the associated [ExecutableElement]
+   */
+  Map<String, ExecutableElement> _computeInterfaceLookupMap(
+      ClassElement classElt, HashSet<ClassElement> visitedInterfaces) {
+    Map<String, ExecutableElement> resultMap = _interfaceLookup[classElt];
+    if (resultMap != null) {
+      return resultMap;
+    }
+    List<Map<String, ExecutableElement>> lookupMaps =
+        _gatherInterfaceLookupMaps(classElt, visitedInterfaces);
+    if (lookupMaps == null) {
+      resultMap = new Map<String, ExecutableElement>();
+    } else {
+      HashMap<String, List<ExecutableElement>> unionMap =
+          _unionInterfaceLookupMaps(lookupMaps);
+      resultMap = _resolveInheritanceLookup(classElt, unionMap);
+    }
+    _interfaceLookup[classElt] = resultMap;
+    return resultMap;
+  }
+
+  /**
+   * Collect a list of interface lookup maps whose elements correspond to all of the classes
+   * directly above [classElt] in the class hierarchy (the direct superclass if any, all
+   * mixins, and all direct superinterfaces). Each item in the list is the interface lookup map
+   * returned by [computeInterfaceLookupMap] for the corresponding super, except with type
+   * parameters appropriately substituted.
+   *
+   * @param classElt the class element to query
+   * @param visitedInterfaces a set of visited classes passed back into this method when it calls
+   *          itself recursively
+   * @return `null` if there was a problem (such as a loop in the class hierarchy) or if there
+   *         are no classes above this one in the class hierarchy. Otherwise, a list of interface
+   *         lookup maps.
+   */
+  List<Map<String, ExecutableElement>> _gatherInterfaceLookupMaps(
+      ClassElement classElt, HashSet<ClassElement> visitedInterfaces) {
+    InterfaceType supertype = classElt.supertype;
+    ClassElement superclassElement =
+        supertype != null ? supertype.element : null;
+    List<InterfaceType> mixins = classElt.mixins;
+    List<InterfaceType> interfaces = classElt.interfaces;
+    // Recursively collect the list of mappings from all of the interface types
+    List<Map<String, ExecutableElement>> lookupMaps =
+        new List<Map<String, ExecutableElement>>();
+    //
+    // Superclass element
+    //
+    if (superclassElement != null) {
+      if (!visitedInterfaces.contains(superclassElement)) {
+        try {
+          visitedInterfaces.add(superclassElement);
+          //
+          // Recursively compute the map for the super type.
+          //
+          Map<String, ExecutableElement> map =
+              _computeInterfaceLookupMap(superclassElement, visitedInterfaces);
+          map = new Map<String, ExecutableElement>.from(map);
+          //
+          // Substitute the super type down the hierarchy.
+          //
+          _substituteTypeParametersDownHierarchy(supertype, map);
+          //
+          // Add any members from the super type into the map as well.
+          //
+          _recordMapWithClassMembers(map, supertype, true);
+          lookupMaps.add(map);
+        } finally {
+          visitedInterfaces.remove(superclassElement);
+        }
+      } else {
+        return null;
+      }
+    }
+    //
+    // Mixin elements
+    //
+    for (int i = mixins.length - 1; i >= 0; i--) {
+      InterfaceType mixinType = mixins[i];
+      ClassElement mixinElement = mixinType.element;
+      if (mixinElement != null) {
+        if (!visitedInterfaces.contains(mixinElement)) {
+          try {
+            visitedInterfaces.add(mixinElement);
+            //
+            // Recursively compute the map for the mixin.
+            //
+            Map<String, ExecutableElement> map =
+                _computeInterfaceLookupMap(mixinElement, visitedInterfaces);
+            map = new Map<String, ExecutableElement>.from(map);
+            //
+            // Substitute the mixin type down the hierarchy.
+            //
+            _substituteTypeParametersDownHierarchy(mixinType, map);
+            //
+            // Add any members from the mixin type into the map as well.
+            //
+            _recordMapWithClassMembers(map, mixinType, true);
+            lookupMaps.add(map);
+          } finally {
+            visitedInterfaces.remove(mixinElement);
+          }
+        } else {
+          return null;
+        }
+      }
+    }
+    //
+    // Interface elements
+    //
+    for (InterfaceType interfaceType in interfaces) {
+      ClassElement interfaceElement = interfaceType.element;
+      if (interfaceElement != null) {
+        if (!visitedInterfaces.contains(interfaceElement)) {
+          try {
+            visitedInterfaces.add(interfaceElement);
+            //
+            // Recursively compute the map for the interfaces.
+            //
+            Map<String, ExecutableElement> map =
+                _computeInterfaceLookupMap(interfaceElement, visitedInterfaces);
+            map = new Map<String, ExecutableElement>.from(map);
+            //
+            // Substitute the supertypes down the hierarchy
+            //
+            _substituteTypeParametersDownHierarchy(interfaceType, map);
+            //
+            // And add any members from the interface into the map as well.
+            //
+            _recordMapWithClassMembers(map, interfaceType, true);
+            lookupMaps.add(map);
+          } finally {
+            visitedInterfaces.remove(interfaceElement);
+          }
+        } else {
+          return null;
+        }
+      }
+    }
+    if (lookupMaps.length == 0) {
+      return null;
+    }
+    return lookupMaps;
+  }
+
+  /**
+   * Given some [ClassElement], this method finds and returns the [ExecutableElement] of
+   * the passed name in the class element. Static members, members in super types and members not
+   * accessible from the current library are not considered.
+   *
+   * @param classElt the class element to query
+   * @param memberName the name of the member to lookup in the class
+   * @return the found [ExecutableElement], or `null` if no such member was found
+   */
+  ExecutableElement _lookupMemberInClass(
+      ClassElement classElt, String memberName) {
+    List<MethodElement> methods = classElt.methods;
+    for (MethodElement method in methods) {
+      if (memberName == method.name &&
+          method.isAccessibleIn(_library) &&
+          !method.isStatic) {
+        return method;
+      }
+    }
+    List<PropertyAccessorElement> accessors = classElt.accessors;
+    for (PropertyAccessorElement accessor in accessors) {
+      if (memberName == accessor.name &&
+          accessor.isAccessibleIn(_library) &&
+          !accessor.isStatic) {
+        return accessor;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Record the passed map with the set of all members (methods, getters and setters) in the type
+   * into the passed map.
+   *
+   * @param map some non-`null` map to put the methods and accessors from the passed
+   *          [ClassElement] into
+   * @param type the type that will be recorded into the passed map
+   * @param doIncludeAbstract `true` if abstract members will be put into the map
+   */
+  void _recordMapWithClassMembers(Map<String, ExecutableElement> map,
+      InterfaceType type, bool doIncludeAbstract) {
+    List<MethodElement> methods = type.methods;
+    for (MethodElement method in methods) {
+      if (method.isAccessibleIn(_library) &&
+          !method.isStatic &&
+          (doIncludeAbstract || !method.isAbstract)) {
+        map[method.name] = method;
+      }
+    }
+    List<PropertyAccessorElement> accessors = type.accessors;
+    for (PropertyAccessorElement accessor in accessors) {
+      if (accessor.isAccessibleIn(_library) &&
+          !accessor.isStatic &&
+          (doIncludeAbstract || !accessor.isAbstract)) {
+        map[accessor.name] = accessor;
+      }
+    }
+  }
+
+  /**
+   * This method is used to report errors on when they are found computing inheritance information.
+   * See [ErrorVerifier.checkForInconsistentMethodInheritance] to see where these generated
+   * error codes are reported back into the analysis engine.
+   *
+   * @param classElt the location of the source for which the exception occurred
+   * @param offset the offset of the location of the error
+   * @param length the length of the location of the error
+   * @param errorCode the error code to be associated with this error
+   * @param arguments the arguments used to build the error message
+   */
+  void _reportError(ClassElement classElt, int offset, int length,
+      ErrorCode errorCode, List<Object> arguments) {
+    HashSet<AnalysisError> errorSet = _errorsInClassElement[classElt];
+    if (errorSet == null) {
+      errorSet = new HashSet<AnalysisError>();
+      _errorsInClassElement[classElt] = errorSet;
+    }
+    errorSet.add(new AnalysisError(
+        classElt.source, offset, length, errorCode, arguments));
+  }
+
+  /**
+   * Given the set of methods defined by classes above [classElt] in the class hierarchy,
+   * apply the appropriate inheritance rules to determine those methods inherited by or overridden
+   * by [classElt]. Also report static warnings
+   * [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE] and
+   * [StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD] if appropriate.
+   *
+   * @param classElt the class element to query.
+   * @param unionMap a mapping from method name to the set of unique (in terms of signature) methods
+   *          defined in superclasses of [classElt].
+   * @return the inheritance lookup map for [classElt].
+   */
+  Map<String, ExecutableElement> _resolveInheritanceLookup(
+      ClassElement classElt, Map<String, List<ExecutableElement>> unionMap) {
+    Map<String, ExecutableElement> resultMap =
+        new Map<String, ExecutableElement>();
+    unionMap.forEach((String key, List<ExecutableElement> list) {
+      int numOfEltsWithMatchingNames = list.length;
+      if (numOfEltsWithMatchingNames == 1) {
+        //
+        // Example: class A inherits only 1 method named 'm'.
+        // Since it is the only such method, it is inherited.
+        // Another example: class A inherits 2 methods named 'm' from 2
+        // different interfaces, but they both have the same signature, so it is
+        // the method inherited.
+        //
+        resultMap[key] = list[0];
+      } else {
+        //
+        // Then numOfEltsWithMatchingNames > 1, check for the warning cases.
+        //
+        bool allMethods = true;
+        bool allSetters = true;
+        bool allGetters = true;
+        for (ExecutableElement executableElement in list) {
+          if (executableElement is PropertyAccessorElement) {
+            allMethods = false;
+            if (executableElement.isSetter) {
+              allGetters = false;
+            } else {
+              allSetters = false;
+            }
+          } else {
+            allGetters = false;
+            allSetters = false;
+          }
+        }
+        //
+        // If there isn't a mixture of methods with getters, then continue,
+        // otherwise create a warning.
+        //
+        if (allMethods || allGetters || allSetters) {
+          //
+          // Compute the element whose type is the subtype of all of the other
+          // types.
+          //
+          List<ExecutableElement> elements = new List.from(list);
+          List<FunctionType> executableElementTypes =
+              new List<FunctionType>(numOfEltsWithMatchingNames);
+          for (int i = 0; i < numOfEltsWithMatchingNames; i++) {
+            executableElementTypes[i] = elements[i].type;
+          }
+          List<int> subtypesOfAllOtherTypesIndexes = new List<int>();
+          for (int i = 0; i < numOfEltsWithMatchingNames; i++) {
+            FunctionType subtype = executableElementTypes[i];
+            if (subtype == null) {
+              continue;
+            }
+            bool subtypeOfAllTypes = true;
+            TypeSystem typeSystem = _library.context.typeSystem;
+            for (int j = 0;
+                j < numOfEltsWithMatchingNames && subtypeOfAllTypes;
+                j++) {
+              if (i != j) {
+                if (!typeSystem.isSubtypeOf(
+                    subtype, executableElementTypes[j])) {
+                  subtypeOfAllTypes = false;
+                  break;
+                }
+              }
+            }
+            if (subtypeOfAllTypes) {
+              subtypesOfAllOtherTypesIndexes.add(i);
+            }
+          }
+          //
+          // The following is split into three cases determined by the number of
+          // elements in subtypesOfAllOtherTypes
+          //
+          if (subtypesOfAllOtherTypesIndexes.length == 1) {
+            //
+            // Example: class A inherited only 2 method named 'm'.
+            // One has the function type '() -> dynamic' and one has the
+            // function type '([int]) -> dynamic'. Since the second method is a
+            // subtype of all the others, it is the inherited method.
+            // Tests: InheritanceManagerTest.
+            // test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_*
+            //
+            resultMap[key] = elements[subtypesOfAllOtherTypesIndexes[0]];
+          } else {
+            if (subtypesOfAllOtherTypesIndexes.isEmpty) {
+              //
+              // Determine if the current class has a method or accessor with
+              // the member name, if it does then then this class does not
+              // "inherit" from any of the supertypes. See issue 16134.
+              //
+              bool classHasMember = false;
+              if (allMethods) {
+                classHasMember = classElt.getMethod(key) != null;
+              } else {
+                List<PropertyAccessorElement> accessors = classElt.accessors;
+                for (int i = 0; i < accessors.length; i++) {
+                  if (accessors[i].name == key) {
+                    classHasMember = true;
+                  }
+                }
+              }
+              //
+              // Example: class A inherited only 2 method named 'm'.
+              // One has the function type '() -> int' and one has the function
+              // type '() -> String'. Since neither is a subtype of the other,
+              // we create a warning, and have this class inherit nothing.
+              //
+              if (!classHasMember) {
+                String firstTwoFuntionTypesStr =
+                    "${executableElementTypes[0]}, ${executableElementTypes[1]}";
+                _reportError(
+                    classElt,
+                    classElt.nameOffset,
+                    classElt.nameLength,
+                    StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE,
+                    [key, firstTwoFuntionTypesStr]);
+              }
+            } else {
+              //
+              // Example: class A inherits 2 methods named 'm'.
+              // One has the function type '(int) -> dynamic' and one has the
+              // function type '(num) -> dynamic'. Since they are both a subtype
+              // of the other, a synthetic function '(dynamic) -> dynamic' is
+              // inherited.
+              // Tests: test_getMapOfMembersInheritedFromInterfaces_
+              // union_multipleSubtypes_*
+              //
+              List<ExecutableElement> elementArrayToMerge =
+                  new List<ExecutableElement>(
+                      subtypesOfAllOtherTypesIndexes.length);
+              for (int i = 0; i < elementArrayToMerge.length; i++) {
+                elementArrayToMerge[i] =
+                    elements[subtypesOfAllOtherTypesIndexes[i]];
+              }
+              ExecutableElement mergedExecutableElement =
+                  _computeMergedExecutableElement(elementArrayToMerge);
+              resultMap[key] = mergedExecutableElement;
+            }
+          }
+        } else {
+          _reportError(
+              classElt,
+              classElt.nameOffset,
+              classElt.nameLength,
+              StaticWarningCode
+                  .INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD,
+              [key]);
+        }
+      }
+    });
+    return resultMap;
+  }
+
+  /**
+   * Loop through all of the members in the given [map], performing type
+   * parameter  substitutions using a passed [supertype].
+   */
+  void _substituteTypeParametersDownHierarchy(
+      InterfaceType superType, Map<String, ExecutableElement> map) {
+    for (String memberName in map.keys) {
+      ExecutableElement executableElement = map[memberName];
+      if (executableElement is MethodMember) {
+        map[memberName] = MethodMember.from(executableElement, superType);
+      } else if (executableElement is PropertyAccessorMember) {
+        map[memberName] =
+            PropertyAccessorMember.from(executableElement, superType);
+      }
+    }
+  }
+
+  /**
+   * Union all of the [lookupMaps] together into a single map, grouping the ExecutableElements
+   * into a list where none of the elements are equal where equality is determined by having equal
+   * function types. (We also take note too of the kind of the element: ()->int and () -> int may
+   * not be equal if one is a getter and the other is a method.)
+   *
+   * @param lookupMaps the maps to be unioned together.
+   * @return the resulting union map.
+   */
+  HashMap<String, List<ExecutableElement>> _unionInterfaceLookupMaps(
+      List<Map<String, ExecutableElement>> lookupMaps) {
+    HashMap<String, List<ExecutableElement>> unionMap =
+        new HashMap<String, List<ExecutableElement>>();
+    for (Map<String, ExecutableElement> lookupMap in lookupMaps) {
+      for (String memberName in lookupMap.keys) {
+        // Get the list value out of the unionMap
+        List<ExecutableElement> list = unionMap[memberName];
+        // If we haven't created such a map for this key yet, do create it and
+        // put the list entry into the unionMap.
+        if (list == null) {
+          list = new List<ExecutableElement>();
+          unionMap[memberName] = list;
+        }
+        // Fetch the entry out of this lookupMap
+        ExecutableElement newExecutableElementEntry = lookupMap[memberName];
+        if (list.isEmpty) {
+          // If the list is empty, just the new value
+          list.add(newExecutableElementEntry);
+        } else {
+          // Otherwise, only add the newExecutableElementEntry if it isn't
+          // already in the list, this covers situation where a class inherits
+          // two methods (or two getters) that are identical.
+          bool alreadyInList = false;
+          bool isMethod1 = newExecutableElementEntry is MethodElement;
+          for (ExecutableElement executableElementInList in list) {
+            bool isMethod2 = executableElementInList is MethodElement;
+            if (isMethod1 == isMethod2 &&
+                executableElementInList.type ==
+                    newExecutableElementEntry.type) {
+              alreadyInList = true;
+              break;
+            }
+          }
+          if (!alreadyInList) {
+            list.add(newExecutableElementEntry);
+          }
+        }
+      }
+    }
+    return unionMap;
+  }
+
+  /**
+   * Given some array of [ExecutableElement]s, this method creates a synthetic element as
+   * described in 8.1.1:
+   *
+   * Let <i>numberOfPositionals</i>(<i>f</i>) denote the number of positional parameters of a
+   * function <i>f</i>, and let <i>numberOfRequiredParams</i>(<i>f</i>) denote the number of
+   * required parameters of a function <i>f</i>. Furthermore, let <i>s</i> denote the set of all
+   * named parameters of the <i>m<sub>1</sub>, &hellip;, m<sub>k</sub></i>. Then let
+   * * <i>h = max(numberOfPositionals(m<sub>i</sub>)),</i>
+   * * <i>r = min(numberOfRequiredParams(m<sub>i</sub>)), for all <i>i</i>, 1 <= i <= k.</i>
+   * Then <i>I</i> has a method named <i>n</i>, with <i>r</i> required parameters of type
+   * <b>dynamic</b>, <i>h</i> positional parameters of type <b>dynamic</b>, named parameters
+   * <i>s</i> of type <b>dynamic</b> and return type <b>dynamic</b>.
+   *
+   */
+  static ExecutableElement _computeMergedExecutableElement(
+      List<ExecutableElement> elementArrayToMerge) {
+    int h = _getNumOfPositionalParameters(elementArrayToMerge[0]);
+    int r = _getNumOfRequiredParameters(elementArrayToMerge[0]);
+    Set<String> namedParametersList = new HashSet<String>();
+    for (int i = 1; i < elementArrayToMerge.length; i++) {
+      ExecutableElement element = elementArrayToMerge[i];
+      int numOfPositionalParams = _getNumOfPositionalParameters(element);
+      if (h < numOfPositionalParams) {
+        h = numOfPositionalParams;
+      }
+      int numOfRequiredParams = _getNumOfRequiredParameters(element);
+      if (r > numOfRequiredParams) {
+        r = numOfRequiredParams;
+      }
+      namedParametersList.addAll(_getNamedParameterNames(element));
+    }
+    return _createSyntheticExecutableElement(
+        elementArrayToMerge,
+        elementArrayToMerge[0].displayName,
+        r,
+        h - r,
+        new List.from(namedParametersList));
+  }
+
+  /**
+   * Used by [computeMergedExecutableElement] to actually create the
+   * synthetic element.
+   *
+   * @param elementArrayToMerge the array used to create the synthetic element
+   * @param name the name of the method, getter or setter
+   * @param numOfRequiredParameters the number of required parameters
+   * @param numOfPositionalParameters the number of positional parameters
+   * @param namedParameters the list of [String]s that are the named parameters
+   * @return the created synthetic element
+   */
+  static ExecutableElement _createSyntheticExecutableElement(
+      List<ExecutableElement> elementArrayToMerge,
+      String name,
+      int numOfRequiredParameters,
+      int numOfPositionalParameters,
+      List<String> namedParameters) {
+    DynamicTypeImpl dynamicType = DynamicTypeImpl.instance;
+    SimpleIdentifier nameIdentifier =
+        new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, name, 0));
+    ExecutableElementImpl executable;
+    ExecutableElement elementToMerge = elementArrayToMerge[0];
+    if (elementToMerge is MethodElement) {
+      MultiplyInheritedMethodElementImpl unionedMethod =
+          new MultiplyInheritedMethodElementImpl(nameIdentifier);
+      unionedMethod.inheritedElements = elementArrayToMerge;
+      executable = unionedMethod;
+    } else if (elementToMerge is PropertyAccessorElement) {
+      MultiplyInheritedPropertyAccessorElementImpl unionedPropertyAccessor =
+          new MultiplyInheritedPropertyAccessorElementImpl(nameIdentifier);
+      unionedPropertyAccessor.getter = elementToMerge.isGetter;
+      unionedPropertyAccessor.setter = elementToMerge.isSetter;
+      unionedPropertyAccessor.inheritedElements = elementArrayToMerge;
+      executable = unionedPropertyAccessor;
+    } else {
+      throw new AnalysisException(
+          'Invalid class of element in merge: ${elementToMerge.runtimeType}');
+    }
+    int numOfParameters = numOfRequiredParameters +
+        numOfPositionalParameters +
+        namedParameters.length;
+    List<ParameterElement> parameters =
+        new List<ParameterElement>(numOfParameters);
+    int i = 0;
+    for (int j = 0; j < numOfRequiredParameters; j++, i++) {
+      ParameterElementImpl parameter = new ParameterElementImpl("", 0);
+      parameter.type = dynamicType;
+      parameter.parameterKind = ParameterKind.REQUIRED;
+      parameters[i] = parameter;
+    }
+    for (int k = 0; k < numOfPositionalParameters; k++, i++) {
+      ParameterElementImpl parameter = new ParameterElementImpl("", 0);
+      parameter.type = dynamicType;
+      parameter.parameterKind = ParameterKind.POSITIONAL;
+      parameters[i] = parameter;
+    }
+    for (int m = 0; m < namedParameters.length; m++, i++) {
+      ParameterElementImpl parameter =
+          new ParameterElementImpl(namedParameters[m], 0);
+      parameter.type = dynamicType;
+      parameter.parameterKind = ParameterKind.NAMED;
+      parameters[i] = parameter;
+    }
+    executable.returnType = dynamicType;
+    executable.parameters = parameters;
+    FunctionTypeImpl methodType = new FunctionTypeImpl(executable);
+    executable.type = methodType;
+    return executable;
+  }
+
+  /**
+   * Given some [ExecutableElement], return the list of named parameters.
+   */
+  static List<String> _getNamedParameterNames(
+      ExecutableElement executableElement) {
+    List<String> namedParameterNames = new List<String>();
+    List<ParameterElement> parameters = executableElement.parameters;
+    for (int i = 0; i < parameters.length; i++) {
+      ParameterElement parameterElement = parameters[i];
+      if (parameterElement.parameterKind == ParameterKind.NAMED) {
+        namedParameterNames.add(parameterElement.name);
+      }
+    }
+    return namedParameterNames;
+  }
+
+  /**
+   * Given some [ExecutableElement] return the number of parameters of the specified kind.
+   */
+  static int _getNumOfParameters(
+      ExecutableElement executableElement, ParameterKind parameterKind) {
+    int parameterCount = 0;
+    List<ParameterElement> parameters = executableElement.parameters;
+    for (int i = 0; i < parameters.length; i++) {
+      ParameterElement parameterElement = parameters[i];
+      if (parameterElement.parameterKind == parameterKind) {
+        parameterCount++;
+      }
+    }
+    return parameterCount;
+  }
+
+  /**
+   * Given some [ExecutableElement] return the number of positional parameters.
+   *
+   * Note: by positional we mean [ParameterKind.REQUIRED] or [ParameterKind.POSITIONAL].
+   */
+  static int _getNumOfPositionalParameters(
+          ExecutableElement executableElement) =>
+      _getNumOfParameters(executableElement, ParameterKind.REQUIRED) +
+      _getNumOfParameters(executableElement, ParameterKind.POSITIONAL);
+
+  /**
+   * Given some [ExecutableElement] return the number of required parameters.
+   */
+  static int _getNumOfRequiredParameters(ExecutableElement executableElement) =>
+      _getNumOfParameters(executableElement, ParameterKind.REQUIRED);
+
+  /**
+   * Given some [ExecutableElement] returns `true` if it is an abstract member of a
+   * class.
+   *
+   * @param executableElement some [ExecutableElement] to evaluate
+   * @return `true` if the given element is an abstract member of a class
+   */
+  static bool _isAbstract(ExecutableElement executableElement) {
+    if (executableElement is MethodElement) {
+      return executableElement.isAbstract;
+    } else if (executableElement is PropertyAccessorElement) {
+      return executableElement.isAbstract;
+    }
+    return false;
+  }
+}
+
+/**
+ * This class is used to replace uses of `HashMap<String, ExecutableElement>`
+ * which are not as performant as this class.
+ */
+@deprecated
+class MemberMap {
+  /**
+   * The current size of this map.
+   */
+  int _size = 0;
+
+  /**
+   * The array of keys.
+   */
+  List<String> _keys;
+
+  /**
+   * The array of ExecutableElement values.
+   */
+  List<ExecutableElement> _values;
+
+  /**
+   * Initialize a newly created member map to have the given [initialCapacity].
+   * The map will grow if needed.
+   */
+  MemberMap([int initialCapacity = 10]) {
+    _initArrays(initialCapacity);
+  }
+
+  /**
+   * Initialize a newly created member map to contain the same members as the
+   * given [memberMap].
+   */
+  MemberMap.from(MemberMap memberMap) {
+    _initArrays(memberMap._size + 5);
+    for (int i = 0; i < memberMap._size; i++) {
+      _keys[i] = memberMap._keys[i];
+      _values[i] = memberMap._values[i];
+    }
+    _size = memberMap._size;
+  }
+
+  /**
+   * Initialize a newly created member map to contain the same members as the
+   * given [map].
+   */
+  MemberMap.fromMap(Map<String, ExecutableElement> map) {
+    _size = map.length;
+    _initArrays(_size + 5);
+    int index = 0;
+    map.forEach((String memberName, ExecutableElement element) {
+      _keys[index] = memberName;
+      _values[index] = element;
+      index++;
+    });
+  }
+
+  /**
+   * The size of the map.
+   *
+   * @return the size of the map.
+   */
+  int get size => _size;
+
+  /**
+   * Given some key, return the ExecutableElement value from the map, if the key does not exist in
+   * the map, `null` is returned.
+   *
+   * @param key some key to look up in the map
+   * @return the associated ExecutableElement value from the map, if the key does not exist in the
+   *         map, `null` is returned
+   */
+  ExecutableElement get(String key) {
+    for (int i = 0; i < _size; i++) {
+      if (_keys[i] != null && _keys[i] == key) {
+        return _values[i];
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Get and return the key at the specified location. If the key/value pair has been removed from
+   * the set, then `null` is returned.
+   *
+   * @param i some non-zero value less than size
+   * @return the key at the passed index
+   * @throw ArrayIndexOutOfBoundsException this exception is thrown if the passed index is less than
+   *        zero or greater than or equal to the capacity of the arrays
+   */
+  String getKey(int i) => _keys[i];
+
+  /**
+   * Get and return the ExecutableElement at the specified location. If the key/value pair has been
+   * removed from the set, then then `null` is returned.
+   *
+   * @param i some non-zero value less than size
+   * @return the key at the passed index
+   * @throw ArrayIndexOutOfBoundsException this exception is thrown if the passed index is less than
+   *        zero or greater than or equal to the capacity of the arrays
+   */
+  ExecutableElement getValue(int i) => _values[i];
+
+  /**
+   * Given some key/value pair, store the pair in the map. If the key exists already, then the new
+   * value overrides the old value.
+   *
+   * @param key the key to store in the map
+   * @param value the ExecutableElement value to store in the map
+   */
+  void put(String key, ExecutableElement value) {
+    // If we already have a value with this key, override the value
+    for (int i = 0; i < _size; i++) {
+      if (_keys[i] != null && _keys[i] == key) {
+        _values[i] = value;
+        return;
+      }
+    }
+    // If needed, double the size of our arrays and copy values over in both
+    // arrays
+    if (_size == _keys.length) {
+      int newArrayLength = _size * 2;
+      List<String> keys_new_array = new List<String>(newArrayLength);
+      List<ExecutableElement> values_new_array =
+          new List<ExecutableElement>(newArrayLength);
+      for (int i = 0; i < _size; i++) {
+        keys_new_array[i] = _keys[i];
+      }
+      for (int i = 0; i < _size; i++) {
+        values_new_array[i] = _values[i];
+      }
+      _keys = keys_new_array;
+      _values = values_new_array;
+    }
+    // Put new value at end of array
+    _keys[_size] = key;
+    _values[_size] = value;
+    _size++;
+  }
+
+  /**
+   * Given some [String] key, this method replaces the associated key and value pair with
+   * `null`. The size is not decremented with this call, instead it is expected that the users
+   * check for `null`.
+   *
+   * @param key the key of the key/value pair to remove from the map
+   */
+  void remove(String key) {
+    for (int i = 0; i < _size; i++) {
+      if (_keys[i] == key) {
+        _keys[i] = null;
+        _values[i] = null;
+        return;
+      }
+    }
+  }
+
+  /**
+   * Sets the ExecutableElement at the specified location.
+   *
+   * @param i some non-zero value less than size
+   * @param value the ExecutableElement value to store in the map
+   */
+  void setValue(int i, ExecutableElement value) {
+    _values[i] = value;
+  }
+
+  /**
+   * Initializes [keys] and [values].
+   */
+  void _initArrays(int initialCapacity) {
+    _keys = new List<String>(initialCapacity);
+    _values = new List<ExecutableElement>(initialCapacity);
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart
new file mode 100644
index 0000000..54086d9
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -0,0 +1,1059 @@
+// 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.resolver.scope;
+
+import 'dart:collection';
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/element.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/java_engine.dart';
+import 'package:analyzer/src/generated/source.dart';
+
+/**
+ * The scope defined by a class.
+ */
+class ClassScope extends EnclosedScope {
+  /**
+   * Initialize a newly created scope, enclosed within the [enclosingScope],
+   * based on the given [classElement].
+   */
+  ClassScope(Scope enclosingScope, ClassElement classElement)
+      : super(enclosingScope) {
+    if (classElement == null) {
+      throw new IllegalArgumentException("class element cannot be null");
+    }
+    _defineMembers(classElement);
+  }
+
+  @override
+  AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
+    if (existing is PropertyAccessorElement && duplicate is MethodElement) {
+      if (existing.nameOffset < duplicate.nameOffset) {
+        return new AnalysisError(
+            duplicate.source,
+            duplicate.nameOffset,
+            duplicate.nameLength,
+            CompileTimeErrorCode.METHOD_AND_GETTER_WITH_SAME_NAME,
+            [existing.displayName]);
+      } else {
+        return new AnalysisError(
+            existing.source,
+            existing.nameOffset,
+            existing.nameLength,
+            CompileTimeErrorCode.GETTER_AND_METHOD_WITH_SAME_NAME,
+            [existing.displayName]);
+      }
+    }
+    return super.getErrorForDuplicate(existing, duplicate);
+  }
+
+  /**
+   * Define the instance members defined by the given [classElement].
+   */
+  void _defineMembers(ClassElement classElement) {
+    for (PropertyAccessorElement accessor in classElement.accessors) {
+      define(accessor);
+    }
+    for (MethodElement method in classElement.methods) {
+      define(method);
+    }
+  }
+}
+
+/**
+ * A scope that is lexically enclosed in another scope.
+ */
+class EnclosedScope extends Scope {
+  /**
+   * The scope in which this scope is lexically enclosed.
+   */
+  @override
+  final Scope enclosingScope;
+
+  /**
+   * A table mapping names that will be defined in this scope, but right now are
+   * not initialized. According to the scoping rules these names are hidden,
+   * even if they were defined in an outer scope.
+   */
+  HashMap<String, Element> _hiddenElements = null;
+
+  /**
+   * Initialize a newly created scope, enclosed within the [enclosingScope].
+   */
+  EnclosedScope(this.enclosingScope);
+
+  @override
+  AnalysisErrorListener get errorListener => enclosingScope.errorListener;
+
+  /**
+   * Record that given [element] is declared in this scope, but hasn't been
+   * initialized yet, so it is error to use. If there is already an element with
+   * the given name defined in an outer scope, then it will become unavailable.
+   */
+  void hide(Element element) {
+    if (element != null) {
+      String name = element.name;
+      if (name != null && !name.isEmpty) {
+        _hiddenElements ??= new HashMap<String, Element>();
+        _hiddenElements[name] = element;
+      }
+    }
+  }
+
+  @override
+  Element internalLookup(
+      Identifier identifier, String name, LibraryElement referencingLibrary) {
+    Element element = localLookup(name, referencingLibrary);
+    if (element != null) {
+      return element;
+    }
+    // May be there is a hidden Element.
+    if (_hiddenElements != null) {
+      Element hiddenElement = _hiddenElements[name];
+      if (hiddenElement != null) {
+        errorListener.onError(new AnalysisError(
+            getSource(identifier),
+            identifier.offset,
+            identifier.length,
+            CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, []));
+        return hiddenElement;
+      }
+    }
+    // Check enclosing scope.
+    return enclosingScope.internalLookup(identifier, name, referencingLibrary);
+  }
+}
+
+/**
+ * The scope defined by a function.
+ */
+class FunctionScope extends EnclosedScope {
+  /**
+   * The element representing the function that defines this scope.
+   */
+  final ExecutableElement _functionElement;
+
+  /**
+   * A flag indicating whether the parameters have already been defined, used to
+   * prevent the parameters from being defined multiple times.
+   */
+  bool _parametersDefined = false;
+
+  /**
+   * Initialize a newly created scope, enclosed within the [enclosingScope],
+   * that represents the given [_functionElement].
+   */
+  FunctionScope(Scope enclosingScope, this._functionElement)
+      : super(new EnclosedScope(new EnclosedScope(enclosingScope))) {
+    if (_functionElement == null) {
+      throw new IllegalArgumentException("function element cannot be null");
+    }
+    _defineTypeParameters();
+  }
+
+  /**
+   * Define the parameters for the given function in the scope that encloses
+   * this function.
+   */
+  void defineParameters() {
+    if (_parametersDefined) {
+      return;
+    }
+    _parametersDefined = true;
+    Scope parameterScope = enclosingScope;
+    for (ParameterElement parameter in _functionElement.parameters) {
+      if (!parameter.isInitializingFormal) {
+        parameterScope.define(parameter);
+      }
+    }
+  }
+
+  /**
+   * Define the type parameters for the function.
+   */
+  void _defineTypeParameters() {
+    Scope typeParameterScope = enclosingScope.enclosingScope;
+    for (TypeParameterElement typeParameter
+        in _functionElement.typeParameters) {
+      typeParameterScope.define(typeParameter);
+    }
+  }
+}
+
+/**
+ * The scope defined by a function type alias.
+ */
+class FunctionTypeScope extends EnclosedScope {
+  final FunctionTypeAliasElement _typeElement;
+
+  bool _parametersDefined = false;
+
+  /**
+   * Initialize a newly created scope, enclosed within the [enclosingScope],
+   * that represents the given [_typeElement].
+   */
+  FunctionTypeScope(Scope enclosingScope, this._typeElement)
+      : super(new EnclosedScope(enclosingScope)) {
+    _defineTypeParameters();
+  }
+
+  /**
+   * Define the parameters for the function type alias.
+   */
+  void defineParameters() {
+    if (_parametersDefined) {
+      return;
+    }
+    _parametersDefined = true;
+    for (ParameterElement parameter in _typeElement.parameters) {
+      define(parameter);
+    }
+  }
+
+  /**
+   * Define the type parameters for the function type alias.
+   */
+  void _defineTypeParameters() {
+    Scope typeParameterScope = enclosingScope;
+    for (TypeParameterElement typeParameter in _typeElement.typeParameters) {
+      typeParameterScope.define(typeParameter);
+    }
+  }
+}
+
+/**
+ * The scope statements that can be the target of unlabeled `break` and
+ * `continue` statements.
+ */
+class ImplicitLabelScope {
+  /**
+   * The implicit label scope associated with the top level of a function.
+   */
+  static const ImplicitLabelScope ROOT = const ImplicitLabelScope._(null, null);
+
+  /**
+   * The implicit label scope enclosing this implicit label scope.
+   */
+  final ImplicitLabelScope outerScope;
+
+  /**
+   * The statement that acts as a target for break and/or continue statements
+   * at this scoping level.
+   */
+  final Statement statement;
+
+  /**
+   * Initialize a newly created scope, enclosed within the [outerScope],
+   * representing the given [statement].
+   */
+  const ImplicitLabelScope._(this.outerScope, this.statement);
+
+  /**
+   * Return the statement which should be the target of an unlabeled `break` or
+   * `continue` statement, or `null` if there is no appropriate target.
+   */
+  Statement getTarget(bool isContinue) {
+    if (outerScope == null) {
+      // This scope represents the toplevel of a function body, so it doesn't
+      // match either break or continue.
+      return null;
+    }
+    if (isContinue && statement is SwitchStatement) {
+      return outerScope.getTarget(isContinue);
+    }
+    return statement;
+  }
+
+  /**
+   * Initialize a newly created scope to represent a switch statement or loop
+   * nested within the current scope.  [statement] is the statement associated
+   * with the newly created scope.
+   */
+  ImplicitLabelScope nest(Statement statement) =>
+      new ImplicitLabelScope._(this, statement);
+}
+
+/**
+ * A scope in which a single label is defined.
+ */
+class LabelScope {
+  /**
+   * The label scope enclosing this label scope.
+   */
+  final LabelScope _outerScope;
+
+  /**
+   * The label defined in this scope.
+   */
+  final String _label;
+
+  /**
+   * The element to which the label resolves.
+   */
+  final LabelElement element;
+
+  /**
+   * The AST node to which the label resolves.
+   */
+  final AstNode node;
+
+  /**
+   * Initialize a newly created scope, enclosed within the [_outerScope],
+   * representing the label [_label]. The [node] is the AST node the label
+   * resolves to. The [element] is the element the label resolves to.
+   */
+  LabelScope(this._outerScope, this._label, this.node, this.element);
+
+  /**
+   * Return the LabelScope which defines [targetLabel], or `null` if it is not
+   * defined in this scope.
+   */
+  LabelScope lookup(String targetLabel) {
+    if (_label == targetLabel) {
+      return this;
+    } else if (_outerScope != null) {
+      return _outerScope.lookup(targetLabel);
+    } else {
+      return null;
+    }
+  }
+}
+
+/**
+ * The scope containing all of the names available from imported libraries.
+ */
+class LibraryImportScope extends Scope {
+  /**
+   * The element representing the library in which this scope is enclosed.
+   */
+  final LibraryElement _definingLibrary;
+
+  /**
+   * The listener that is to be informed when an error is encountered.
+   */
+  @override
+  final AnalysisErrorListener errorListener;
+
+  /**
+   * A list of the namespaces representing the names that are available in this scope from imported
+   * libraries.
+   */
+  List<Namespace> _importedNamespaces;
+
+  /**
+   * Initialize a newly created scope representing the names imported into the
+   * [_definingLibrary]. The [errorListener] is the listener that is to be
+   * informed when an error is encountered.
+   */
+  LibraryImportScope(this._definingLibrary, this.errorListener) {
+    _createImportedNamespaces();
+  }
+
+  @override
+  void define(Element element) {
+    if (!Scope.isPrivateName(element.displayName)) {
+      super.define(element);
+    }
+  }
+
+  @override
+  Source getSource(AstNode node) {
+    Source source = super.getSource(node);
+    if (source == null) {
+      source = _definingLibrary.definingCompilationUnit.source;
+    }
+    return source;
+  }
+
+  @override
+  Element internalLookup(
+      Identifier identifier, String name, LibraryElement referencingLibrary) {
+    Element foundElement = localLookup(name, referencingLibrary);
+    if (foundElement != null) {
+      return foundElement;
+    }
+    for (int i = 0; i < _importedNamespaces.length; i++) {
+      Namespace nameSpace = _importedNamespaces[i];
+      Element element = nameSpace.get(name);
+      if (element != null) {
+        if (foundElement == null) {
+          foundElement = element;
+        } else if (!identical(foundElement, element)) {
+          foundElement = MultiplyDefinedElementImpl.fromElements(
+              _definingLibrary.context, foundElement, element);
+        }
+      }
+    }
+    Element element = foundElement;
+    if (element is MultiplyDefinedElementImpl) {
+      foundElement = _removeSdkElements(identifier, name, element);
+    }
+    if (foundElement is MultiplyDefinedElementImpl) {
+      String foundEltName = foundElement.displayName;
+      List<Element> conflictingMembers = foundElement.conflictingElements;
+      int count = conflictingMembers.length;
+      List<String> libraryNames = new List<String>(count);
+      for (int i = 0; i < count; i++) {
+        libraryNames[i] = _getLibraryName(conflictingMembers[i]);
+      }
+      libraryNames.sort();
+      errorListener.onError(new AnalysisError(
+          getSource(identifier),
+          identifier.offset,
+          identifier.length,
+          StaticWarningCode.AMBIGUOUS_IMPORT, [
+        foundEltName,
+        StringUtilities.printListOfQuotedNames(libraryNames)
+      ]));
+      return foundElement;
+    }
+    if (foundElement != null) {
+      defineNameWithoutChecking(name, foundElement);
+    }
+    return foundElement;
+  }
+
+  /**
+   * Create all of the namespaces associated with the libraries imported into
+   * this library. The names are not added to this scope, but are stored for
+   * later reference.
+   */
+  void _createImportedNamespaces() {
+    NamespaceBuilder builder = new NamespaceBuilder();
+    List<ImportElement> imports = _definingLibrary.imports;
+    int count = imports.length;
+    _importedNamespaces = new List<Namespace>(count);
+    for (int i = 0; i < count; i++) {
+      _importedNamespaces[i] =
+          builder.createImportNamespaceForDirective(imports[i]);
+    }
+  }
+
+  /**
+   * Return the name of the library that defines given [element].
+   */
+  String _getLibraryName(Element element) {
+    if (element == null) {
+      return StringUtilities.EMPTY;
+    }
+    LibraryElement library = element.library;
+    if (library == null) {
+      return StringUtilities.EMPTY;
+    }
+    List<ImportElement> imports = _definingLibrary.imports;
+    int count = imports.length;
+    for (int i = 0; i < count; i++) {
+      if (identical(imports[i].importedLibrary, library)) {
+        return library.definingCompilationUnit.displayName;
+      }
+    }
+    List<String> indirectSources = new List<String>();
+    for (int i = 0; i < count; i++) {
+      LibraryElement importedLibrary = imports[i].importedLibrary;
+      if (importedLibrary != null) {
+        for (LibraryElement exportedLibrary
+            in importedLibrary.exportedLibraries) {
+          if (identical(exportedLibrary, library)) {
+            indirectSources
+                .add(importedLibrary.definingCompilationUnit.displayName);
+          }
+        }
+      }
+    }
+    int indirectCount = indirectSources.length;
+    StringBuffer buffer = new StringBuffer();
+    buffer.write(library.definingCompilationUnit.displayName);
+    if (indirectCount > 0) {
+      buffer.write(" (via ");
+      if (indirectCount > 1) {
+        indirectSources.sort();
+        buffer.write(StringUtilities.printListOfQuotedNames(indirectSources));
+      } else {
+        buffer.write(indirectSources[0]);
+      }
+      buffer.write(")");
+    }
+    return buffer.toString();
+  }
+
+  /**
+   * Given a collection of elements (captured by the [foundElement]) that the
+   * [identifier] (with the given [name]) resolved to, remove from the list all
+   * of the names defined in the SDK and return the element(s) that remain.
+   */
+  Element _removeSdkElements(Identifier identifier, String name,
+      MultiplyDefinedElementImpl foundElement) {
+    List<Element> conflictingElements = foundElement.conflictingElements;
+    List<Element> nonSdkElements = new List<Element>();
+    Element sdkElement = null;
+    for (Element member in conflictingElements) {
+      if (member.library.isInSdk) {
+        sdkElement = member;
+      } else {
+        nonSdkElements.add(member);
+      }
+    }
+    if (sdkElement != null && nonSdkElements.length > 0) {
+      String sdkLibName = _getLibraryName(sdkElement);
+      String otherLibName = _getLibraryName(nonSdkElements[0]);
+      errorListener.onError(new AnalysisError(
+          getSource(identifier),
+          identifier.offset,
+          identifier.length,
+          StaticWarningCode.CONFLICTING_DART_IMPORT,
+          [name, sdkLibName, otherLibName]));
+    }
+    if (nonSdkElements.length == conflictingElements.length) {
+      // None of the members were removed
+      return foundElement;
+    } else if (nonSdkElements.length == 1) {
+      // All but one member was removed
+      return nonSdkElements[0];
+    } else if (nonSdkElements.length == 0) {
+      // All members were removed
+      AnalysisEngine.instance.logger
+          .logInformation("Multiply defined SDK element: $foundElement");
+      return foundElement;
+    }
+    return new MultiplyDefinedElementImpl(
+        _definingLibrary.context, nonSdkElements);
+  }
+}
+
+/**
+ * A scope containing all of the names defined in a given library.
+ */
+class LibraryScope extends EnclosedScope {
+  /**
+   * Initialize a newly created scope representing the names defined in the
+   * [definingLibrary]. The [errorListener] is the listener that is to be
+   * informed when an error is encountered
+   */
+  LibraryScope(
+      LibraryElement definingLibrary, AnalysisErrorListener errorListener)
+      : super(new LibraryImportScope(definingLibrary, errorListener)) {
+    _defineTopLevelNames(definingLibrary);
+  }
+
+  @override
+  AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
+    if (existing is PrefixElement) {
+      // TODO(scheglov) consider providing actual 'nameOffset' from the
+      // synthetic accessor
+      int offset = duplicate.nameOffset;
+      if (duplicate is PropertyAccessorElement) {
+        PropertyAccessorElement accessor = duplicate;
+        if (accessor.isSynthetic) {
+          offset = accessor.variable.nameOffset;
+        }
+      }
+      return new AnalysisError(
+          duplicate.source,
+          offset,
+          duplicate.nameLength,
+          CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER,
+          [existing.displayName]);
+    }
+    return super.getErrorForDuplicate(existing, duplicate);
+  }
+
+  /**
+   * Add to this scope all of the public top-level names that are defined in the
+   * given [compilationUnit].
+   */
+  void _defineLocalNames(CompilationUnitElement compilationUnit) {
+    for (PropertyAccessorElement element in compilationUnit.accessors) {
+      define(element);
+    }
+    for (ClassElement element in compilationUnit.enums) {
+      define(element);
+    }
+    for (FunctionElement element in compilationUnit.functions) {
+      define(element);
+    }
+    for (FunctionTypeAliasElement element
+        in compilationUnit.functionTypeAliases) {
+      define(element);
+    }
+    for (ClassElement element in compilationUnit.types) {
+      define(element);
+    }
+  }
+
+  /**
+   * Add to this scope all of the names that are explicitly defined in the
+   * [definingLibrary].
+   */
+  void _defineTopLevelNames(LibraryElement definingLibrary) {
+    for (PrefixElement prefix in definingLibrary.prefixes) {
+      define(prefix);
+    }
+    _defineLocalNames(definingLibrary.definingCompilationUnit);
+    for (CompilationUnitElement compilationUnit in definingLibrary.parts) {
+      _defineLocalNames(compilationUnit);
+    }
+  }
+}
+
+/**
+ * A mapping of identifiers to the elements represented by those identifiers.
+ * Namespaces are the building blocks for scopes.
+ */
+class Namespace {
+  /**
+   * An empty namespace.
+   */
+  static Namespace EMPTY = new Namespace(new HashMap<String, Element>());
+
+  /**
+   * A table mapping names that are defined in this namespace to the element
+   * representing the thing declared with that name.
+   */
+  final HashMap<String, Element> _definedNames;
+
+  /**
+   * Initialize a newly created namespace to have the [_definedNames].
+   */
+  Namespace(this._definedNames);
+
+  /**
+   * Return a table containing the same mappings as those defined by this
+   * namespace.
+   */
+  Map<String, Element> get definedNames => _definedNames;
+
+  /**
+   * Return the element in this namespace that is available to the containing
+   * scope using the given name.
+   */
+  Element get(String name) => _definedNames[name];
+}
+
+/**
+ * The builder used to build a namespace. Namespace builders are thread-safe and
+ * re-usable.
+ */
+class NamespaceBuilder {
+  /**
+   * Create a namespace representing the export namespace of the given [element].
+   */
+  Namespace createExportNamespaceForDirective(ExportElement element) {
+    LibraryElement exportedLibrary = element.exportedLibrary;
+    if (exportedLibrary == null) {
+      //
+      // The exported library will be null if the URI does not reference a valid
+      // library.
+      //
+      return Namespace.EMPTY;
+    }
+    HashMap<String, Element> exportedNames = _getExportMapping(exportedLibrary);
+    exportedNames = _applyCombinators(exportedNames, element.combinators);
+    return new Namespace(exportedNames);
+  }
+
+  /**
+   * Create a namespace representing the export namespace of the given [library].
+   */
+  Namespace createExportNamespaceForLibrary(LibraryElement library) {
+    HashMap<String, Element> exportedNames = _getExportMapping(library);
+    return new Namespace(exportedNames);
+  }
+
+  /**
+   * Create a namespace representing the import namespace of the given [element].
+   */
+  Namespace createImportNamespaceForDirective(ImportElement element) {
+    LibraryElement importedLibrary = element.importedLibrary;
+    if (importedLibrary == null) {
+      //
+      // The imported library will be null if the URI does not reference a valid
+      // library.
+      //
+      return Namespace.EMPTY;
+    }
+    HashMap<String, Element> exportedNames = _getExportMapping(importedLibrary);
+    exportedNames = _applyCombinators(exportedNames, element.combinators);
+    exportedNames = _applyPrefix(exportedNames, element.prefix);
+    return new Namespace(exportedNames);
+  }
+
+  /**
+   * Create a namespace representing the public namespace of the given
+   * [library].
+   */
+  Namespace createPublicNamespaceForLibrary(LibraryElement library) {
+    HashMap<String, Element> definedNames = new HashMap<String, Element>();
+    _addPublicNames(definedNames, library.definingCompilationUnit);
+    for (CompilationUnitElement compilationUnit in library.parts) {
+      _addPublicNames(definedNames, compilationUnit);
+    }
+    return new Namespace(definedNames);
+  }
+
+  /**
+   * Add all of the names in the given [namespace] to the table of
+   * [definedNames].
+   */
+  void _addAllFromNamespace(
+      Map<String, Element> definedNames, Namespace namespace) {
+    if (namespace != null) {
+      definedNames.addAll(namespace.definedNames);
+    }
+  }
+
+  /**
+   * Add the given [element] to the table of [definedNames] if it has a
+   * publicly visible name.
+   */
+  void _addIfPublic(Map<String, Element> definedNames, Element element) {
+    String name = element.name;
+    if (name != null && !Scope.isPrivateName(name)) {
+      definedNames[name] = element;
+    }
+  }
+
+  /**
+   * Add to the table of [definedNames] all of the public top-level names that
+   * are defined in the given [compilationUnit].
+   *          namespace
+   */
+  void _addPublicNames(Map<String, Element> definedNames,
+      CompilationUnitElement compilationUnit) {
+    for (PropertyAccessorElement element in compilationUnit.accessors) {
+      _addIfPublic(definedNames, element);
+    }
+    for (ClassElement element in compilationUnit.enums) {
+      _addIfPublic(definedNames, element);
+    }
+    for (FunctionElement element in compilationUnit.functions) {
+      _addIfPublic(definedNames, element);
+    }
+    for (FunctionTypeAliasElement element
+        in compilationUnit.functionTypeAliases) {
+      _addIfPublic(definedNames, element);
+    }
+    for (ClassElement element in compilationUnit.types) {
+      _addIfPublic(definedNames, element);
+    }
+  }
+
+  /**
+   * Apply the given [combinators] to all of the names in the given table of
+   * [definedNames].
+   */
+  HashMap<String, Element> _applyCombinators(
+      HashMap<String, Element> definedNames,
+      List<NamespaceCombinator> combinators) {
+    for (NamespaceCombinator combinator in combinators) {
+      if (combinator is HideElementCombinator) {
+        definedNames = _hide(definedNames, combinator.hiddenNames);
+      } else if (combinator is ShowElementCombinator) {
+        definedNames = _show(definedNames, combinator.shownNames);
+      } else {
+        // Internal error.
+        AnalysisEngine.instance.logger
+            .logError("Unknown type of combinator: ${combinator.runtimeType}");
+      }
+    }
+    return definedNames;
+  }
+
+  /**
+   * Apply the prefix defined by the [prefixElement] to all of the names in the
+   * table of [definedNames].
+   */
+  HashMap<String, Element> _applyPrefix(
+      HashMap<String, Element> definedNames, PrefixElement prefixElement) {
+    if (prefixElement != null) {
+      String prefix = prefixElement.name;
+      HashMap<String, Element> newNames = new HashMap<String, Element>();
+      definedNames.forEach((String name, Element element) {
+        newNames["$prefix.$name"] = element;
+      });
+      return newNames;
+    } else {
+      return definedNames;
+    }
+  }
+
+  /**
+   * Create a mapping table representing the export namespace of the given
+   * [library]. The set of [visitedElements] contains the libraries that do not
+   * need to be visited when processing the export directives of the given
+   * library because all of the names defined by them will be added by another
+   * library.
+   */
+  HashMap<String, Element> _computeExportMapping(
+      LibraryElement library, HashSet<LibraryElement> visitedElements) {
+    visitedElements.add(library);
+    try {
+      HashMap<String, Element> definedNames = new HashMap<String, Element>();
+      for (ExportElement element in library.exports) {
+        LibraryElement exportedLibrary = element.exportedLibrary;
+        if (exportedLibrary != null &&
+            !visitedElements.contains(exportedLibrary)) {
+          //
+          // The exported library will be null if the URI does not reference a
+          // valid library.
+          //
+          HashMap<String, Element> exportedNames =
+              _computeExportMapping(exportedLibrary, visitedElements);
+          exportedNames = _applyCombinators(exportedNames, element.combinators);
+          definedNames.addAll(exportedNames);
+        }
+      }
+      _addAllFromNamespace(
+          definedNames,
+          (library.context as InternalAnalysisContext)
+              .getPublicNamespace(library));
+      return definedNames;
+    } finally {
+      visitedElements.remove(library);
+    }
+  }
+
+  HashMap<String, Element> _getExportMapping(LibraryElement library) {
+    if (library is LibraryElementImpl) {
+      if (library.exportNamespace != null) {
+        return library.exportNamespace.definedNames;
+      } else {
+        HashMap<String, Element> exportMapping =
+            _computeExportMapping(library, new HashSet<LibraryElement>());
+        library.exportNamespace = new Namespace(exportMapping);
+        return exportMapping;
+      }
+    }
+    return _computeExportMapping(library, new HashSet<LibraryElement>());
+  }
+
+  /**
+   * Return a new map of names which has all the names from [definedNames]
+   * with exception of [hiddenNames].
+   */
+  Map<String, Element> _hide(
+      HashMap<String, Element> definedNames, List<String> hiddenNames) {
+    HashMap<String, Element> newNames =
+        new HashMap<String, Element>.from(definedNames);
+    for (String name in hiddenNames) {
+      newNames.remove(name);
+      newNames.remove("$name=");
+    }
+    return newNames;
+  }
+
+  /**
+   * Return a new map of names which has only [shownNames] from [definedNames].
+   */
+  HashMap<String, Element> _show(
+      HashMap<String, Element> definedNames, List<String> shownNames) {
+    HashMap<String, Element> newNames = new HashMap<String, Element>();
+    for (String name in shownNames) {
+      Element element = definedNames[name];
+      if (element != null) {
+        newNames[name] = element;
+      }
+      String setterName = "$name=";
+      element = definedNames[setterName];
+      if (element != null) {
+        newNames[setterName] = element;
+      }
+    }
+    return newNames;
+  }
+}
+
+/**
+ * A name scope used by the resolver to determine which names are visible at any
+ * given point in the code.
+ */
+abstract class Scope {
+  /**
+   * The prefix used to mark an identifier as being private to its library.
+   */
+  static int PRIVATE_NAME_PREFIX = 0x5F;
+
+  /**
+   * The suffix added to the declared name of a setter when looking up the
+   * setter. Used to disambiguate between a getter and a setter that have the
+   * same name.
+   */
+  static String SETTER_SUFFIX = "=";
+
+  /**
+   * The name used to look up the method used to implement the unary minus
+   * operator. Used to disambiguate between the unary and binary operators.
+   */
+  static String UNARY_MINUS = "unary-";
+
+  /**
+   * A table mapping names that are defined in this scope to the element
+   * representing the thing declared with that name.
+   */
+  HashMap<String, Element> _definedNames = null;
+
+  /**
+   * Return the scope in which this scope is lexically enclosed.
+   */
+  Scope get enclosingScope => null;
+
+  /**
+   * Return the listener that is to be informed when an error is encountered.
+   */
+  AnalysisErrorListener get errorListener;
+
+  /**
+   * Add the given [element] to this scope. If there is already an element with
+   * the given name defined in this scope, then an error will be generated and
+   * the original element will continue to be mapped to the name. If there is an
+   * element with the given name in an enclosing scope, then a warning will be
+   * generated but the given element will hide the inherited element.
+   */
+  void define(Element element) {
+    String name = _getName(element);
+    if (name != null && !name.isEmpty) {
+      if (_definedNames != null && _definedNames.containsKey(name)) {
+        errorListener
+            .onError(getErrorForDuplicate(_definedNames[name], element));
+      } else {
+        _definedNames ??= new HashMap<String, Element>();
+        _definedNames[name] = element;
+      }
+    }
+  }
+
+  /**
+   * Add the given [element] to this scope without checking for duplication or
+   * hiding.
+   */
+  void defineNameWithoutChecking(String name, Element element) {
+    _definedNames ??= new HashMap<String, Element>();
+    _definedNames[name] = element;
+  }
+
+  /**
+   * Add the given [element] to this scope without checking for duplication or
+   * hiding.
+   */
+  void defineWithoutChecking(Element element) {
+    _definedNames ??= new HashMap<String, Element>();
+    _definedNames[_getName(element)] = element;
+  }
+
+  /**
+   * Return the error code to be used when reporting that a name being defined
+   * locally conflicts with another element of the same name in the local scope.
+   * [existing] is the first element to be declared with the conflicting name,
+   * while [duplicate] another element declared with the conflicting name.
+   */
+  AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
+    // TODO(brianwilkerson) Customize the error message based on the types of
+    // elements that share the same name.
+    // TODO(jwren) There are 4 error codes for duplicate, but only 1 is being
+    // generated.
+    Source source = duplicate.source;
+    return new AnalysisError(source, duplicate.nameOffset, duplicate.nameLength,
+        CompileTimeErrorCode.DUPLICATE_DEFINITION, [existing.displayName]);
+  }
+
+  /**
+   * Return the source that contains the given [identifier], or the source
+   * associated with this scope if the source containing the identifier could
+   * not be determined.
+   */
+  Source getSource(AstNode identifier) {
+    CompilationUnit unit =
+        identifier.getAncestor((node) => node is CompilationUnit);
+    if (unit != null) {
+      CompilationUnitElement unitElement = unit.element;
+      if (unitElement != null) {
+        return unitElement.source;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Return the element with which the given [name] is associated, or `null` if
+   * the name is not defined within this scope. The [identifier] is the
+   * identifier node to lookup element for, used to report correct kind of a
+   * problem and associate problem with. The [referencingLibrary] is the library
+   * that contains the reference to the name, used to implement library-level
+   * privacy.
+   */
+  Element internalLookup(
+      Identifier identifier, String name, LibraryElement referencingLibrary);
+
+  /**
+   * Return the element with which the given [name] is associated, or `null` if
+   * the name is not defined within this scope. This method only returns
+   * elements that are directly defined within this scope, not elements that are
+   * defined in an enclosing scope. The [referencingLibrary] is the library that
+   * contains the reference to the name, used to implement library-level privacy.
+   */
+  Element localLookup(String name, LibraryElement referencingLibrary) {
+    if (_definedNames != null) {
+      return _definedNames[name];
+    }
+    return null;
+  }
+
+  /**
+   * Return the element with which the given [identifier] is associated, or
+   * `null` if the name is not defined within this scope. The
+   * [referencingLibrary] is the library that contains the reference to the
+   * name, used to implement library-level privacy.
+   */
+  Element lookup(Identifier identifier, LibraryElement referencingLibrary) =>
+      internalLookup(identifier, identifier.name, referencingLibrary);
+
+  /**
+   * Return the name that will be used to look up the given [element].
+   */
+  String _getName(Element element) {
+    if (element is MethodElement) {
+      MethodElement method = element;
+      if (method.name == "-" && method.parameters.length == 0) {
+        return UNARY_MINUS;
+      }
+    }
+    return element.name;
+  }
+
+  /**
+   * Return `true` if the given [name] is a library-private name.
+   */
+  static bool isPrivateName(String name) =>
+      name != null && StringUtilities.startsWithChar(name, PRIVATE_NAME_PREFIX);
+}
+
+/**
+ * The scope defined by the type parameters in a class.
+ */
+class TypeParameterScope extends EnclosedScope {
+  /**
+   * Initialize a newly created scope, enclosed within the [enclosingScope],
+   * that defined the type parameters from the given [classElement].
+   */
+  TypeParameterScope(Scope enclosingScope, ClassElement classElement)
+      : super(enclosingScope) {
+    if (classElement == null) {
+      throw new IllegalArgumentException("class element cannot be null");
+    }
+    _defineTypeParameters(classElement);
+  }
+
+  /**
+   * Define the type parameters declared by the [classElement].
+   */
+  void _defineTypeParameters(ClassElement classElement) {
+    for (TypeParameterElement typeParameter in classElement.typeParameters) {
+      define(typeParameter);
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index 16113c5..b3a9e78 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -9,8 +9,7 @@
 import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/engine.dart'
-    show AnalysisEngine, RecordingErrorListener;
+import 'package:analyzer/src/generated/engine.dart' show RecordingErrorListener;
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
 import 'package:analyzer/src/generated/source.dart' show Source;
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index e8591ae..b37ebea 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -219,14 +219,13 @@
   Object visitCommentReference(CommentReference node) {
     Identifier identifier = node.identifier;
     if (identifier is SimpleIdentifier) {
-      SimpleIdentifier simpleIdentifier = identifier;
-      Element element = _resolveSimpleIdentifier(simpleIdentifier);
+      Element element = _resolveSimpleIdentifier(identifier);
       if (element == null) {
         //
         // This might be a reference to an imported name that is missing the
         // prefix.
         //
-        element = _findImportWithoutPrefix(simpleIdentifier);
+        element = _findImportWithoutPrefix(identifier);
         if (element is MultiplyDefinedElement) {
           // TODO(brianwilkerson) Report this error?
           element = null;
@@ -242,14 +241,14 @@
         if (element.library == null || element.library != _definingLibrary) {
           // TODO(brianwilkerson) Report this error?
         }
-        simpleIdentifier.staticElement = element;
+        identifier.staticElement = element;
         if (node.newKeyword != null) {
           if (element is ClassElement) {
             ConstructorElement constructor = element.unnamedConstructor;
             if (constructor == null) {
               // TODO(brianwilkerson) Report this error.
             } else {
-              simpleIdentifier.staticElement = constructor;
+              identifier.staticElement = constructor;
             }
           } else {
             // TODO(brianwilkerson) Report this error.
@@ -257,9 +256,8 @@
         }
       }
     } else if (identifier is PrefixedIdentifier) {
-      PrefixedIdentifier prefixedIdentifier = identifier;
-      SimpleIdentifier prefix = prefixedIdentifier.prefix;
-      SimpleIdentifier name = prefixedIdentifier.identifier;
+      SimpleIdentifier prefix = identifier.prefix;
+      SimpleIdentifier name = identifier.identifier;
       Element element = _resolveSimpleIdentifier(prefix);
       if (element == null) {
 //        resolver.reportError(StaticWarningCode.UNDEFINED_IDENTIFIER, prefix, prefix.getName());
@@ -291,7 +289,7 @@
               }
             }
             if (memberElement == null) {
-//              reportGetterOrSetterNotFound(prefixedIdentifier, name, element.getDisplayName());
+//              reportGetterOrSetterNotFound(identifier, name, element.getDisplayName());
             } else {
               name.staticElement = memberElement;
             }
@@ -321,18 +319,17 @@
     super.visitConstructorDeclaration(node);
     ConstructorElement element = node.element;
     if (element is ConstructorElementImpl) {
-      ConstructorElementImpl constructorElement = element;
       ConstructorName redirectedNode = node.redirectedConstructor;
       if (redirectedNode != null) {
         // set redirected factory constructor
         ConstructorElement redirectedElement = redirectedNode.staticElement;
-        constructorElement.redirectedConstructor = redirectedElement;
+        element.redirectedConstructor = redirectedElement;
       } else {
         // set redirected generative constructor
         for (ConstructorInitializer initializer in node.initializers) {
           if (initializer is RedirectingConstructorInvocation) {
             ConstructorElement redirectedElement = initializer.staticElement;
-            constructorElement.redirectedConstructor = redirectedElement;
+            element.redirectedConstructor = redirectedElement;
           }
         }
       }
@@ -354,8 +351,19 @@
   Object visitConstructorName(ConstructorName node) {
     DartType type = node.type.type;
     if (type != null && type.isDynamic) {
-      return null;
-    } else if (type is! InterfaceType) {
+      // Nothing to do.
+    } else if (type is InterfaceType) {
+      // look up ConstructorElement
+      ConstructorElement constructor;
+      SimpleIdentifier name = node.name;
+      if (name == null) {
+        constructor = type.lookUpConstructor(null, _definingLibrary);
+      } else {
+        constructor = type.lookUpConstructor(name.name, _definingLibrary);
+        name.staticElement = constructor;
+      }
+      node.staticElement = constructor;
+    } else {
 // TODO(brianwilkerson) Report these errors.
 //      ASTNode parent = node.getParent();
 //      if (parent instanceof InstanceCreationExpression) {
@@ -367,20 +375,7 @@
 //      } else {
 //        // This is part of a redirecting factory constructor; not sure which error code to use
 //      }
-      return null;
     }
-    // look up ConstructorElement
-    ConstructorElement constructor;
-    SimpleIdentifier name = node.name;
-    InterfaceType interfaceType = type as InterfaceType;
-    if (name == null) {
-      constructor = interfaceType.lookUpConstructor(null, _definingLibrary);
-    } else {
-      constructor =
-          interfaceType.lookUpConstructor(name.name, _definingLibrary);
-      name.staticElement = constructor;
-    }
-    node.staticElement = constructor;
     return null;
   }
 
@@ -722,8 +717,9 @@
         } else {
           DartType type = _getBestType(target);
           if (type != null) {
-            if (type.element is ClassElement) {
-              classElementContext = type.element as ClassElement;
+            Element element = type.element;
+            if (element is ClassElement) {
+              classElementContext = element;
             }
           }
         }
@@ -808,11 +804,14 @@
         errorCode, StaticTypeWarningCode.UNDEFINED_SUPER_METHOD)) {
       // Generate the type name.
       // The error code will never be generated via type propagation
-      DartType targetType = _getStaticType(target);
-      if (targetType is InterfaceType && !targetType.isObject) {
-        targetType = (targetType as InterfaceType).superclass;
+      DartType getSuperType(DartType type) {
+        if (type is InterfaceType && !type.isObject) {
+          return type.superclass;
+        }
+        return type;
       }
-      String targetTypeName = targetType == null ? null : targetType.name;
+      DartType targetType = getSuperType(_getStaticType(target));
+      String targetTypeName = targetType?.name;
       _resolver.reportErrorForNode(StaticTypeWarningCode.UNDEFINED_SUPER_METHOD,
           methodName, [methodName.name, targetTypeName]);
     }
@@ -887,20 +886,21 @@
         if (identifier.inSetterContext()) {
           _resolver.reportErrorForNode(StaticWarningCode.UNDEFINED_SETTER,
               identifier, [identifier.name, prefixElement.name]);
-        } else if (node.parent is Annotation) {
-          Annotation annotation = node.parent as Annotation;
-          _resolver.reportErrorForNode(
-              CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
           return null;
+        }
+        AstNode parent = node.parent;
+        if (parent is Annotation) {
+          _resolver.reportErrorForNode(
+              CompileTimeErrorCode.INVALID_ANNOTATION, parent);
         } else {
           _resolver.reportErrorForNode(StaticWarningCode.UNDEFINED_GETTER,
               identifier, [identifier.name, prefixElement.name]);
         }
         return null;
       }
-      if (element is PropertyAccessorElement && identifier.inSetterContext()) {
-        PropertyInducingElement variable =
-            (element as PropertyAccessorElement).variable;
+      Element accessor = element;
+      if (accessor is PropertyAccessorElement && identifier.inSetterContext()) {
+        PropertyInducingElement variable = accessor.variable;
         if (variable != null) {
           PropertyAccessorElement setter = variable.setter;
           if (setter != null) {
@@ -912,17 +912,16 @@
       // the import that defines the prefix, not the prefix's element.
       identifier.staticElement = element;
       // Validate annotation element.
-      if (node.parent is Annotation) {
-        Annotation annotation = node.parent as Annotation;
-        _resolveAnnotationElement(annotation);
-        return null;
+      AstNode parent = node.parent;
+      if (parent is Annotation) {
+        _resolveAnnotationElement(parent);
       }
       return null;
     }
     // May be annotation, resolve invocation of "const" constructor.
-    if (node.parent is Annotation) {
-      Annotation annotation = node.parent as Annotation;
-      _resolveAnnotationElement(annotation);
+    AstNode parent = node.parent;
+    if (parent is Annotation) {
+      _resolveAnnotationElement(parent);
     }
     //
     // Otherwise, the prefix is really an expression that happens to be a simple
@@ -1083,18 +1082,19 @@
       if (_isConstructorReturnType(node)) {
         _resolver.reportErrorForNode(
             CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node);
-      } else if (node.parent is Annotation) {
-        Annotation annotation = node.parent as Annotation;
-        _resolver.reportErrorForNode(
-            CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
-      } else if (element is PrefixElement) {
-        _resolver.reportErrorForNode(
-            CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
-            node,
-            [element.name]);
       } else {
-        _recordUndefinedNode(_resolver.enclosingClass,
-            StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]);
+        if (parent is Annotation) {
+          _resolver.reportErrorForNode(
+              CompileTimeErrorCode.INVALID_ANNOTATION, parent);
+        } else if (element != null) {
+          _resolver.reportErrorForNode(
+              CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
+              node,
+              [element.name]);
+        } else {
+          _recordUndefinedNode(_resolver.enclosingClass,
+              StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]);
+        }
       }
     }
     node.staticElement = element;
@@ -1109,9 +1109,8 @@
     //
     // Validate annotation element.
     //
-    if (node.parent is Annotation) {
-      Annotation annotation = node.parent as Annotation;
-      _resolveAnnotationElement(annotation);
+    if (parent is Annotation) {
+      _resolveAnnotationElement(parent);
     }
     return null;
   }
@@ -1200,8 +1199,7 @@
     // Prefix is not declared, instead "prefix.id" are declared.
     if (element is PrefixElement) {
       return CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT;
-    }
-    if (element is PropertyAccessorElement) {
+    } else if (element is PropertyAccessorElement) {
       //
       // This is really a function expression invocation.
       //
@@ -1415,12 +1413,11 @@
   }
 
   /**
-   * Assuming that the given [expression] is a prefix for a deferred import,
+   * Assuming that the given [identifier] is a prefix for a deferred import,
    * return the library that is being imported.
    */
-  LibraryElement _getImportedLibrary(Expression expression) {
-    PrefixElement prefixElement =
-        (expression as SimpleIdentifier).staticElement as PrefixElement;
+  LibraryElement _getImportedLibrary(SimpleIdentifier identifier) {
+    PrefixElement prefixElement = identifier.staticElement as PrefixElement;
     List<ImportElement> imports =
         prefixElement.enclosingElement.getImportsWithPrefix(prefixElement);
     return imports[0].importedLibrary;
@@ -1515,24 +1512,23 @@
       DartType invokeType, TypeArgumentList typeArguments, AstNode node) {
     // TODO(jmesserly): support generic "call" methods on InterfaceType.
     if (invokeType is FunctionType) {
-      FunctionType type = invokeType;
-      List<TypeParameterElement> parameters = type.typeFormals;
+      List<TypeParameterElement> parameters = invokeType.typeFormals;
 
       NodeList<TypeName> arguments = typeArguments?.arguments;
       if (arguments != null && arguments.length != parameters.length) {
         _resolver.reportErrorForNode(
             StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
             node,
-            [type, parameters.length, arguments?.length ?? 0]);
+            [invokeType, parameters.length, arguments?.length ?? 0]);
 
         // Wrong number of type arguments. Ignore them.
         arguments = null;
       }
       if (parameters.isNotEmpty) {
         if (arguments == null) {
-          invokeType = _resolver.typeSystem.instantiateToBounds(type);
+          return _resolver.typeSystem.instantiateToBounds(invokeType);
         } else {
-          invokeType = type.instantiate(arguments.map((n) => n.type).toList());
+          return invokeType.instantiate(arguments.map((n) => n.type).toList());
         }
       }
     }
@@ -1543,20 +1539,18 @@
    * Return `true` if the given [expression] is a prefix for a deferred import.
    */
   bool _isDeferredPrefix(Expression expression) {
-    if (expression is! SimpleIdentifier) {
-      return false;
+    if (expression is SimpleIdentifier) {
+      Element element = expression.staticElement;
+      if (element is PrefixElement) {
+        List<ImportElement> imports =
+            element.enclosingElement.getImportsWithPrefix(element);
+        if (imports.length != 1) {
+          return false;
+        }
+        return imports[0].isDeferred;
+      }
     }
-    Element element = (expression as SimpleIdentifier).staticElement;
-    if (element is! PrefixElement) {
-      return false;
-    }
-    PrefixElement prefixElement = element as PrefixElement;
-    List<ImportElement> imports =
-        prefixElement.enclosingElement.getImportsWithPrefix(prefixElement);
-    if (imports.length != 1) {
-      return false;
-    }
-    return imports[0].isDeferred;
+    return false;
   }
 
   /**
@@ -1869,9 +1863,8 @@
     {
       Identifier annName = annotation.name;
       if (annName is PrefixedIdentifier) {
-        PrefixedIdentifier prefixed = annName;
-        nameNode1 = prefixed.prefix;
-        nameNode2 = prefixed.identifier;
+        nameNode1 = annName.prefix;
+        nameNode2 = annName.identifier;
       } else {
         nameNode1 = annName as SimpleIdentifier;
         nameNode2 = null;
@@ -1891,8 +1884,7 @@
       }
       // Class(args)
       if (element1 is ClassElement) {
-        ClassElement classElement = element1;
-        constructor = new InterfaceTypeImpl(classElement)
+        constructor = new InterfaceTypeImpl(element1)
             .lookUpConstructor(null, _definingLibrary);
       }
     }
@@ -1904,8 +1896,7 @@
       Element element2 = nameNode2.staticElement;
       // Class.CONST - not resolved yet
       if (element1 is ClassElement) {
-        ClassElement classElement = element1;
-        element2 = classElement.lookUpGetter(nameNode2.name, _definingLibrary);
+        element2 = element1.lookUpGetter(nameNode2.name, _definingLibrary);
       }
       // prefix.CONST or Class.CONST
       if (element2 is PropertyAccessorElement) {
@@ -1920,8 +1911,7 @@
       }
       // Class.constructor(args)
       if (element1 is ClassElement) {
-        ClassElement classElement = element1;
-        constructor = new InterfaceTypeImpl(classElement)
+        constructor = new InterfaceTypeImpl(element1)
             .lookUpConstructor(nameNode2.name, _definingLibrary);
         nameNode2.staticElement = constructor;
       }
@@ -1933,11 +1923,10 @@
       Element element2 = nameNode2.staticElement;
       // element2 should be ClassElement
       if (element2 is ClassElement) {
-        ClassElement classElement = element2;
         String name3 = nameNode3.name;
         // prefix.Class.CONST
         PropertyAccessorElement getter =
-            classElement.lookUpGetter(name3, _definingLibrary);
+            element2.lookUpGetter(name3, _definingLibrary);
         if (getter != null) {
           nameNode3.staticElement = getter;
           annotation.element = element2;
@@ -1945,7 +1934,7 @@
           return;
         }
         // prefix.Class.constructor(args)
-        constructor = new InterfaceTypeImpl(classElement)
+        constructor = new InterfaceTypeImpl(element2)
             .lookUpConstructor(name3, _definingLibrary);
         nameNode3.staticElement = constructor;
       }
@@ -2084,17 +2073,15 @@
       }
       for (SimpleIdentifier name in names) {
         String nameStr = name.name;
-        Element element = namespace.get(nameStr);
-        if (element == null) {
-          element = namespace.get("$nameStr=");
-        }
+        Element element = namespace.get(nameStr) ?? namespace.get("$nameStr=");
         if (element != null) {
           // Ensure that the name always resolves to a top-level variable
           // rather than a getter or setter
           if (element is PropertyAccessorElement) {
-            element = (element as PropertyAccessorElement).variable;
+            name.staticElement = element.variable;
+          } else {
+            name.staticElement = element;
           }
-          name.staticElement = element;
         }
       }
     }
@@ -2298,8 +2285,7 @@
       if (propertyName.inGetterContext()) {
         if (!isStaticProperty &&
             staticOrPropagatedEnclosingElt is ClassElement) {
-          ClassElement classElement = staticOrPropagatedEnclosingElt;
-          InterfaceType targetType = classElement.type;
+          InterfaceType targetType = staticOrPropagatedEnclosingElt.type;
           if (!_enableStrictCallChecks &&
               targetType != null &&
               targetType.isDartCoreFunction &&
@@ -2308,7 +2294,8 @@
             // invoked?
 //            resolveArgumentsToParameters(node.getArgumentList(), invokedFunction);
             return;
-          } else if (classElement.isEnum && propertyName.name == "_name") {
+          } else if (staticOrPropagatedEnclosingElt.isEnum &&
+              propertyName.name == "_name") {
             _resolver.reportErrorForNode(
                 CompileTimeErrorCode.ACCESS_PRIVATE_ENUM_FIELD,
                 propertyName,
@@ -2458,16 +2445,16 @@
    */
   static void resolveMetadata(AnnotatedNode node) {
     _resolveAnnotations(node.metadata);
-    if (node is VariableDeclaration && node.parent is VariableDeclarationList) {
-      VariableDeclarationList list = node.parent as VariableDeclarationList;
-      _resolveAnnotations(list.metadata);
-      if (list.parent is FieldDeclaration) {
-        FieldDeclaration fieldDeclaration = list.parent as FieldDeclaration;
-        _resolveAnnotations(fieldDeclaration.metadata);
-      } else if (list.parent is TopLevelVariableDeclaration) {
-        TopLevelVariableDeclaration variableDeclaration =
-            list.parent as TopLevelVariableDeclaration;
-        _resolveAnnotations(variableDeclaration.metadata);
+    if (node is VariableDeclaration) {
+      AstNode parent = node.parent;
+      if (parent is VariableDeclarationList) {
+        _resolveAnnotations(parent.metadata);
+        AstNode grandParent = parent.parent;
+        if (grandParent is FieldDeclaration) {
+          _resolveAnnotations(grandParent.metadata);
+        } else if (grandParent is TopLevelVariableDeclaration) {
+          _resolveAnnotations(grandParent.metadata);
+        }
       }
     }
   }
@@ -2491,9 +2478,8 @@
   static bool _isFactoryConstructorReturnType(SimpleIdentifier identifier) {
     AstNode parent = identifier.parent;
     if (parent is ConstructorDeclaration) {
-      ConstructorDeclaration constructor = parent;
-      return identical(constructor.returnType, identifier) &&
-          constructor.factoryKeyword != null;
+      return identical(parent.returnType, identifier) &&
+          parent.factoryKeyword != null;
     }
     return false;
   }
@@ -2505,14 +2491,11 @@
     for (AstNode node = expression; node != null; node = node.parent) {
       if (node is CompilationUnit) {
         return false;
-      }
-      if (node is ConstructorDeclaration) {
+      } else if (node is ConstructorDeclaration) {
         return node.factoryKeyword == null;
-      }
-      if (node is ConstructorFieldInitializer) {
+      } else if (node is ConstructorFieldInitializer) {
         return false;
-      }
-      if (node is MethodDeclaration) {
+      } else if (node is MethodDeclaration) {
         return !node.isStatic;
       }
     }
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index f3947b4..96cdd80 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -13,7 +13,6 @@
 import 'package:analyzer/source/error_processor.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart' show ScannerErrorCode;
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/generated/shared_messages.dart'
     as shared_messages;
 import 'package:analyzer/src/generated/java_core.dart';
@@ -144,34 +143,33 @@
   String get message => _message;
 
   @override
-  bool operator ==(Object obj) {
-    if (identical(obj, this)) {
+  bool operator ==(Object other) {
+    if (identical(other, this)) {
       return true;
     }
     // prepare other AnalysisError
-    if (obj is! AnalysisError) {
-      return false;
+    if (other is AnalysisError) {
+      // Quick checks.
+      if (!identical(errorCode, other.errorCode)) {
+        return false;
+      }
+      if (offset != other.offset || length != other.length) {
+        return false;
+      }
+      if (isStaticOnly != other.isStaticOnly) {
+        return false;
+      }
+      // Deep checks.
+      if (_message != other._message) {
+        return false;
+      }
+      if (source != other.source) {
+        return false;
+      }
+      // OK
+      return true;
     }
-    AnalysisError other = obj as AnalysisError;
-    // Quick checks.
-    if (!identical(errorCode, other.errorCode)) {
-      return false;
-    }
-    if (offset != other.offset || length != other.length) {
-      return false;
-    }
-    if (isStaticOnly != other.isStaticOnly) {
-      return false;
-    }
-    // Deep checks.
-    if (_message != other._message) {
-      return false;
-    }
-    if (source != other.source) {
-      return false;
-    }
-    // OK
-    return true;
+    return false;
   }
 
   /**
@@ -2686,6 +2684,7 @@
     HintCode.INVALID_USE_OF_PROTECTED_MEMBER,
     HintCode.MISSING_JS_LIB_ANNOTATION,
     HintCode.MISSING_REQUIRED_PARAM,
+    HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS,
     HintCode.MISSING_RETURN,
     HintCode.NULL_AWARE_IN_CONDITION,
     HintCode.OVERRIDE_ON_NON_OVERRIDING_GETTER,
@@ -2695,9 +2694,11 @@
     HintCode.TYPE_CHECK_IS_NOT_NULL,
     HintCode.TYPE_CHECK_IS_NULL,
     HintCode.UNDEFINED_GETTER,
+    HintCode.UNDEFINED_HIDDEN_NAME,
     HintCode.UNDEFINED_METHOD,
     HintCode.UNDEFINED_OPERATOR,
     HintCode.UNDEFINED_SETTER,
+    HintCode.UNDEFINED_SHOWN_NAME,
     HintCode.UNNECESSARY_CAST,
     HintCode.UNNECESSARY_NO_SUCH_METHOD,
     HintCode.UNNECESSARY_TYPE_CHECK_FALSE,
@@ -3265,12 +3266,12 @@
       for (int i = 0; i < count; i++) {
         Object argument = arguments[i];
         if (argument is DartType) {
-          DartType type = argument;
-          Element element = type.element;
+          Element element = argument.element;
           if (element == null) {
-            arguments[i] = displayName(type);
+            arguments[i] = displayName(argument);
           } else {
-            arguments[i] = element.getExtendedDisplayName(displayName(type));
+            arguments[i] =
+                element.getExtendedDisplayName(displayName(argument));
           }
         }
       }
@@ -3293,8 +3294,8 @@
     int count = arguments.length;
     HashSet<String> typeNames = new HashSet<String>();
     for (int i = 0; i < count; i++) {
-      if (arguments[i] is DartType &&
-          !typeNames.add((arguments[i] as DartType).displayName)) {
+      Object argument = arguments[i];
+      if (argument is DartType && !typeNames.add(argument.displayName)) {
         return true;
       }
     }
@@ -3581,12 +3582,22 @@
    *
    * Parameters:
    * 0: the name of the parameter
-   * 1: an optional reason
    */
   static const HintCode MISSING_REQUIRED_PARAM = const HintCode(
+      'MISSING_REQUIRED_PARAM', "The parameter '{0}' is required.");
+
+  /**
+   * Generate a hint for a constructor, function or method invocation where a
+   * required parameter is missing.
+   *
+   * Parameters:
+   * 0: the name of the parameter
+   * 1: message details
+   */
+  static const HintCode MISSING_REQUIRED_PARAM_WITH_DETAILS = const HintCode(
       'MISSING_REQUIRED_PARAM', "The parameter '{0}' is required. {1}");
 
-   /**
+  /**
    * Generate a hint for an element that is annotated with `@JS(...)` whose
    * library declaration is not similarly annotated.
    */
@@ -3687,6 +3698,13 @@
       shared_messages.UNDEFINED_GETTER_HINT;
 
   /**
+   * An undefined name hidden in an import or export directive.
+   */
+  static const HintCode UNDEFINED_HIDDEN_NAME = const HintCode(
+      'UNDEFINED_HIDDEN_NAME',
+      "The library '{0}' doesn't export a member with the hidden name '{1}'");
+
+  /**
    * This hint is generated anywhere where the
    * [StaticTypeWarningCode.UNDEFINED_METHOD] would have been generated, if we
    * used propagated information for the warnings.
@@ -3724,6 +3742,13 @@
       shared_messages.UNDEFINED_SETTER_HINT;
 
   /**
+   * An undefined name shown in an import or export directive.
+   */
+  static const HintCode UNDEFINED_SHOWN_NAME = const HintCode(
+      'UNDEFINED_SHOWN_NAME',
+      "The library '{0}' doesn't export a member with the shown name '{1}'");
+
+  /**
    * Unnecessary cast.
    */
   static const HintCode UNNECESSARY_CAST =
@@ -3791,8 +3816,8 @@
   /**
    * Unused shown names are names shown on imports which are never used.
    */
-  static const HintCode UNUSED_SHOWN_NAME =
-      const HintCode('UNUSED_SHOWN_NAME', "The name {0} is shown, but not used.");
+  static const HintCode UNUSED_SHOWN_NAME = const HintCode(
+      'UNUSED_SHOWN_NAME', "The name {0} is shown, but not used.");
 
   /**
    * Hint for cases where the source expects a method or function to return a
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index ac7214d..c99057a 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -13,20 +13,21 @@
 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/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';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/inheritance_manager.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/element_resolver.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/parser.dart'
-    show Parser, ParserErrorCode;
+import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk, SdkLibrary;
 import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/task/strong/info.dart' show StaticInfo;
 
 /**
  * A visitor used to traverse an AST structure looking for additional errors and
@@ -72,6 +73,11 @@
   InterfaceType _intType;
 
   /**
+   * The options for verification.
+   */
+  AnalysisOptions _options;
+
+  /**
    * The object providing access to the types defined by the language.
    */
   final TypeProvider _typeProvider;
@@ -301,6 +307,7 @@
     _intType = _typeProvider.intType;
     _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT = _typeProvider.nonSubtypableTypes;
     _typeSystem = _currentLibrary.context.typeSystem;
+    _options = _currentLibrary.context.analysisOptions;
   }
 
   @override
@@ -574,7 +581,9 @@
       SimpleIdentifier fieldName = node.fieldName;
       Element staticElement = fieldName.staticElement;
       _checkForInvalidField(node, fieldName, staticElement);
-      _checkForFieldInitializerNotAssignable(node, staticElement);
+      if (staticElement is FieldElement) {
+        _checkForFieldInitializerNotAssignable(node, staticElement);
+      }
       return super.visitConstructorFieldInitializer(node);
     } finally {
       _isInConstructorInitializer = false;
@@ -644,10 +653,10 @@
       DartType expectedReturnType = functionType == null
           ? DynamicTypeImpl.instance
           : functionType.returnType;
-      bool isSetterWithImplicitReturn =
-          _enclosingFunction.hasImplicitReturnType &&
-              _enclosingFunction is PropertyAccessorElement &&
-              (_enclosingFunction as PropertyAccessorElement).isSetter;
+      ExecutableElement function = _enclosingFunction;
+      bool isSetterWithImplicitReturn = function.hasImplicitReturnType &&
+          function is PropertyAccessorElement &&
+          function.isSetter;
       if (!isSetterWithImplicitReturn) {
         _checkForReturnOfInvalidType(node.expression, expectedReturnType);
       }
@@ -817,9 +826,8 @@
       TypeName typeName = constructorName.type;
       DartType type = typeName.type;
       if (type is InterfaceType) {
-        InterfaceType interfaceType = type;
-        _checkForConstOrNewWithAbstractClass(node, typeName, interfaceType);
-        _checkForConstOrNewWithEnum(node, typeName, interfaceType);
+        _checkForConstOrNewWithAbstractClass(node, typeName, type);
+        _checkForConstOrNewWithEnum(node, typeName, type);
         _checkForMissingRequiredParam(
             node.staticElement?.type, node.argumentList, node.constructorName);
         if (_isInConstInstanceCreation) {
@@ -1236,10 +1244,13 @@
     NodeList<FormalParameter> formalParameters =
         constructor.parameters.parameters;
     for (FormalParameter formalParameter in formalParameters) {
-      FormalParameter parameter = formalParameter;
-      if (parameter is DefaultFormalParameter) {
-        parameter = (parameter as DefaultFormalParameter).parameter;
+      FormalParameter baseParameter(FormalParameter parameter) {
+        if (parameter is DefaultFormalParameter) {
+          return parameter.parameter;
+        }
+        return parameter;
       }
+      FormalParameter parameter = baseParameter(formalParameter);
       if (parameter is FieldFormalParameter) {
         FieldElement fieldElement =
             (parameter.element as FieldFormalParameterElementImpl).field;
@@ -1271,17 +1282,14 @@
         return;
       }
       if (constructorInitializer is ConstructorFieldInitializer) {
-        ConstructorFieldInitializer constructorFieldInitializer =
-            constructorInitializer;
-        SimpleIdentifier fieldName = constructorFieldInitializer.fieldName;
+        SimpleIdentifier fieldName = constructorInitializer.fieldName;
         Element element = fieldName.staticElement;
         if (element is FieldElement) {
-          FieldElement fieldElement = element;
-          INIT_STATE state = fieldElementsMap[fieldElement];
+          INIT_STATE state = fieldElementsMap[element];
           if (state == INIT_STATE.NOT_INIT) {
-            fieldElementsMap[fieldElement] = INIT_STATE.INIT_IN_INITIALIZERS;
+            fieldElementsMap[element] = INIT_STATE.INIT_IN_INITIALIZERS;
           } else if (state == INIT_STATE.INIT_IN_DECLARATION) {
-            if (fieldElement.isFinal || fieldElement.isConst) {
+            if (element.isFinal || element.isConst) {
               _errorReporter.reportErrorForNode(
                   StaticWarningCode
                       .FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION,
@@ -1296,7 +1304,7 @@
             _errorReporter.reportErrorForNode(
                 CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS,
                 fieldName,
-                [fieldElement.displayName]);
+                [element.displayName]);
           }
         }
       }
@@ -1376,9 +1384,8 @@
     bool isGetter = false;
     bool isSetter = false;
     if (executableElement is PropertyAccessorElement) {
-      PropertyAccessorElement accessorElement = executableElement;
-      isGetter = accessorElement.isGetter;
-      isSetter = accessorElement.isSetter;
+      isGetter = executableElement.isGetter;
+      isSetter = executableElement.isSetter;
     }
     String executableElementName = executableElement.name;
     FunctionType overridingFT = executableElement.type;
@@ -1807,27 +1814,26 @@
     bool problemReported = false;
     for (TypeName mixinName in withClause.mixinTypes) {
       DartType mixinType = mixinName.type;
-      if (mixinType is! InterfaceType) {
-        continue;
-      }
-      if (_checkForExtendsOrImplementsDisallowedClass(
-          mixinName, CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS)) {
-        problemReported = true;
-      } else {
-        ClassElement mixinElement = (mixinType as InterfaceType).element;
-        if (_checkForExtendsOrImplementsDeferredClass(
-            mixinName, CompileTimeErrorCode.MIXIN_DEFERRED_CLASS)) {
+      if (mixinType is InterfaceType) {
+        if (_checkForExtendsOrImplementsDisallowedClass(
+            mixinName, CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS)) {
           problemReported = true;
-        }
-        if (_checkForMixinDeclaresConstructor(mixinName, mixinElement)) {
-          problemReported = true;
-        }
-        if (!enableSuperMixins &&
-            _checkForMixinInheritsNotFromObject(mixinName, mixinElement)) {
-          problemReported = true;
-        }
-        if (_checkForMixinReferencesSuper(mixinName, mixinElement)) {
-          problemReported = true;
+        } else {
+          ClassElement mixinElement = mixinType.element;
+          if (_checkForExtendsOrImplementsDeferredClass(
+              mixinName, CompileTimeErrorCode.MIXIN_DEFERRED_CLASS)) {
+            problemReported = true;
+          }
+          if (_checkForMixinDeclaresConstructor(mixinName, mixinElement)) {
+            problemReported = true;
+          }
+          if (!enableSuperMixins &&
+              _checkForMixinInheritsNotFromObject(mixinName, mixinElement)) {
+            problemReported = true;
+          }
+          if (_checkForMixinReferencesSuper(mixinName, mixinElement)) {
+            problemReported = true;
+          }
         }
       }
     }
@@ -1917,9 +1923,9 @@
         : functionType.returnType;
     Expression returnExpression = statement.expression;
     // RETURN_IN_GENERATIVE_CONSTRUCTOR
-    bool isGenerativeConstructor = _enclosingFunction is ConstructorElement &&
-        !(_enclosingFunction as ConstructorElement).isFactory;
-    if (isGenerativeConstructor) {
+    bool isGenerativeConstructor(ExecutableElement element) =>
+        element is ConstructorElement && !element.isFactory;
+    if (isGenerativeConstructor(_enclosingFunction)) {
       if (returnExpression == null) {
         return;
       }
@@ -2008,11 +2014,9 @@
       DartType actualStaticType,
       ErrorCode errorCode) {
     // Warning case: test static type information
-    if (actualStaticType != null &&
-        expectedStaticType != null &&
-        !_typeSystem.isAssignableTo(actualStaticType, expectedStaticType)) {
-      _errorReporter.reportTypeErrorForNode(
-          errorCode, expression, [actualStaticType, expectedStaticType]);
+    if (actualStaticType != null && expectedStaticType != null) {
+      _checkForAssignableExpressionAtType(
+          expression, actualStaticType, expectedStaticType, errorCode);
     }
   }
 
@@ -2092,12 +2096,36 @@
     if (expressionType == null) {
       return;
     }
-    if (_typeSystem.isAssignableTo(expressionType, type)) {
+    if (_expressionIsAssignableAtType(expression, expressionType, type)) {
       return;
     }
     _errorReporter.reportErrorForNode(errorCode, expression, arguments);
   }
 
+  bool _checkForAssignableExpression(
+      Expression expression, DartType expectedStaticType, ErrorCode errorCode) {
+    DartType actualStaticType = getStaticType(expression);
+    return actualStaticType != null &&
+        _checkForAssignableExpressionAtType(
+            expression, actualStaticType, expectedStaticType, errorCode);
+  }
+
+  bool _checkForAssignableExpressionAtType(
+      Expression expression,
+      DartType actualStaticType,
+      DartType expectedStaticType,
+      ErrorCode errorCode) {
+    // TODO(leafp): Move the Downcast functionality here.
+    // TODO(leafp): Support strict downcasts
+    if (!_expressionIsAssignableAtType(
+        expression, actualStaticType, expectedStaticType)) {
+      _errorReporter.reportTypeErrorForNode(
+          errorCode, expression, [actualStaticType, expectedStaticType]);
+      return false;
+    }
+    return true;
+  }
+
   /**
    * Verify that the given [expression] is not final.
    *
@@ -2115,15 +2143,14 @@
         highlightedNode = expression.identifier;
       }
     } else if (expression is PropertyAccess) {
-      PropertyAccess propertyAccess = expression;
-      element = propertyAccess.propertyName.staticElement;
-      highlightedNode = propertyAccess.propertyName;
+      element = expression.propertyName.staticElement;
+      highlightedNode = expression.propertyName;
     }
     // check if element is assignable
-    if (element is PropertyAccessorElement) {
-      PropertyAccessorElement accessor = element as PropertyAccessorElement;
-      element = accessor.variable;
+    Element toVariable(Element element) {
+      return element is PropertyAccessorElement ? element.variable : element;
     }
+    element = toVariable(element);
     if (element is VariableElement) {
       if (element.isConst) {
         _errorReporter.reportErrorForNode(
@@ -2184,8 +2211,7 @@
       // fall-through without statements at all
       AstNode parent = switchCase.parent;
       if (parent is SwitchStatement) {
-        SwitchStatement switchStatement = parent;
-        NodeList<SwitchMember> members = switchStatement.members;
+        NodeList<SwitchMember> members = parent.members;
         int index = members.indexOf(switchCase);
         if (index != -1 && index < members.length - 1) {
           return;
@@ -2454,21 +2480,20 @@
     // this prevents multiple warnings for one issue.
     HashMap<String, ClassMember> memberHashMap =
         new HashMap<String, ClassMember>();
-    for (ClassMember classMember in classMembers) {
-      if (classMember is MethodDeclaration) {
-        MethodDeclaration method = classMember;
-        if (method.isStatic) {
+    for (ClassMember member in classMembers) {
+      if (member is MethodDeclaration) {
+        if (member.isStatic) {
           continue;
         }
         // prepare name
-        SimpleIdentifier name = method.name;
+        SimpleIdentifier name = member.name;
         if (name == null) {
           continue;
         }
         bool addThisMemberToTheMap = true;
-        bool isGetter = method.isGetter;
-        bool isSetter = method.isSetter;
-        bool isOperator = method.isOperator;
+        bool isGetter = member.isGetter;
+        bool isSetter = member.isSetter;
+        bool isOperator = member.isOperator;
         bool isMethod = !isGetter && !isSetter && !isOperator;
         // Do lookups in the enclosing class (and the inherited member) if the
         // member is a method or a setter for
@@ -2512,10 +2537,10 @@
         }
         // Finally, add this member into the HashMap.
         if (addThisMemberToTheMap) {
-          if (method.isSetter) {
-            memberHashMap["${name.name}="] = method;
+          if (member.isSetter) {
+            memberHashMap["${name.name}="] = member;
           } else {
-            memberHashMap[name.name] = method;
+            memberHashMap[name.name] = member;
           }
         }
       }
@@ -2667,14 +2692,13 @@
     // try to find and check super constructor invocation
     for (ConstructorInitializer initializer in constructor.initializers) {
       if (initializer is SuperConstructorInvocation) {
-        SuperConstructorInvocation superInvocation = initializer;
-        ConstructorElement element = superInvocation.staticElement;
+        ConstructorElement element = initializer.staticElement;
         if (element == null || element.isConst) {
           return;
         }
         _errorReporter.reportErrorForNode(
             CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER,
-            superInvocation,
+            initializer,
             [element.enclosingElement.displayName]);
         return;
       }
@@ -2784,7 +2808,7 @@
     if (type.element.isAbstract) {
       ConstructorElement element = expression.staticElement;
       if (element != null && !element.isFactory) {
-        if ((expression.keyword as KeywordToken).keyword == Keyword.CONST) {
+        if (expression.keyword.keyword == Keyword.CONST) {
           _errorReporter.reportErrorForNode(
               StaticWarningCode.CONST_WITH_ABSTRACT_CLASS, typeName);
         } else {
@@ -2910,10 +2934,9 @@
   void _checkForDefaultValueInFunctionTypeAlias(FunctionTypeAlias alias) {
     FormalParameterList formalParameterList = alias.parameters;
     NodeList<FormalParameter> parameters = formalParameterList.parameters;
-    for (FormalParameter formalParameter in parameters) {
-      if (formalParameter is DefaultFormalParameter) {
-        DefaultFormalParameter defaultFormalParameter = formalParameter;
-        if (defaultFormalParameter.defaultValue != null) {
+    for (FormalParameter parameter in parameters) {
+      if (parameter is DefaultFormalParameter) {
+        if (parameter.defaultValue != null) {
           _errorReporter.reportErrorForNode(
               CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS, alias);
         }
@@ -2958,19 +2981,16 @@
       for (int i = 0; i < count; i++) {
         Directive directive = directives[i];
         if (directive is ImportDirective) {
-          ImportDirective importDirective = directive;
-          SimpleIdentifier prefix = importDirective.prefix;
+          SimpleIdentifier prefix = directive.prefix;
           if (prefix != null) {
             Element element = prefix.staticElement;
             if (element is PrefixElement) {
-              PrefixElement prefixElement = element;
-              List<ImportDirective> elements =
-                  prefixToDirectivesMap[prefixElement];
+              List<ImportDirective> elements = prefixToDirectivesMap[element];
               if (elements == null) {
                 elements = new List<ImportDirective>();
-                prefixToDirectivesMap[prefixElement] = elements;
+                prefixToDirectivesMap[element] = elements;
               }
-              elements.add(importDirective);
+              elements.add(directive);
             }
           }
         }
@@ -3259,19 +3279,14 @@
 
   /**
    * Verify that the given constructor field [initializer] has compatible field
-   * and initializer expression types. The [staticElement] is the static element
+   * and initializer expression types. The [fieldElement] is the static element
    * from the name in the [ConstructorFieldInitializer].
    *
    * See [CompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE], and
    * [StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE].
    */
   void _checkForFieldInitializerNotAssignable(
-      ConstructorFieldInitializer initializer, Element staticElement) {
-    // prepare field element
-    if (staticElement is! FieldElement) {
-      return;
-    }
-    FieldElement fieldElement = staticElement as FieldElement;
+      ConstructorFieldInitializer initializer, FieldElement fieldElement) {
     // prepare field type
     DartType fieldType = fieldElement.type;
     // prepare expression type
@@ -3284,7 +3299,7 @@
     if (staticType == null) {
       return;
     }
-    if (_typeSystem.isAssignableTo(staticType, fieldType)) {
+    if (_expressionIsAssignableAtType(expression, staticType, fieldType)) {
       return;
     }
     // report problem
@@ -3425,14 +3440,27 @@
     }
     if (_enclosingFunction.isAsynchronous) {
       if (_enclosingFunction.isGenerator) {
-        if (!_typeSystem.isAssignableTo(
+        if (_options.strongMode) {
+          if (_enclosingFunction.returnType.element !=
+              _typeProvider.streamType.element) {
+            _errorReporter.reportErrorForNode(
+                StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE,
+                returnType);
+          }
+        } else if (!_typeSystem.isAssignableTo(
             _enclosingFunction.returnType, _typeProvider.streamDynamicType)) {
           _errorReporter.reportErrorForNode(
               StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE,
               returnType);
         }
       } else {
-        if (!_typeSystem.isAssignableTo(
+        if (_options.strongMode) {
+          if (_enclosingFunction.returnType.element !=
+              _typeProvider.futureType.element) {
+            _errorReporter.reportErrorForNode(
+                StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, returnType);
+          }
+        } else if (!_typeSystem.isAssignableTo(
             _enclosingFunction.returnType, _typeProvider.futureDynamicType)) {
           _errorReporter.reportErrorForNode(
               StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, returnType);
@@ -3523,23 +3551,20 @@
     }
     // qualified method invocation
     if (parent is MethodInvocation) {
-      MethodInvocation invocation = parent;
-      if (identical(invocation.methodName, identifier) &&
-          invocation.realTarget != null) {
+      if (identical(parent.methodName, identifier) &&
+          parent.realTarget != null) {
         return;
       }
     }
     // qualified property access
     if (parent is PropertyAccess) {
-      PropertyAccess access = parent;
-      if (identical(access.propertyName, identifier) &&
-          access.realTarget != null) {
+      if (identical(parent.propertyName, identifier) &&
+          parent.realTarget != null) {
         return;
       }
     }
     if (parent is PrefixedIdentifier) {
-      PrefixedIdentifier prefixed = parent;
-      if (identical(prefixed.identifier, identifier)) {
+      if (identical(parent.identifier, identifier)) {
         return;
       }
     }
@@ -3626,9 +3651,8 @@
     // Ensure that the inheritance manager has a chance to generate all errors
     // we may care about, note that we ensure that the interfaces data since
     // there are no errors.
-    _inheritanceManager.getMapOfMembersInheritedFromInterfaces(_enclosingClass);
-    HashSet<AnalysisError> errors =
-        _inheritanceManager.getErrors(_enclosingClass);
+    _inheritanceManager.getMembersInheritedFromInterfaces(_enclosingClass);
+    Set<AnalysisError> errors = _inheritanceManager.getErrors(_enclosingClass);
     if (errors == null || errors.isEmpty) {
       return;
     }
@@ -3712,23 +3736,20 @@
     }
     // prepare member Element
     Element element = name.staticElement;
-    if (element is! ExecutableElement) {
-      return;
+    if (element is ExecutableElement) {
+      // OK, top-level element
+      if (element.enclosingElement is! ClassElement) {
+        return;
+      }
+      // OK, instance member
+      if (!element.isStatic) {
+        return;
+      }
+      _errorReporter.reportErrorForNode(
+          StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER,
+          name,
+          [name.name]);
     }
-    ExecutableElement executableElement = element as ExecutableElement;
-    // OK, top-level element
-    if (executableElement.enclosingElement is! ClassElement) {
-      return;
-    }
-    // OK, instance member
-    if (!executableElement.isStatic) {
-      return;
-    }
-
-    _errorReporter.reportErrorForNode(
-        StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER,
-        name,
-        [name.name]);
   }
 
   /**
@@ -3852,13 +3873,8 @@
     DartType leftType = (leftVariableElement == null)
         ? getStaticType(lhs)
         : leftVariableElement.type;
-    DartType staticRightType = getStaticType(rhs);
-    if (!_typeSystem.isAssignableTo(staticRightType, leftType)) {
-      _errorReporter.reportTypeErrorForNode(
-          StaticTypeWarningCode.INVALID_ASSIGNMENT,
-          rhs,
-          [staticRightType, leftType]);
-    }
+    _checkForAssignableExpression(
+        rhs, leftType, StaticTypeWarningCode.INVALID_ASSIGNMENT);
   }
 
   /**
@@ -3900,13 +3916,12 @@
   void _checkForInvalidField(ConstructorFieldInitializer initializer,
       SimpleIdentifier fieldName, Element staticElement) {
     if (staticElement is FieldElement) {
-      FieldElement fieldElement = staticElement;
-      if (fieldElement.isSynthetic) {
+      if (staticElement.isSynthetic) {
         _errorReporter.reportErrorForNode(
             CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD,
             initializer,
             [fieldName]);
-      } else if (fieldElement.isStatic) {
+      } else if (staticElement.isStatic) {
         _errorReporter.reportErrorForNode(
             CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD,
             initializer,
@@ -4071,82 +4086,81 @@
       Declaration accessorDeclaration, String accessorTextName) {
     ExecutableElement accessorElement =
         accessorDeclaration.element as ExecutableElement;
-    if (accessorElement is! PropertyAccessorElement) {
-      return;
-    }
-    PropertyAccessorElement propertyAccessorElement =
-        accessorElement as PropertyAccessorElement;
-    PropertyAccessorElement counterpartAccessor = null;
-    ClassElement enclosingClassForCounterpart = null;
-    if (propertyAccessorElement.isGetter) {
-      counterpartAccessor = propertyAccessorElement.correspondingSetter;
-    } else {
-      counterpartAccessor = propertyAccessorElement.correspondingGetter;
-      // If the setter and getter are in the same enclosing element, return,
-      // this prevents having MISMATCHED_GETTER_AND_SETTER_TYPES reported twice.
-      if (counterpartAccessor != null &&
-          identical(counterpartAccessor.enclosingElement,
-              propertyAccessorElement.enclosingElement)) {
-        return;
-      }
-    }
-    if (counterpartAccessor == null) {
-      // If the accessor is declared in a class, check the superclasses.
-      if (_enclosingClass != null) {
-        // Figure out the correct identifier to lookup in the inheritance graph,
-        // if 'x', then 'x=', or if 'x=', then 'x'.
-        String lookupIdentifier = propertyAccessorElement.name;
-        if (StringUtilities.endsWithChar(lookupIdentifier, 0x3D)) {
-          lookupIdentifier =
-              lookupIdentifier.substring(0, lookupIdentifier.length - 1);
-        } else {
-          lookupIdentifier += "=";
-        }
-        // lookup with the identifier.
-        ExecutableElement elementFromInheritance = _inheritanceManager
-            .lookupInheritance(_enclosingClass, lookupIdentifier);
-        // Verify that we found something, and that it is an accessor
-        if (elementFromInheritance != null &&
-            elementFromInheritance is PropertyAccessorElement) {
-          enclosingClassForCounterpart =
-              elementFromInheritance.enclosingElement as ClassElement;
-          counterpartAccessor = elementFromInheritance;
+    if (accessorElement is PropertyAccessorElement) {
+      PropertyAccessorElement counterpartAccessor = null;
+      ClassElement enclosingClassForCounterpart = null;
+      if (accessorElement.isGetter) {
+        counterpartAccessor = accessorElement.correspondingSetter;
+      } else {
+        counterpartAccessor = accessorElement.correspondingGetter;
+        // If the setter and getter are in the same enclosing element, return,
+        // this prevents having MISMATCHED_GETTER_AND_SETTER_TYPES reported twice.
+        if (counterpartAccessor != null &&
+            identical(counterpartAccessor.enclosingElement,
+                accessorElement.enclosingElement)) {
+          return;
         }
       }
       if (counterpartAccessor == null) {
-        return;
+        // If the accessor is declared in a class, check the superclasses.
+        if (_enclosingClass != null) {
+          // Figure out the correct identifier to lookup in the inheritance graph,
+          // if 'x', then 'x=', or if 'x=', then 'x'.
+          String lookupIdentifier = accessorElement.name;
+          if (StringUtilities.endsWithChar(lookupIdentifier, 0x3D)) {
+            lookupIdentifier =
+                lookupIdentifier.substring(0, lookupIdentifier.length - 1);
+          } else {
+            lookupIdentifier += "=";
+          }
+          // lookup with the identifier.
+          ExecutableElement elementFromInheritance = _inheritanceManager
+              .lookupInheritance(_enclosingClass, lookupIdentifier);
+          // Verify that we found something, and that it is an accessor
+          if (elementFromInheritance != null &&
+              elementFromInheritance is PropertyAccessorElement) {
+            enclosingClassForCounterpart =
+                elementFromInheritance.enclosingElement as ClassElement;
+            counterpartAccessor = elementFromInheritance;
+          }
+        }
+        if (counterpartAccessor == null) {
+          return;
+        }
       }
-    }
-    // Default of null == no accessor or no type (dynamic)
-    DartType getterType = null;
-    DartType setterType = null;
-    // Get an existing counterpart accessor if any.
-    if (propertyAccessorElement.isGetter) {
-      getterType = _getGetterType(propertyAccessorElement);
-      setterType = _getSetterType(counterpartAccessor);
-    } else if (propertyAccessorElement.isSetter) {
-      setterType = _getSetterType(propertyAccessorElement);
-      getterType = _getGetterType(counterpartAccessor);
-    }
-    // If either types are not assignable to each other, report an error
-    // (if the getter is null, it is dynamic which is assignable to everything).
-    if (setterType != null &&
-        getterType != null &&
-        !_typeSystem.isAssignableTo(getterType, setterType)) {
-      if (enclosingClassForCounterpart == null) {
-        _errorReporter.reportTypeErrorForNode(
-            StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES,
-            accessorDeclaration,
-            [accessorTextName, setterType, getterType]);
-      } else {
-        _errorReporter.reportTypeErrorForNode(
-            StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE,
-            accessorDeclaration, [
-          accessorTextName,
-          setterType,
-          getterType,
-          enclosingClassForCounterpart.displayName
-        ]);
+      // Default of null == no accessor or no type (dynamic)
+      DartType getterType = null;
+      DartType setterType = null;
+      // Get an existing counterpart accessor if any.
+      if (accessorElement.isGetter) {
+        getterType = _getGetterType(accessorElement);
+        setterType = _getSetterType(counterpartAccessor);
+      } else if (accessorElement.isSetter) {
+        setterType = _getSetterType(accessorElement);
+        getterType = _getGetterType(counterpartAccessor);
+      }
+      // If either types are not assignable to each other, report an error
+      // (if the getter is null, it is dynamic which is assignable to everything).
+      if (setterType != null &&
+          getterType != null &&
+          !_typeSystem.isAssignableTo(getterType, setterType)) {
+        if (enclosingClassForCounterpart == null) {
+          _errorReporter.reportTypeErrorForNode(
+              StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES,
+              accessorDeclaration,
+              [accessorTextName, setterType, getterType]);
+        } else {
+          _errorReporter.reportTypeErrorForNode(
+              StaticWarningCode
+                  .MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE,
+              accessorDeclaration,
+              [
+                accessorTextName,
+                setterType,
+                getterType,
+                enclosingClassForCounterpart.displayName
+              ]);
+        }
       }
     }
   }
@@ -4165,45 +4179,44 @@
       return;
     }
     Element expressionElement = expressionType.element;
-    if (expressionElement is! ClassElement) {
-      return;
-    }
-    ClassElement classElement = expressionElement as ClassElement;
-    if (!classElement.isEnum) {
-      return;
-    }
-    List<String> constantNames = <String>[];
-    List<FieldElement> fields = classElement.fields;
-    int fieldCount = fields.length;
-    for (int i = 0; i < fieldCount; i++) {
-      FieldElement field = fields[i];
-      if (field.isStatic && !field.isSynthetic) {
-        constantNames.add(field.name);
-      }
-    }
-    NodeList<SwitchMember> members = statement.members;
-    int memberCount = members.length;
-    for (int i = 0; i < memberCount; i++) {
-      SwitchMember member = members[i];
-      if (member is SwitchDefault) {
+    if (expressionElement is ClassElement) {
+      if (!expressionElement.isEnum) {
         return;
       }
-      String constantName = _getConstantName((member as SwitchCase).expression);
-      if (constantName != null) {
-        constantNames.remove(constantName);
+      List<String> constantNames = <String>[];
+      List<FieldElement> fields = expressionElement.fields;
+      int fieldCount = fields.length;
+      for (int i = 0; i < fieldCount; i++) {
+        FieldElement field = fields[i];
+        if (field.isStatic && !field.isSynthetic) {
+          constantNames.add(field.name);
+        }
       }
-    }
-    if (constantNames.isEmpty) {
-      return;
-    }
-    for (int i = 0; i < constantNames.length; i++) {
-      int offset = statement.offset;
-      int end = statement.rightParenthesis.end;
-      _errorReporter.reportErrorForOffset(
-          StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH,
-          offset,
-          end - offset,
-          [constantNames[i]]);
+      NodeList<SwitchMember> members = statement.members;
+      int memberCount = members.length;
+      for (int i = 0; i < memberCount; i++) {
+        SwitchMember member = members[i];
+        if (member is SwitchDefault) {
+          return;
+        }
+        String constantName =
+            _getConstantName((member as SwitchCase).expression);
+        if (constantName != null) {
+          constantNames.remove(constantName);
+        }
+      }
+      if (constantNames.isEmpty) {
+        return;
+      }
+      for (int i = 0; i < constantNames.length; i++) {
+        int offset = statement.offset;
+        int end = statement.rightParenthesis.end;
+        _errorReporter.reportErrorForOffset(
+            StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH,
+            offset,
+            end - offset,
+            [constantNames[i]]);
+      }
     }
   }
 
@@ -4228,10 +4241,16 @@
             String paramName = param.name;
             if (!_containsNamedExpression(argumentList, paramName)) {
               DartObject constantValue = annotation.constantValue;
-              String reason =
-                  constantValue.getField('reason')?.toStringValue() ?? '';
-              _errorReporter.reportErrorForNode(
-                  HintCode.MISSING_REQUIRED_PARAM, node, [paramName, reason]);
+              String reason = constantValue.getField('reason')?.toStringValue();
+              if (reason != null) {
+                _errorReporter.reportErrorForNode(
+                    HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS,
+                    node,
+                    [paramName, reason]);
+              } else {
+                _errorReporter.reportErrorForNode(
+                    HintCode.MISSING_REQUIRED_PARAM, node, [paramName]);
+              }
             }
           }
         }
@@ -4496,14 +4515,13 @@
     // Loop through the set of all executable elements declared in the implicit
     // interface.
     //
-    MemberMap membersInheritedFromInterfaces = _inheritanceManager
-        .getMapOfMembersInheritedFromInterfaces(_enclosingClass);
-    MemberMap membersInheritedFromSuperclasses = _inheritanceManager
-        .getMapOfMembersInheritedFromClasses(_enclosingClass);
-    for (int i = 0; i < membersInheritedFromInterfaces.size; i++) {
-      String memberName = membersInheritedFromInterfaces.getKey(i);
+    Map<String, ExecutableElement> membersInheritedFromInterfaces =
+        _inheritanceManager.getMembersInheritedFromInterfaces(_enclosingClass);
+    Map<String, ExecutableElement> membersInheritedFromSuperclasses =
+        _inheritanceManager.getMembersInheritedFromClasses(_enclosingClass);
+    for (String memberName in membersInheritedFromInterfaces.keys) {
       ExecutableElement executableElt =
-          membersInheritedFromInterfaces.getValue(i);
+          membersInheritedFromInterfaces[memberName];
       if (memberName == null) {
         break;
       }
@@ -4524,7 +4542,7 @@
       }
       // First check to see if this element was declared in the superclass
       // chain, in which case there is already a concrete implementation.
-      ExecutableElement elt = membersInheritedFromSuperclasses.get(memberName);
+      ExecutableElement elt = membersInheritedFromSuperclasses[memberName];
       // Check to see if an element was found in the superclass chain with the
       // correct name.
       if (elt != null) {
@@ -4573,12 +4591,11 @@
     List<String> stringMembersArrayListSet = new List<String>();
     for (int i = 0; i < missingOverridesArray.length; i++) {
       String newStrMember;
-      Element enclosingElement = missingOverridesArray[i].enclosingElement;
+      ExecutableElement element = missingOverridesArray[i];
+      Element enclosingElement = element.enclosingElement;
       String prefix = StringUtilities.EMPTY;
-      if (missingOverridesArray[i] is PropertyAccessorElement) {
-        PropertyAccessorElement propertyAccessorElement =
-            missingOverridesArray[i] as PropertyAccessorElement;
-        if (propertyAccessorElement.isGetter) {
+      if (element is PropertyAccessorElement) {
+        if (element.isGetter) {
           prefix = _GETTER_SPACE;
           // "getter "
         } else {
@@ -4588,9 +4605,9 @@
       }
       if (enclosingElement != null) {
         newStrMember =
-            "$prefix'${enclosingElement.displayName}.${missingOverridesArray[i].displayName}'";
+            "$prefix'${enclosingElement.displayName}.${element.displayName}'";
       } else {
-        newStrMember = "$prefix'${missingOverridesArray[i].displayName}'";
+        newStrMember = "$prefix'${element.displayName}'";
       }
       stringMembersArrayListSet.add(newStrMember);
     }
@@ -4672,9 +4689,8 @@
             StaticTypeWarningCode.NON_BOOL_EXPRESSION, expression);
       }
     } else if (type is FunctionType) {
-      FunctionType functionType = type;
-      if (functionType.typeArguments.length == 0 &&
-          !_typeSystem.isAssignableTo(functionType.returnType, _boolType)) {
+      if (type.typeArguments.length == 0 &&
+          !_typeSystem.isAssignableTo(type.returnType, _boolType)) {
         _errorReporter.reportErrorForNode(
             StaticTypeWarningCode.NON_BOOL_EXPRESSION, expression);
       }
@@ -5060,7 +5076,8 @@
       ]);
       return;
     }
-    if (_typeSystem.isAssignableTo(staticReturnType, expectedReturnType)) {
+    if (_expressionIsAssignableAtType(
+        returnExpression, staticReturnType, expectedReturnType)) {
       return;
     }
     _errorReporter.reportTypeErrorForNode(
@@ -5102,17 +5119,16 @@
     }
     // prepare member Element
     Element element = name.staticElement;
-    if (element is! ExecutableElement) {
-      return;
+    if (element is ExecutableElement) {
+      // OK, static
+      if (element.isStatic) {
+        return;
+      }
+      _errorReporter.reportErrorForNode(
+          StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER,
+          name,
+          [name.name]);
     }
-    ExecutableElement memberElement = element as ExecutableElement;
-    // OK, static
-    if (memberElement.isStatic) {
-      return;
-    }
-
-    _errorReporter.reportErrorForNode(
-        StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, name, [name.name]);
   }
 
   /**
@@ -5138,8 +5154,9 @@
 
     Expression caseExpression = switchCase.expression;
     DartType caseType = getStaticType(caseExpression);
+
     // check types
-    if (!_typeSystem.isAssignableTo(expressionType, caseType)) {
+    if (!_expressionIsAssignableAtType(expression, expressionType, caseType)) {
       _errorReporter.reportErrorForNode(
           StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE,
           expression,
@@ -5190,37 +5207,37 @@
     }
     // prepare ClassElement
     Element element = type.element;
-    if (element is! ClassElement) {
-      return;
-    }
-    ClassElement classElement = element as ClassElement;
-    // prepare type parameters
-    List<DartType> typeParameters = classElement.type.typeArguments;
-    List<TypeParameterElement> boundingElts = classElement.typeParameters;
-    // iterate over each bounded type parameter and corresponding argument
-    NodeList<TypeName> typeNameArgList = typeName.typeArguments.arguments;
-    List<DartType> typeArguments = (type as InterfaceType).typeArguments;
-    int loopThroughIndex =
-        math.min(typeNameArgList.length, boundingElts.length);
+    if (element is ClassElement) {
+      // prepare type parameters
+      List<DartType> typeParameters = element.type.typeArguments;
+      List<TypeParameterElement> boundingElts = element.typeParameters;
+      // iterate over each bounded type parameter and corresponding argument
+      NodeList<TypeName> typeNameArgList = typeName.typeArguments.arguments;
+      List<DartType> typeArguments = (type as InterfaceType).typeArguments;
+      int loopThroughIndex =
+          math.min(typeNameArgList.length, boundingElts.length);
 
-    for (int i = 0; i < loopThroughIndex; i++) {
-      TypeName argTypeName = typeNameArgList[i];
-      DartType argType = argTypeName.type;
-      DartType boundType = boundingElts[i].bound;
-      if (argType != null && boundType != null) {
-        if (typeArguments.length != 0 &&
-            typeArguments.length == typeParameters.length) {
-          boundType = boundType.substitute2(typeArguments, typeParameters);
-        }
-        if (!_typeSystem.isSubtypeOf(argType, boundType)) {
-          ErrorCode errorCode;
-          if (_isInConstInstanceCreation) {
-            errorCode = CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS;
-          } else {
-            errorCode = StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS;
+      for (int i = 0; i < loopThroughIndex; i++) {
+        TypeName argTypeName = typeNameArgList[i];
+        DartType argType = argTypeName.type;
+        DartType boundType = boundingElts[i].bound;
+        if (argType != null && boundType != null) {
+          if (typeArguments.length != 0 &&
+              typeArguments.length == typeParameters.length) {
+            boundType = boundType.substitute2(typeArguments, typeParameters);
           }
-          _errorReporter.reportTypeErrorForNode(
-              errorCode, argTypeName, [argType, boundType]);
+          if (!_typeSystem.isSubtypeOf(argType, boundType)) {
+            ErrorCode errorCode;
+            if (_isInConstInstanceCreation) {
+              errorCode =
+                  CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS;
+            } else {
+              errorCode =
+                  StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS;
+            }
+            _errorReporter.reportTypeErrorForNode(
+                errorCode, argTypeName, [argType, boundType]);
+          }
         }
       }
     }
@@ -5380,8 +5397,7 @@
       } else {
         ParameterElement parameterElement = parameter.element;
         if (parameterElement is FieldFormalParameterElementImpl) {
-          FieldFormalParameterElementImpl fieldFormal = parameterElement;
-          DartType declaredType = fieldFormal.type;
+          DartType declaredType = parameterElement.type;
           DartType fieldType = fieldElement.type;
           if (fieldElement.isSynthetic) {
             _errorReporter.reportErrorForNode(
@@ -5545,11 +5561,8 @@
       impliedReturnType =
           _typeProvider.iterableType.instantiate(<DartType>[staticYieldedType]);
     }
-    if (!_typeSystem.isAssignableTo(impliedReturnType, declaredReturnType)) {
-      _errorReporter.reportTypeErrorForNode(
-          StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
-          yieldExpression,
-          [impliedReturnType, declaredReturnType]);
+    if (!_checkForAssignableExpressionAtType(yieldExpression, impliedReturnType,
+        declaredReturnType, StaticTypeWarningCode.YIELD_OF_INVALID_TYPE)) {
       return;
     }
     if (isYieldEach) {
@@ -5663,6 +5676,19 @@
     return false;
   }
 
+  bool _expressionIsAssignableAtType(Expression expression,
+      DartType actualStaticType, DartType expectedStaticType) {
+    bool concrete =
+        _options.strongMode && StaticInfo.isKnownFunction(expression);
+    if (concrete) {
+      actualStaticType =
+          _typeSystem.typeToConcreteType(_typeProvider, actualStaticType);
+      // TODO(leafp): Move the Downcast functionality here.
+      // TODO(leafp): Support strict downcasts
+    }
+    return _typeSystem.isAssignableTo(actualStaticType, expectedStaticType);
+  }
+
   MethodElement _findOverriddenMemberThatMustCallSuper(MethodDeclaration node) {
     ExecutableElement overriddenMember = _getOverriddenMember(node.element);
     List<ExecutableElement> seen = <ExecutableElement>[];
@@ -5781,6 +5807,12 @@
    * indirectly.
    */
   bool _hasRedirectingFactoryConstructorCycle(ConstructorElement constructor) {
+    ConstructorElement nonMember(ConstructorElement constructor) {
+      return constructor is ConstructorMember
+          ? constructor.baseElement
+          : constructor;
+    }
+
     Set<ConstructorElement> constructors = new HashSet<ConstructorElement>();
     ConstructorElement current = constructor;
     while (current != null) {
@@ -5788,10 +5820,7 @@
         return identical(current, constructor);
       }
       constructors.add(current);
-      current = current.redirectedConstructor;
-      if (current is ConstructorMember) {
-        current = (current as ConstructorMember).baseElement;
-      }
+      current = nonMember(current.redirectedConstructor);
     }
     return false;
   }
@@ -5866,22 +5895,21 @@
     String executableName = executableElement.name;
     if (executableElement is MethodElement) {
       foundElt = classElement.getMethod(executableName);
-      if (foundElt != null && !(foundElt as MethodElement).isAbstract) {
+      if (foundElt != null && !foundElt.isAbstract) {
         return true;
       }
       List<InterfaceType> mixins = classElement.mixins;
       for (int i = 0; i < mixins.length && foundElt == null; i++) {
         foundElt = mixins[i].getMethod(executableName);
       }
-      if (foundElt != null && !(foundElt as MethodElement).isAbstract) {
+      if (foundElt != null && !foundElt.isAbstract) {
         return true;
       }
     } else if (executableElement is PropertyAccessorElement) {
-      PropertyAccessorElement propertyAccessorElement = executableElement;
-      if (propertyAccessorElement.isGetter) {
+      if (executableElement.isGetter) {
         foundElt = classElement.getGetter(executableName);
       }
-      if (foundElt == null && propertyAccessorElement.isSetter) {
+      if (foundElt == null && executableElement.isSetter) {
         foundElt = classElement.getSetter(executableName);
       }
       if (foundElt != null &&
@@ -5895,8 +5923,7 @@
           foundElt = mixins[i].getSetter(executableName);
         }
       }
-      if (foundElt != null &&
-          !(foundElt as PropertyAccessorElement).isAbstract) {
+      if (foundElt != null && !foundElt.isAbstract) {
         return true;
       }
     }
@@ -5910,14 +5937,11 @@
     for (AstNode node = expression.parent; node != null; node = node.parent) {
       if (node is CompilationUnit) {
         return false;
-      }
-      if (node is ConstructorDeclaration) {
+      } else if (node is ConstructorDeclaration) {
         return node.factoryKeyword == null;
-      }
-      if (node is ConstructorInitializer) {
+      } else if (node is ConstructorInitializer) {
         return false;
-      }
-      if (node is MethodDeclaration) {
+      } else if (node is MethodDeclaration) {
         return !node.isStatic;
       }
     }
@@ -6101,8 +6125,7 @@
     toCheck.add(type.element);
     // type arguments
     if (type is InterfaceType) {
-      InterfaceType interfaceType = type;
-      for (DartType typeArgument in interfaceType.typeArguments) {
+      for (DartType typeArgument in type.typeArguments) {
         _addTypeToCheck(typeArgument);
       }
     }
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index 9ed4477..2b98d4a 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -18,6 +18,7 @@
 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/resolver/inheritance_manager.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/constant.dart';
@@ -422,8 +423,9 @@
         (node.parent as VariableDeclarationList).type, element.type);
     // matches, restore the existing element
     node.name.staticElement = element;
-    if (element is VariableElementImpl) {
-      (element as VariableElementImpl).initializer = newElement.initializer;
+    Element variable = element;
+    if (variable is VariableElementImpl) {
+      variable.initializer = newElement.initializer;
     }
   }
 
@@ -1622,7 +1624,6 @@
       RecordingErrorListener errorListener = new RecordingErrorListener();
       Parser parser = new Parser(_unitSource, errorListener);
       AnalysisOptions options = _unitElement.context.analysisOptions;
-      parser.parseConditionalDirectives = options.enableConditionalDirectives;
       parser.parseGenericMethods = options.enableGenericMethods;
       CompilationUnit unit = parser.parseCompilationUnit(token);
       _newParseErrors = errorListener.errors;
@@ -1686,9 +1687,9 @@
           setElementDocumentationComment(parentElement, parent);
         } else if (parentElement == null && parent is FieldDeclaration) {
           for (VariableDeclaration field in parent.fields.variables) {
-            if (field.element is ElementImpl) {
-              setElementDocumentationComment(
-                  field.element as ElementImpl, parent);
+            Element fieldElement = field.element;
+            if (fieldElement is ElementImpl) {
+              setElementDocumentationComment(fieldElement, parent);
             }
           }
         }
@@ -1866,7 +1867,7 @@
   static Token _getBeginTokenNotComment(AstNode node) {
     Token oldBeginToken = node.beginToken;
     if (oldBeginToken is CommentToken) {
-      oldBeginToken = (oldBeginToken as CommentToken).parent;
+      return oldBeginToken.parent;
     }
     return oldBeginToken;
   }
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 32afd15..98a26e9 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -15,8 +15,7 @@
 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/engine.dart' show AnalysisEngine;
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/generated/shared_messages.dart'
     as shared_messages;
@@ -1833,7 +1832,7 @@
     ResolutionCopier.copyResolutionData(oldNode, newNode);
     IncrementalAstCloner cloner =
         new IncrementalAstCloner(oldNode, newNode, _tokenMap);
-    return originalStructure.accept(cloner) as AstNode;
+    return originalStructure.accept(cloner);
   }
 
   /**
@@ -2169,12 +2168,6 @@
   bool _inInitializer = false;
 
   /**
-   * A flag indicating whether the parser is to parse conditional directives
-   * syntax.
-   */
-  bool parseConditionalDirectives = false;
-
-  /**
    * A flag indicating whether the parser is to parse generic method syntax.
    */
   bool parseGenericMethods = false;
@@ -2217,6 +2210,12 @@
     this._parseAsync = parseAsync;
   }
 
+  @deprecated
+  bool get parseConditionalDirectives => true;
+
+  @deprecated
+  void set parseConditionalDirectives(bool value) {}
+
   /**
    * Set whether parser is to parse function bodies.
    */
@@ -2414,7 +2413,7 @@
         return _parseOperator(
             commentAndMetadata, modifiers.externalKeyword, returnType);
       } else if (_matchesIdentifier() &&
-          _peek().matchesAny([
+          _peek().matchesAny(const <TokenType>[
             TokenType.OPEN_PAREN,
             TokenType.OPEN_CURLY_BRACKET,
             TokenType.FUNCTION,
@@ -2428,8 +2427,11 @@
         // We have found an error of some kind. Try to recover.
         //
         if (_matchesIdentifier()) {
-          if (_peek().matchesAny(
-              [TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) {
+          if (_peek().matchesAny(const <TokenType>[
+            TokenType.EQ,
+            TokenType.COMMA,
+            TokenType.SEMICOLON
+          ])) {
             //
             // We appear to have a variable declaration with a type of "void".
             //
@@ -2587,8 +2589,11 @@
           methodName,
           typeParameters,
           parameters);
-    } else if (_peek()
-        .matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) {
+    } else if (_peek().matchesAny(const <TokenType>[
+      TokenType.EQ,
+      TokenType.COMMA,
+      TokenType.SEMICOLON
+    ])) {
       if (modifiers.constKeyword == null &&
           modifiers.finalKeyword == null &&
           modifiers.varKeyword == null) {
@@ -3038,18 +3043,14 @@
     // better.
     //
     List<FormalParameter> parameters = new List<FormalParameter>();
-    List<FormalParameter> normalParameters = new List<FormalParameter>();
-    List<FormalParameter> positionalParameters = new List<FormalParameter>();
-    List<FormalParameter> namedParameters = new List<FormalParameter>();
-    List<FormalParameter> currentParameters = normalParameters;
     Token leftSquareBracket = null;
     Token rightSquareBracket = null;
     Token leftCurlyBracket = null;
     Token rightCurlyBracket = null;
     ParameterKind kind = ParameterKind.REQUIRED;
     bool firstParameter = true;
-    bool reportedMuliplePositionalGroups = false;
-    bool reportedMulipleNamedGroups = false;
+    bool reportedMultiplePositionalGroups = false;
+    bool reportedMultipleNamedGroups = false;
     bool reportedMixedGroups = false;
     bool wasOptionalParameter = false;
     Token initialToken = null;
@@ -3074,31 +3075,29 @@
       //
       if (_matches(TokenType.OPEN_SQUARE_BRACKET)) {
         wasOptionalParameter = true;
-        if (leftSquareBracket != null && !reportedMuliplePositionalGroups) {
+        if (leftSquareBracket != null && !reportedMultiplePositionalGroups) {
           _reportErrorForCurrentToken(
               ParserErrorCode.MULTIPLE_POSITIONAL_PARAMETER_GROUPS);
-          reportedMuliplePositionalGroups = true;
+          reportedMultiplePositionalGroups = true;
         }
         if (leftCurlyBracket != null && !reportedMixedGroups) {
           _reportErrorForCurrentToken(ParserErrorCode.MIXED_PARAMETER_GROUPS);
           reportedMixedGroups = true;
         }
         leftSquareBracket = getAndAdvance();
-        currentParameters = positionalParameters;
         kind = ParameterKind.POSITIONAL;
       } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
         wasOptionalParameter = true;
-        if (leftCurlyBracket != null && !reportedMulipleNamedGroups) {
+        if (leftCurlyBracket != null && !reportedMultipleNamedGroups) {
           _reportErrorForCurrentToken(
               ParserErrorCode.MULTIPLE_NAMED_PARAMETER_GROUPS);
-          reportedMulipleNamedGroups = true;
+          reportedMultipleNamedGroups = true;
         }
         if (leftSquareBracket != null && !reportedMixedGroups) {
           _reportErrorForCurrentToken(ParserErrorCode.MIXED_PARAMETER_GROUPS);
           reportedMixedGroups = true;
         }
         leftCurlyBracket = getAndAdvance();
-        currentParameters = namedParameters;
         kind = ParameterKind.NAMED;
       }
       //
@@ -3106,7 +3105,6 @@
       //
       FormalParameter parameter = _parseFormalParameter(kind);
       parameters.add(parameter);
-      currentParameters.add(parameter);
       if (kind == ParameterKind.REQUIRED && wasOptionalParameter) {
         _reportErrorForNode(
             ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, parameter);
@@ -3118,7 +3116,6 @@
       // mismatched delimiters.
       if (_matches(TokenType.CLOSE_SQUARE_BRACKET)) {
         rightSquareBracket = getAndAdvance();
-        currentParameters = normalParameters;
         if (leftSquareBracket == null) {
           if (leftCurlyBracket != null) {
             _reportErrorForCurrentToken(
@@ -3134,7 +3131,6 @@
         kind = ParameterKind.REQUIRED;
       } else if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
         rightCurlyBracket = getAndAdvance();
-        currentParameters = normalParameters;
         if (leftCurlyBracket == null) {
           if (leftSquareBracket != null) {
             _reportErrorForCurrentToken(
@@ -3447,12 +3443,17 @@
    *         label* nonLabeledStatement
    */
   Statement parseStatement2() {
-    List<Label> labels = new List<Label>();
+    List<Label> labels = null;
     while (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) {
-      labels.add(parseLabel(isDeclaration: true));
+      Label label = parseLabel(isDeclaration: true);
+      if (labels == null) {
+        labels = <Label>[label];
+      } else {
+        labels.add(label);
+      }
     }
     Statement statement = _parseNonLabeledStatement();
-    if (labels.isEmpty) {
+    if (labels == null) {
       return statement;
     }
     return new LabeledStatement(labels, statement);
@@ -4072,8 +4073,8 @@
     if (afterParameters == null) {
       return false;
     }
-    if (afterParameters
-        .matchesAny([TokenType.OPEN_CURLY_BRACKET, TokenType.FUNCTION])) {
+    if (afterParameters.matchesAny(
+        const <TokenType>[TokenType.OPEN_CURLY_BRACKET, TokenType.FUNCTION])) {
       return true;
     }
     String lexeme = afterParameters.lexeme;
@@ -4121,7 +4122,7 @@
     if (_matchesKeyword(Keyword.CONST)) {
       // Look to see whether we might be at the start of a list or map literal,
       // otherwise this should be the start of a variable declaration.
-      return !_peek().matchesAny([
+      return !_peek().matchesAny(const <TokenType>[
         TokenType.LT,
         TokenType.OPEN_CURLY_BRACKET,
         TokenType.OPEN_SQUARE_BRACKET,
@@ -4258,11 +4259,8 @@
         _tokenMatches(token.next, TokenType.COLON)) {
       token = token.next.next;
     }
-    if (token.type == TokenType.KEYWORD) {
-      Keyword keyword = (token as KeywordToken).keyword;
-      return keyword == Keyword.CASE || keyword == Keyword.DEFAULT;
-    }
-    return false;
+    Keyword keyword = token.keyword;
+    return keyword == Keyword.CASE || keyword == Keyword.DEFAULT;
   }
 
   /**
@@ -4467,21 +4465,24 @@
       while (_isLikelyArgumentList()) {
         TypeArgumentList typeArguments = _parseOptionalTypeArguments();
         ArgumentList argumentList = parseArgumentList();
-        if (expression is SimpleIdentifier) {
-          expression = new MethodInvocation(null, null,
-              expression as SimpleIdentifier, typeArguments, argumentList);
-        } else if (expression is PrefixedIdentifier) {
-          PrefixedIdentifier identifier = expression as PrefixedIdentifier;
+        Expression currentExpression = expression;
+        if (currentExpression is SimpleIdentifier) {
           expression = new MethodInvocation(
-              identifier.prefix,
-              identifier.period,
-              identifier.identifier,
+              null, null, currentExpression, typeArguments, argumentList);
+        } else if (currentExpression is PrefixedIdentifier) {
+          expression = new MethodInvocation(
+              currentExpression.prefix,
+              currentExpression.period,
+              currentExpression.identifier,
               typeArguments,
               argumentList);
-        } else if (expression is PropertyAccess) {
-          PropertyAccess access = expression as PropertyAccess;
-          expression = new MethodInvocation(access.target, access.operator,
-              access.propertyName, typeArguments, argumentList);
+        } else if (currentExpression is PropertyAccess) {
+          expression = new MethodInvocation(
+              currentExpression.target,
+              currentExpression.operator,
+              currentExpression.propertyName,
+              typeArguments,
+              argumentList);
         } else {
           expression = new FunctionExpressionInvocation(
               expression, typeArguments, argumentList);
@@ -4703,12 +4704,12 @@
         progress = true;
         while (_isLikelyArgumentList()) {
           TypeArgumentList typeArguments = _parseOptionalTypeArguments();
-          if (expression is PropertyAccess) {
-            PropertyAccess propertyAccess = expression as PropertyAccess;
+          Expression currentExpression = expression;
+          if (currentExpression is PropertyAccess) {
             expression = new MethodInvocation(
-                propertyAccess.target,
-                propertyAccess.operator,
-                propertyAccess.propertyName,
+                currentExpression.target,
+                currentExpression.operator,
+                currentExpression.propertyName,
                 typeArguments,
                 parseArgumentList());
           } else {
@@ -4986,14 +4987,16 @@
    */
   CommentAndMetadata _parseCommentAndMetadata() {
     Comment comment = _parseDocumentationComment();
-    List<Annotation> metadata = new List<Annotation>();
+    List<Annotation> metadata = null;
     while (_matches(TokenType.AT)) {
+      metadata ??= new List<Annotation>();
       metadata.add(parseAnnotation());
       Comment optionalComment = _parseDocumentationComment();
       if (optionalComment != null) {
         comment = optionalComment;
       }
     }
+    metadata ??= const <Annotation>[];
     return new CommentAndMetadata(comment, metadata);
   }
 
@@ -5180,7 +5183,7 @@
         return _convertToFunctionDeclaration(_parseOperator(
             commentAndMetadata, modifiers.externalKeyword, returnType));
       } else if (_matchesIdentifier() &&
-          _peek().matchesAny([
+          _peek().matchesAny(const <TokenType>[
             TokenType.OPEN_PAREN,
             TokenType.OPEN_CURLY_BRACKET,
             TokenType.FUNCTION,
@@ -5194,8 +5197,11 @@
         // We have found an error of some kind. Try to recover.
         //
         if (_matchesIdentifier()) {
-          if (_peek().matchesAny(
-              [TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) {
+          if (_peek().matchesAny(const <TokenType>[
+            TokenType.EQ,
+            TokenType.COMMA,
+            TokenType.SEMICOLON
+          ])) {
             //
             // We appear to have a variable declaration with a type of "void".
             //
@@ -5253,8 +5259,11 @@
       _validateModifiersForTopLevelFunction(modifiers);
       return _parseFunctionDeclaration(
           commentAndMetadata, modifiers.externalKeyword, returnType);
-    } else if (_peek()
-        .matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) {
+    } else if (_peek().matchesAny(const <TokenType>[
+      TokenType.EQ,
+      TokenType.COMMA,
+      TokenType.SEMICOLON
+    ])) {
       if (modifiers.constKeyword == null &&
           modifiers.finalKeyword == null &&
           modifiers.varKeyword == null) {
@@ -5304,7 +5313,7 @@
           new VariableDeclarationList(null, null, null, returnType, variables),
           semicolon);
     }
-    if (_peek().matchesAny([
+    if (_peek().matchesAny(const <TokenType>[
       TokenType.OPEN_PAREN,
       TokenType.FUNCTION,
       TokenType.OPEN_CURLY_BRACKET,
@@ -5360,10 +5369,8 @@
    */
   List<Configuration> _parseConfigurations() {
     List<Configuration> configurations = <Configuration>[];
-    if (parseConditionalDirectives) {
-      while (_matchesKeyword(Keyword.IF)) {
-        configurations.add(_parseConfiguration());
-      }
+    while (_matchesKeyword(Keyword.IF)) {
+      configurations.add(_parseConfiguration());
     }
     return configurations;
   }
@@ -6288,7 +6295,7 @@
         _parseFunctionDeclaration(commentAndMetadata, null, returnType);
     Token propertyKeyword = declaration.propertyKeyword;
     if (propertyKeyword != null) {
-      if ((propertyKeyword as KeywordToken).keyword == Keyword.GET) {
+      if (propertyKeyword.keyword == Keyword.GET) {
         _reportErrorForToken(
             ParserErrorCode.GETTER_IN_FUNCTION, propertyKeyword);
       } else {
@@ -7023,8 +7030,8 @@
       }
       return parseBlock();
     } else if (_matches(TokenType.KEYWORD) &&
-        !(_currentToken as KeywordToken).keyword.isPseudoKeyword) {
-      Keyword keyword = (_currentToken as KeywordToken).keyword;
+        !_currentToken.keyword.isPseudoKeyword) {
+      Keyword keyword = _currentToken.keyword;
       // TODO(jwren) compute some metrics to figure out a better order for this
       // if-then sequence to optimize performance
       if (keyword == Keyword.ASSERT) {
@@ -7059,7 +7066,7 @@
       } else if (keyword == Keyword.VOID) {
         TypeName returnType = parseReturnType();
         if (_matchesIdentifier() &&
-            _peek().matchesAny([
+            _peek().matchesAny(const <TokenType>[
               TokenType.OPEN_PAREN,
               TokenType.OPEN_CURLY_BRACKET,
               TokenType.FUNCTION,
@@ -7072,8 +7079,11 @@
           // We have found an error of some kind. Try to recover.
           //
           if (_matchesIdentifier()) {
-            if (_peek().matchesAny(
-                [TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) {
+            if (_peek().matchesAny(const <TokenType>[
+              TokenType.EQ,
+              TokenType.COMMA,
+              TokenType.SEMICOLON
+            ])) {
               //
               // We appear to have a variable declaration with a type of "void".
               //
@@ -7094,7 +7104,7 @@
           return new EmptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
         }
       } else if (keyword == Keyword.CONST) {
-        if (_peek().matchesAny([
+        if (_peek().matchesAny(const <TokenType>[
           TokenType.LT,
           TokenType.OPEN_CURLY_BRACKET,
           TokenType.OPEN_SQUARE_BRACKET,
@@ -7323,10 +7333,14 @@
         if (_isLikelyArgumentList()) {
           TypeArgumentList typeArguments = _parseOptionalTypeArguments();
           ArgumentList argumentList = parseArgumentList();
-          if (operand is PropertyAccess) {
-            PropertyAccess access = operand as PropertyAccess;
-            operand = new MethodInvocation(access.target, access.operator,
-                access.propertyName, typeArguments, argumentList);
+          Expression currentOperand = operand;
+          if (currentOperand is PropertyAccess) {
+            operand = new MethodInvocation(
+                currentOperand.target,
+                currentOperand.operator,
+                currentOperand.propertyName,
+                typeArguments,
+                argumentList);
           } else {
             operand = new FunctionExpressionInvocation(
                 operand, typeArguments, argumentList);
@@ -8483,14 +8497,15 @@
     // Look to see whether the token after the open parenthesis is something
     // that should only occur at the beginning of a parameter list.
     //
-    if (next.matchesAny([
+    if (next.matchesAny(const <TokenType>[
           TokenType.AT,
           TokenType.OPEN_SQUARE_BRACKET,
           TokenType.OPEN_CURLY_BRACKET
         ]) ||
         _tokenMatchesKeyword(next, Keyword.VOID) ||
         (_tokenMatchesIdentifier(next) &&
-            (next.next.matchesAny([TokenType.COMMA, TokenType.CLOSE_PAREN])))) {
+            (next.next.matchesAny(
+                const <TokenType>[TokenType.COMMA, TokenType.CLOSE_PAREN])))) {
       return _skipPastMatchingToken(startToken);
     }
     //
@@ -8501,8 +8516,8 @@
         _tokenMatches(next.next, TokenType.OPEN_PAREN)) {
       Token afterParameters = _skipFormalParameterList(next.next);
       if (afterParameters != null &&
-          (afterParameters
-              .matchesAny([TokenType.COMMA, TokenType.CLOSE_PAREN]))) {
+          afterParameters.matchesAny(
+              const <TokenType>[TokenType.COMMA, TokenType.CLOSE_PAREN])) {
         return _skipPastMatchingToken(startToken);
       }
     }
@@ -8833,15 +8848,13 @@
    * Return `true` if the given [token] matches the given [keyword].
    */
   bool _tokenMatchesKeyword(Token token, Keyword keyword) =>
-      token.type == TokenType.KEYWORD &&
-      (token as KeywordToken).keyword == keyword;
+      token.keyword == keyword;
 
   /**
    * Return `true` if the given [token] matches a pseudo keyword.
    */
   bool _tokenMatchesPseudoKeyword(Token token) =>
-      _tokenMatches(token, TokenType.KEYWORD) &&
-      (token as KeywordToken).keyword.isPseudoKeyword;
+      token.keyword?.isPseudoKeyword ?? false;
 
   /**
    * Return `true` if the given [token] matches the given [identifier].
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 3f1c0ed..3b06ea0 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -13,12 +13,12 @@
 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';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/utilities.dart';
+import 'package:analyzer/src/dart/resolver/inheritance_manager.dart';
+import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/element_resolver.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -33,6 +33,8 @@
 import 'package:analyzer/src/task/strong/info.dart'
     show InferredType, StaticInfo;
 
+export 'package:analyzer/src/dart/resolver/inheritance_manager.dart';
+export 'package:analyzer/src/dart/resolver/scope.dart';
 export 'package:analyzer/src/generated/type_system.dart';
 
 /**
@@ -519,10 +521,12 @@
       if (element == null) {
         return false;
       } else if (element is PropertyAccessorElement && element.isSynthetic) {
-        element = (element as PropertyAccessorElement).variable;
-        if (element == null) {
+        // TODO(brianwilkerson) Why isn't this the implementation for PropertyAccessorElement?
+        Element variable = element.variable;
+        if (variable == null) {
           return false;
         }
+        return variable.isDeprecated;
       }
       return element.isDeprecated;
     }
@@ -532,10 +536,9 @@
         // TODO(jwren) We should modify ConstructorElement.getDisplayName(),
         // or have the logic centralized elsewhere, instead of doing this logic
         // here.
-        ConstructorElement constructorElement = element;
-        displayName = constructorElement.enclosingElement.displayName;
-        if (!constructorElement.displayName.isEmpty) {
-          displayName = "$displayName.${constructorElement.displayName}";
+        displayName = element.enclosingElement.displayName;
+        if (!element.displayName.isEmpty) {
+          displayName = "$displayName.${element.displayName}";
         }
       }
       _errorReporter.reportErrorForNode(
@@ -596,16 +599,16 @@
       return false;
     }
     // Report error if the (x/y) has toInt() invoked on it
-    if (node.parent is ParenthesizedExpression) {
+    AstNode parent = node.parent;
+    if (parent is ParenthesizedExpression) {
       ParenthesizedExpression parenthesizedExpression =
-          _wrapParenthesizedExpression(node.parent as ParenthesizedExpression);
-      if (parenthesizedExpression.parent is MethodInvocation) {
-        MethodInvocation methodInvocation =
-            parenthesizedExpression.parent as MethodInvocation;
-        if (_TO_INT_METHOD_NAME == methodInvocation.methodName.name &&
-            methodInvocation.argumentList.arguments.isEmpty) {
+          _wrapParenthesizedExpression(parent);
+      AstNode grandParent = parenthesizedExpression.parent;
+      if (grandParent is MethodInvocation) {
+        if (_TO_INT_METHOD_NAME == grandParent.methodName.name &&
+            grandParent.argumentList.arguments.isEmpty) {
           _errorReporter.reportErrorForNode(
-              HintCode.DIVISION_OPTIMIZATION, methodInvocation);
+              HintCode.DIVISION_OPTIMIZATION, grandParent);
           return true;
         }
       }
@@ -750,38 +753,34 @@
    * @return `true` if and only if a hint code is generated on the passed node
    * See [HintCode.MISSING_RETURN].
    */
-  bool _checkForMissingReturn(TypeName returnType, FunctionBody body) {
+  void _checkForMissingReturn(TypeName returnType, FunctionBody body) {
     // Check that the method or function has a return type, and a function body
     if (returnType == null || body == null) {
-      return false;
+      return;
     }
     // Check that the body is a BlockFunctionBody
-    if (body is! BlockFunctionBody) {
-      return false;
+    if (body is BlockFunctionBody) {
+      // Generators are never required to have a return statement.
+      if (body.isGenerator) {
+        return;
+      }
+      // Check that the type is resolvable, and is not "void"
+      DartType returnTypeType = returnType.type;
+      if (returnTypeType == null || returnTypeType.isVoid) {
+        return;
+      }
+      // For async, give no hint if Future<Null> is assignable to the return
+      // type.
+      if (body.isAsynchronous &&
+          _typeSystem.isAssignableTo(_futureNullType, returnTypeType)) {
+        return;
+      }
+      // Check the block for a return statement, if not, create the hint
+      if (!ExitDetector.exits(body)) {
+        _errorReporter.reportErrorForNode(
+            HintCode.MISSING_RETURN, returnType, [returnTypeType.displayName]);
+      }
     }
-    // Generators are never required to have a return statement.
-    if (body.isGenerator) {
-      return false;
-    }
-    // Check that the type is resolvable, and is not "void"
-    DartType returnTypeType = returnType.type;
-    if (returnTypeType == null || returnTypeType.isVoid) {
-      return false;
-    }
-    // For async, give no hint if Future<Null> is assignable to the return
-    // type.
-    if (body.isAsynchronous &&
-        _typeSystem.isAssignableTo(_futureNullType, returnTypeType)) {
-      return false;
-    }
-    // Check the block for a return statement, if not, create the hint
-    BlockFunctionBody blockFunctionBody = body as BlockFunctionBody;
-    if (!ExitDetector.exits(blockFunctionBody)) {
-      _errorReporter.reportErrorForNode(
-          HintCode.MISSING_RETURN, returnType, [returnTypeType.displayName]);
-      return true;
-    }
-    return false;
   }
 
   /**
@@ -972,28 +971,22 @@
 //  }
 
   /**
-   * Check for situations where the result of a method or function is used, when it returns 'void'.
+   * Check for situations where the result of a method or function is used, when
+   * it returns 'void'.
    *
-   * TODO(jwren) Many other situations of use could be covered. We currently cover the cases var x =
-   * m() and x = m(), but we could also cover cases such as m().x, m()[k], a + m(), f(m()), return
-   * m().
-   *
-   * @param node expression on the RHS of some assignment
-   * @return `true` if and only if a hint code is generated on the passed node
    * See [HintCode.USE_OF_VOID_RESULT].
    */
-  bool _checkForUseOfVoidResult(Expression expression) {
-    if (expression == null || expression is! MethodInvocation) {
-      return false;
+  void _checkForUseOfVoidResult(Expression expression) {
+    // TODO(jwren) Many other situations of use could be covered. We currently
+    // cover the cases var x = m() and x = m(), but we could also cover cases
+    // such as m().x, m()[k], a + m(), f(m()), return m().
+    if (expression is MethodInvocation) {
+      if (identical(expression.staticType, VoidTypeImpl.instance)) {
+        SimpleIdentifier methodName = expression.methodName;
+        _errorReporter.reportErrorForNode(
+            HintCode.USE_OF_VOID_RESULT, methodName, [methodName.name]);
+      }
     }
-    MethodInvocation methodInvocation = expression as MethodInvocation;
-    if (identical(methodInvocation.staticType, VoidTypeImpl.instance)) {
-      SimpleIdentifier methodName = methodInvocation.methodName;
-      _errorReporter.reportErrorForNode(
-          HintCode.USE_OF_VOID_RESULT, methodName, [methodName.name]);
-      return true;
-    }
-    return false;
   }
 
   bool _hasSuperClassOrMixin(ClassElement element, InterfaceType type) {
@@ -1027,9 +1020,9 @@
    */
   static ParenthesizedExpression _wrapParenthesizedExpression(
       ParenthesizedExpression parenthesizedExpression) {
-    if (parenthesizedExpression.parent is ParenthesizedExpression) {
-      return _wrapParenthesizedExpression(
-          parenthesizedExpression.parent as ParenthesizedExpression);
+    AstNode parent = parenthesizedExpression.parent;
+    if (parent is ParenthesizedExpression) {
+      return _wrapParenthesizedExpression(parent);
     }
     return parenthesizedExpression;
   }
@@ -1093,61 +1086,6 @@
 }
 
 /**
- * Instances of the class `ClassScope` implement the scope defined by a class.
- */
-class ClassScope extends EnclosedScope {
-  /**
-   * Initialize a newly created scope enclosed within another scope.
-   *
-   * @param enclosingScope the scope in which this scope is lexically enclosed
-   * @param typeElement the element representing the type represented by this scope
-   */
-  ClassScope(Scope enclosingScope, ClassElement typeElement)
-      : super(enclosingScope) {
-    if (typeElement == null) {
-      throw new IllegalArgumentException("class element cannot be null");
-    }
-    _defineMembers(typeElement);
-  }
-
-  @override
-  AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
-    if (existing is PropertyAccessorElement && duplicate is MethodElement) {
-      if (existing.nameOffset < duplicate.nameOffset) {
-        return new AnalysisError(
-            duplicate.source,
-            duplicate.nameOffset,
-            duplicate.nameLength,
-            CompileTimeErrorCode.METHOD_AND_GETTER_WITH_SAME_NAME,
-            [existing.displayName]);
-      } else {
-        return new AnalysisError(
-            existing.source,
-            existing.nameOffset,
-            existing.nameLength,
-            CompileTimeErrorCode.GETTER_AND_METHOD_WITH_SAME_NAME,
-            [existing.displayName]);
-      }
-    }
-    return super.getErrorForDuplicate(existing, duplicate);
-  }
-
-  /**
-   * Define the instance members defined by the class.
-   *
-   * @param typeElement the element representing the type represented by this scope
-   */
-  void _defineMembers(ClassElement typeElement) {
-    for (PropertyAccessorElement accessor in typeElement.accessors) {
-      define(accessor);
-    }
-    for (MethodElement method in typeElement.methods) {
-      define(method);
-    }
-  }
-}
-
-/**
  * Instances of the class `ConstantVerifier` traverse an AST structure looking for additional
  * errors and warnings not covered by the parser and resolver. In particular, it looks for errors
  * and warnings related to constant expressions.
@@ -1219,9 +1157,8 @@
     // check annotation creation
     Element element = node.element;
     if (element is ConstructorElement) {
-      ConstructorElement constructorElement = element;
-      // should 'const' constructor
-      if (!constructorElement.isConst) {
+      // should be 'const' constructor
+      if (!element.isConst) {
         _errorReporter.reportErrorForNode(
             CompileTimeErrorCode.NON_CONSTANT_ANNOTATION_CONSTRUCTOR, node);
         return null;
@@ -1384,8 +1321,7 @@
     DartType firstType = null;
     for (SwitchMember switchMember in switchMembers) {
       if (switchMember is SwitchCase) {
-        SwitchCase switchCase = switchMember;
-        Expression expression = switchCase.expression;
+        Expression expression = switchMember.expression;
         DartObjectImpl caseResult = _validate(
             expression, CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION);
         if (caseResult != null) {
@@ -1475,18 +1411,17 @@
     }
     // prepare ClassElement
     Element element = type.element;
-    if (element is! ClassElement) {
-      return false;
+    if (element is ClassElement) {
+      // lookup for ==
+      MethodElement method =
+          element.lookUpConcreteMethod("==", _currentLibrary);
+      if (method == null || method.enclosingElement.type.isObject) {
+        return false;
+      }
+      // there is == that we don't like
+      return true;
     }
-    ClassElement classElement = element as ClassElement;
-    // lookup for ==
-    MethodElement method =
-        classElement.lookUpConcreteMethod("==", _currentLibrary);
-    if (method == null || method.enclosingElement.type.isObject) {
-      return false;
-    }
-    // there is == that we don't like
-    return true;
+    return false;
   }
 
   /**
@@ -1573,11 +1508,10 @@
    */
   void _validateConstantArguments(ArgumentList argumentList) {
     for (Expression argument in argumentList.arguments) {
-      if (argument is NamedExpression) {
-        argument = (argument as NamedExpression).expression;
-      }
+      Expression realArgument =
+          argument is NamedExpression ? argument.expression : argument;
       _validate(
-          argument, CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT);
+          realArgument, CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT);
     }
   }
 
@@ -1593,19 +1527,16 @@
     NodeList<ConstructorInitializer> initializers = constructor.initializers;
     for (ConstructorInitializer initializer in initializers) {
       if (initializer is ConstructorFieldInitializer) {
-        ConstructorFieldInitializer fieldInitializer = initializer;
         _validateInitializerExpression(
-            parameterElements, fieldInitializer.expression);
+            parameterElements, initializer.expression);
       }
       if (initializer is RedirectingConstructorInvocation) {
-        RedirectingConstructorInvocation invocation = initializer;
         _validateInitializerInvocationArguments(
-            parameterElements, invocation.argumentList);
+            parameterElements, initializer.argumentList);
       }
       if (initializer is SuperConstructorInvocation) {
-        SuperConstructorInvocation invocation = initializer;
         _validateInitializerInvocationArguments(
-            parameterElements, invocation.argumentList);
+            parameterElements, initializer.argumentList);
       }
     }
   }
@@ -1622,8 +1553,7 @@
     }
     for (FormalParameter parameter in parameters.parameters) {
       if (parameter is DefaultFormalParameter) {
-        DefaultFormalParameter defaultParameter = parameter;
-        Expression defaultValue = defaultParameter.defaultValue;
+        Expression defaultValue = parameter.defaultValue;
         DartObjectImpl result;
         if (defaultValue == null) {
           result =
@@ -1656,30 +1586,27 @@
       ClassDeclaration classDeclaration, ConstructorDeclaration errorSite) {
     NodeList<ClassMember> members = classDeclaration.members;
     for (ClassMember member in members) {
-      if (member is FieldDeclaration) {
-        FieldDeclaration fieldDeclaration = member;
-        if (!fieldDeclaration.isStatic) {
-          for (VariableDeclaration variableDeclaration
-              in fieldDeclaration.fields.variables) {
-            Expression initializer = variableDeclaration.initializer;
-            if (initializer != null) {
-              // Ignore any errors produced during validation--if the constant
-              // can't be eavluated we'll just report a single error.
-              AnalysisErrorListener errorListener =
-                  AnalysisErrorListener.NULL_LISTENER;
-              ErrorReporter subErrorReporter =
-                  new ErrorReporter(errorListener, _errorReporter.source);
-              DartObjectImpl result = initializer.accept(new ConstantVisitor(
-                  new ConstantEvaluationEngine(_typeProvider, declaredVariables,
-                      typeSystem: _typeSystem),
-                  subErrorReporter));
-              if (result == null) {
-                _errorReporter.reportErrorForNode(
-                    CompileTimeErrorCode
-                        .CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST,
-                    errorSite,
-                    [variableDeclaration.name.name]);
-              }
+      if (member is FieldDeclaration && !member.isStatic) {
+        for (VariableDeclaration variableDeclaration
+            in member.fields.variables) {
+          Expression initializer = variableDeclaration.initializer;
+          if (initializer != null) {
+            // Ignore any errors produced during validation--if the constant
+            // can't be eavluated we'll just report a single error.
+            AnalysisErrorListener errorListener =
+                AnalysisErrorListener.NULL_LISTENER;
+            ErrorReporter subErrorReporter =
+                new ErrorReporter(errorListener, _errorReporter.source);
+            DartObjectImpl result = initializer.accept(new ConstantVisitor(
+                new ConstantEvaluationEngine(_typeProvider, declaredVariables,
+                    typeSystem: _typeSystem),
+                subErrorReporter));
+            if (result == null) {
+              _errorReporter.reportErrorForNode(
+                  CompileTimeErrorCode
+                      .CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST,
+                  errorSite,
+                  [variableDeclaration.name.name]);
             }
           }
         }
@@ -1932,6 +1859,21 @@
   }
 
   @override
+  Object visitExportDirective(ExportDirective node) {
+    ExportElement exportElement = node.element;
+    if (exportElement != null) {
+      // The element is null when the URI is invalid
+      LibraryElement library = exportElement.exportedLibrary;
+      if (library != null) {
+        for (Combinator combinator in node.combinators) {
+          _checkCombinator(exportElement.exportedLibrary, combinator);
+        }
+      }
+    }
+    return super.visitExportDirective(node);
+  }
+
+  @override
   Object visitIfStatement(IfStatement node) {
     Expression conditionExpression = node.condition;
     conditionExpression?.accept(this);
@@ -1961,6 +1903,21 @@
   }
 
   @override
+  Object visitImportDirective(ImportDirective node) {
+    ImportElement importElement = node.element;
+    if (importElement != null) {
+      // The element is null when the URI is invalid
+      LibraryElement library = importElement.importedLibrary;
+      if (library != null) {
+        for (Combinator combinator in node.combinators) {
+          _checkCombinator(library, combinator);
+        }
+      }
+    }
+    return super.visitImportDirective(node);
+  }
+
+  @override
   Object visitSwitchCase(SwitchCase node) {
     _checkForDeadStatementsInNodeList(node.statements);
     return super.visitSwitchCase(node);
@@ -2060,6 +2017,35 @@
   }
 
   /**
+   * Resolve the names in the given [combinator] in the scope of the given
+   * [library].
+   */
+  void _checkCombinator(LibraryElement library, Combinator combinator) {
+    Namespace namespace =
+        new NamespaceBuilder().createExportNamespaceForLibrary(library);
+    NodeList<SimpleIdentifier> names;
+    ErrorCode hintCode;
+    if (combinator is HideCombinator) {
+      names = combinator.hiddenNames;
+      hintCode = HintCode.UNDEFINED_HIDDEN_NAME;
+    } else {
+      names = (combinator as ShowCombinator).shownNames;
+      hintCode = HintCode.UNDEFINED_SHOWN_NAME;
+    }
+    for (SimpleIdentifier name in names) {
+      String nameStr = name.name;
+      Element element = namespace.get(nameStr);
+      if (element == null) {
+        element = namespace.get("$nameStr=");
+      }
+      if (element == null) {
+        _errorReporter
+            .reportErrorForNode(hintCode, name, [library.identifier, nameStr]);
+      }
+    }
+  }
+
+  /**
    * Given some [NodeList] of [Statement]s, from either a [Block] or
    * [SwitchMember], this loops through the list in reverse order searching for statements
    * after a return, unlabeled break or unlabeled continue statement to mark them as dead code.
@@ -2130,11 +2116,9 @@
   bool _isDebugConstant(Expression expression) {
     Element element = null;
     if (expression is Identifier) {
-      Identifier identifier = expression;
-      element = identifier.staticElement;
+      element = expression.staticElement;
     } else if (expression is PropertyAccess) {
-      PropertyAccess propertyAccess = expression;
-      element = propertyAccess.propertyName.staticElement;
+      element = expression.propertyName.staticElement;
     }
     if (element is PropertyAccessorElement) {
       PropertyInducingElement variable = element.variable;
@@ -2388,9 +2372,9 @@
             accessors = _enclosingUnit.accessors;
           }
           PropertyAccessorElement accessor;
-          if ((property as KeywordToken).keyword == Keyword.GET) {
+          if (property.keyword == Keyword.GET) {
             accessor = _findIdentifier(accessors, functionName);
-          } else if ((property as KeywordToken).keyword == Keyword.SET) {
+          } else if (property.keyword == Keyword.SET) {
             accessor = _findWithNameAndOffset(accessors, functionName,
                 functionName.name + '=', functionName.offset);
             _expectedElements.remove(accessor);
@@ -2501,9 +2485,9 @@
         methodName.staticElement = _enclosingExecutable;
       } else {
         PropertyAccessorElement accessor;
-        if ((property as KeywordToken).keyword == Keyword.GET) {
+        if (property.keyword == Keyword.GET) {
           accessor = _findIdentifier(_enclosingClass.accessors, methodName);
-        } else if ((property as KeywordToken).keyword == Keyword.SET) {
+        } else if (property.keyword == Keyword.SET) {
           accessor = _findWithNameAndOffset(_enclosingClass.accessors,
               methodName, nameOfMethod + '=', methodName.offset);
           _expectedElements.remove(accessor);
@@ -2847,7 +2831,7 @@
    */
   ExportElement _findExport(
       ExportDirective node, List<ExportElement> exports, Source source) {
-    if (source == null || !_enclosingUnit.context.exists(source)) {
+    if (source == null) {
       return null;
     }
     for (ExportElement export in exports) {
@@ -2862,6 +2846,9 @@
         return export;
       }
     }
+    if (!_enclosingUnit.context.exists(source)) {
+      return null;
+    }
     _mismatch("Could not find export element for '$source'", node);
     return null; // Never reached
   }
@@ -2873,7 +2860,7 @@
    */
   ImportElement _findImport(
       ImportDirective node, List<ImportElement> imports, Source source) {
-    if (source == null || !_enclosingUnit.context.exists(source)) {
+    if (source == null) {
       return null;
     }
     SimpleIdentifier prefix = node.prefix;
@@ -2895,6 +2882,9 @@
         return element;
       }
     }
+    if (!_enclosingUnit.context.exists(source)) {
+      return null;
+    }
     if (foundSource) {
       if (prefix == null) {
         _mismatch(
@@ -3291,80 +3281,6 @@
 }
 
 /**
- * Instances of the class `EnclosedScope` implement a scope that is lexically enclosed in
- * another scope.
- */
-class EnclosedScope extends Scope {
-  /**
-   * The scope in which this scope is lexically enclosed.
-   */
-  @override
-  final Scope enclosingScope;
-
-  /**
-   * A table mapping names that will be defined in this scope, but right now are not initialized.
-   * According to the scoping rules these names are hidden, even if they were defined in an outer
-   * scope.
-   */
-  HashMap<String, Element> _hiddenElements = new HashMap<String, Element>();
-
-  /**
-   * A flag indicating whether there are any names defined in this scope.
-   */
-  bool _hasHiddenName = false;
-
-  /**
-   * Initialize a newly created scope enclosed within another scope.
-   *
-   * @param enclosingScope the scope in which this scope is lexically enclosed
-   */
-  EnclosedScope(this.enclosingScope);
-
-  @override
-  AnalysisErrorListener get errorListener => enclosingScope.errorListener;
-
-  /**
-   * Record that given element is declared in this scope, but hasn't been initialized yet, so it is
-   * error to use. If there is already an element with the given name defined in an outer scope,
-   * then it will become unavailable.
-   *
-   * @param element the element declared, but not initialized in this scope
-   */
-  void hide(Element element) {
-    if (element != null) {
-      String name = element.name;
-      if (name != null && !name.isEmpty) {
-        _hiddenElements[name] = element;
-        _hasHiddenName = true;
-      }
-    }
-  }
-
-  @override
-  Element internalLookup(
-      Identifier identifier, String name, LibraryElement referencingLibrary) {
-    Element element = localLookup(name, referencingLibrary);
-    if (element != null) {
-      return element;
-    }
-    // May be there is a hidden Element.
-    if (_hasHiddenName) {
-      Element hiddenElement = _hiddenElements[name];
-      if (hiddenElement != null) {
-        errorListener.onError(new AnalysisError(
-            getSource(identifier),
-            identifier.offset,
-            identifier.length,
-            CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, []));
-        return hiddenElement;
-      }
-    }
-    // Check enclosing scope.
-    return enclosingScope.internalLookup(identifier, name, referencingLibrary);
-  }
-}
-
-/**
  * Instances of the class `EnumMemberBuilder` build the members in enum declarations.
  */
 class EnumMemberBuilder extends RecursiveAstVisitor<Object> {
@@ -3553,8 +3469,7 @@
     // evaluates to a constant false value?
     if (operatorType == TokenType.BAR_BAR) {
       if (lhsExpression is BooleanLiteral) {
-        BooleanLiteral booleanLiteral = lhsExpression;
-        if (!booleanLiteral.value) {
+        if (!lhsExpression.value) {
           return _nodeExits(rhsExpression);
         }
       }
@@ -3564,8 +3479,7 @@
     // expression if the left hand side is the true literal.
     if (operatorType == TokenType.AMPERSAND_AMPERSAND) {
       if (lhsExpression is BooleanLiteral) {
-        BooleanLiteral booleanLiteral = lhsExpression;
-        if (booleanLiteral.value) {
+        if (lhsExpression.value) {
           return _nodeExits(rhsExpression);
         }
       }
@@ -3626,11 +3540,10 @@
       }
       // TODO(jwren) Do we want to take all constant expressions into account?
       if (conditionExpression is BooleanLiteral) {
-        BooleanLiteral booleanLiteral = conditionExpression;
         // If do {} while (true), and the body doesn't return or the body
         // doesn't have a break, then return true.
         bool blockReturns = _nodeExits(node.body);
-        if (booleanLiteral.value &&
+        if (conditionExpression.value &&
             (blockReturns || !_enclosingBlockContainsBreak)) {
           return true;
         }
@@ -3723,8 +3636,7 @@
     }
     // TODO(jwren) Do we want to take all constant expressions into account?
     if (conditionExpression is BooleanLiteral) {
-      BooleanLiteral booleanLiteral = conditionExpression;
-      if (booleanLiteral.value) {
+      if (conditionExpression.value) {
         // if(true) ...
         return _nodeExits(thenStatement);
       } else if (elseStatement != null) {
@@ -3918,11 +3830,10 @@
       }
       // TODO(jwren) Do we want to take all constant expressions into account?
       if (conditionExpression is BooleanLiteral) {
-        BooleanLiteral booleanLiteral = conditionExpression;
         // If while(true), and the body doesn't return or the body doesn't have
         // a break, then return true.
         bool blockReturns = node.body.accept(this);
-        if (booleanLiteral.value &&
+        if (conditionExpression.value &&
             (blockReturns || !_enclosingBlockContainsBreak)) {
           return true;
         }
@@ -3983,103 +3894,6 @@
 }
 
 /**
- * The scope defined by a function.
- */
-class FunctionScope extends EnclosedScope {
-  /**
-   * The element representing the function that defines this scope.
-   */
-  final ExecutableElement _functionElement;
-
-  /**
-   * A flag indicating whether the parameters have already been defined, used to
-   * prevent the parameters from being defined multiple times.
-   */
-  bool _parametersDefined = false;
-
-  /**
-   * Initialize a newly created scope enclosed within the [enclosingScope] that
-   * represents the given [_functionElement].
-   */
-  FunctionScope(Scope enclosingScope, this._functionElement)
-      : super(new EnclosedScope(new EnclosedScope(enclosingScope))) {
-    if (_functionElement == null) {
-      throw new IllegalArgumentException("function element cannot be null");
-    }
-    _defineTypeParameters();
-  }
-
-  /**
-   * Define the parameters for the given function in the scope that encloses
-   * this function.
-   */
-  void defineParameters() {
-    if (_parametersDefined) {
-      return;
-    }
-    _parametersDefined = true;
-    Scope parameterScope = enclosingScope;
-    for (ParameterElement parameter in _functionElement.parameters) {
-      if (!parameter.isInitializingFormal) {
-        parameterScope.define(parameter);
-      }
-    }
-  }
-
-  /**
-   * Define the type parameters for the function.
-   */
-  void _defineTypeParameters() {
-    Scope typeParameterScope = enclosingScope.enclosingScope;
-    for (TypeParameterElement typeParameter
-        in _functionElement.typeParameters) {
-      typeParameterScope.define(typeParameter);
-    }
-  }
-}
-
-/**
- * The scope defined by a function type alias.
- */
-class FunctionTypeScope extends EnclosedScope {
-  final FunctionTypeAliasElement _typeElement;
-
-  bool _parametersDefined = false;
-
-  /**
-   * Initialize a newly created scope enclosed within the [enclosingScope] that
-   * represents the given [_typeElement].
-   */
-  FunctionTypeScope(Scope enclosingScope, this._typeElement)
-      : super(new EnclosedScope(enclosingScope)) {
-    _defineTypeParameters();
-  }
-
-  /**
-   * Define the parameters for the function type alias.
-   */
-  void defineParameters() {
-    if (_parametersDefined) {
-      return;
-    }
-    _parametersDefined = true;
-    for (ParameterElement parameter in _typeElement.parameters) {
-      define(parameter);
-    }
-  }
-
-  /**
-   * Define the type parameters for the function type alias.
-   */
-  void _defineTypeParameters() {
-    Scope typeParameterScope = enclosingScope;
-    for (TypeParameterElement typeParameter in _typeElement.typeParameters) {
-      typeParameterScope.define(typeParameter);
-    }
-  }
-}
-
-/**
  * A visitor that visits ASTs and fills [UsedImportedElements].
  */
 class GatherUsedImportedElementsVisitor extends RecursiveAstVisitor {
@@ -4109,6 +3923,30 @@
   }
 
   /**
+   * If the given [identifier] is prefixed with a [PrefixElement], fill the
+   * corresponding `UsedImportedElements.prefixMap` entry and return `true`.
+   */
+  bool _recordPrefixMap(SimpleIdentifier identifier, Element element) {
+    bool recordIfTargetIsPrefixElement(Expression target) {
+      if (target is SimpleIdentifier && target.staticElement is PrefixElement) {
+        List<Element> prefixedElements = usedElements.prefixMap
+            .putIfAbsent(target.staticElement, () => <Element>[]);
+        prefixedElements.add(element);
+        return true;
+      }
+      return false;
+    }
+    AstNode parent = identifier.parent;
+    if (parent is MethodInvocation && parent.methodName == identifier) {
+      return recordIfTargetIsPrefixElement(parent.target);
+    }
+    if (parent is PrefixedIdentifier && parent.identifier == identifier) {
+      return recordIfTargetIsPrefixElement(parent.prefix);
+    }
+    return false;
+  }
+
+  /**
    * Visit identifiers used by the given [directive].
    */
   void _visitDirective(Directive directive) {
@@ -4123,8 +3961,7 @@
     // If the element is multiply defined then call this method recursively for
     // each of the conflicting elements.
     if (element is MultiplyDefinedElement) {
-      MultiplyDefinedElement multiplyDefinedElement = element;
-      for (Element elt in multiplyDefinedElement.conflictingElements) {
+      for (Element elt in element.conflictingElements) {
         _visitIdentifier(identifier, elt);
       }
       return;
@@ -4157,30 +3994,6 @@
     // Remember the element.
     usedElements.elements.add(element);
   }
-
-  /**
-   * If the given [identifier] is prefixed with a [PrefixElement], fill the
-   * corresponding `UsedImportedElements.prefixMap` entry and return `true`.
-   */
-  bool _recordPrefixMap(SimpleIdentifier identifier, Element element) {
-    bool recordIfTargetIsPrefixElement(Expression target) {
-      if (target is SimpleIdentifier && target.staticElement is PrefixElement) {
-        List<Element> prefixedElements = usedElements.prefixMap
-            .putIfAbsent(target.staticElement, () => <Element>[]);
-        prefixedElements.add(element);
-        return true;
-      }
-      return false;
-    }
-    AstNode parent = identifier.parent;
-    if (parent is MethodInvocation && parent.methodName == identifier) {
-      return recordIfTargetIsPrefixElement(parent.target);
-    }
-    if (parent is PrefixedIdentifier && parent.identifier == identifier) {
-      return recordIfTargetIsPrefixElement(parent.prefix);
-    }
-    return false;
-  }
 }
 
 /**
@@ -4422,57 +4235,6 @@
 }
 
 /**
- * Instances of the class `ImplicitLabelScope` represent the scope statements
- * that can be the target of unlabeled break and continue statements.
- */
-class ImplicitLabelScope {
-  /**
-   * The implicit label scope associated with the top level of a function.
-   */
-  static const ImplicitLabelScope ROOT = const ImplicitLabelScope._(null, null);
-
-  /**
-   * The implicit label scope enclosing this implicit label scope.
-   */
-  final ImplicitLabelScope outerScope;
-
-  /**
-   * The statement that acts as a target for break and/or continue statements
-   * at this scoping level.
-   */
-  final Statement statement;
-
-  /**
-   * Private constructor.
-   */
-  const ImplicitLabelScope._(this.outerScope, this.statement);
-
-  /**
-   * Get the statement which should be the target of an unlabeled `break` or
-   * `continue` statement, or `null` if there is no appropriate target.
-   */
-  Statement getTarget(bool isContinue) {
-    if (outerScope == null) {
-      // This scope represents the toplevel of a function body, so it doesn't
-      // match either break or continue.
-      return null;
-    }
-    if (isContinue && statement is SwitchStatement) {
-      return outerScope.getTarget(isContinue);
-    }
-    return statement;
-  }
-
-  /**
-   * Initialize a newly created scope to represent a switch statement or loop
-   * nested within the current scope.  [statement] is the statement associated
-   * with the newly created scope.
-   */
-  ImplicitLabelScope nest(Statement statement) =>
-      new ImplicitLabelScope._(this, statement);
-}
-
-/**
  * Instances of the class `ImportsVerifier` visit all of the referenced libraries in the source code
  * verifying that all of the imports are used, otherwise a [HintCode.UNUSED_IMPORT] hint is
  * generated with [generateUnusedImportHints].
@@ -4556,27 +4318,25 @@
   void addImports(CompilationUnit node) {
     for (Directive directive in node.directives) {
       if (directive is ImportDirective) {
-        ImportDirective importDirective = directive;
-        LibraryElement libraryElement = importDirective.uriElement;
+        LibraryElement libraryElement = directive.uriElement;
         if (libraryElement == null) {
           continue;
         }
-        _unusedImports.add(importDirective);
+        _unusedImports.add(directive);
         //
         // Initialize prefixElementMap
         //
-        if (importDirective.asKeyword != null) {
-          SimpleIdentifier prefixIdentifier = importDirective.prefix;
+        if (directive.asKeyword != null) {
+          SimpleIdentifier prefixIdentifier = directive.prefix;
           if (prefixIdentifier != null) {
             Element element = prefixIdentifier.staticElement;
             if (element is PrefixElement) {
-              PrefixElement prefixElementKey = element;
-              List<ImportDirective> list = _prefixElementMap[prefixElementKey];
+              List<ImportDirective> list = _prefixElementMap[element];
               if (list == null) {
                 list = new List<ImportDirective>();
-                _prefixElementMap[prefixElementKey] = list;
+                _prefixElementMap[element] = list;
               }
-              list.add(importDirective);
+              list.add(directive);
             }
             // TODO (jwren) Can the element ever not be a PrefixElement?
           }
@@ -4584,14 +4344,14 @@
         //
         // Initialize libraryMap: libraryElement -> importDirective
         //
-        _putIntoLibraryMap(libraryElement, importDirective);
+        _putIntoLibraryMap(libraryElement, directive);
         //
         // For this new addition to the libraryMap, also recursively add any
         // exports from the libraryElement.
         //
         _addAdditionalLibrariesForExports(
-            libraryElement, importDirective, new List<LibraryElement>());
-        _addShownNames(importDirective);
+            libraryElement, directive, new HashSet<LibraryElement>());
+        _addShownNames(directive);
       }
     }
     if (_unusedImports.length > 1) {
@@ -4738,15 +4498,15 @@
    * Recursively add any exported library elements into the [libraryMap].
    */
   void _addAdditionalLibrariesForExports(LibraryElement library,
-      ImportDirective importDirective, List<LibraryElement> exportPath) {
-    if (exportPath.contains(library)) {
+      ImportDirective importDirective, Set<LibraryElement> visitedLibraries) {
+    if (!visitedLibraries.add(library)) {
       return;
     }
-    exportPath.add(library);
-    for (LibraryElement exportedLibraryElt in library.exportedLibraries) {
-      _putIntoLibraryMap(exportedLibraryElt, importDirective);
+    for (ExportElement exportElt in library.exports) {
+      LibraryElement exportedLibrary = exportElt.exportedLibrary;
+      _putIntoLibraryMap(exportedLibrary, importDirective);
       _addAdditionalLibrariesForExports(
-          exportedLibraryElt, importDirective, exportPath);
+          exportedLibrary, importDirective, visitedLibraries);
     }
   }
 
@@ -5105,1041 +4865,6 @@
 }
 
 /**
- * Instances of the class `InheritanceManager` manage the knowledge of where class members
- * (methods, getters & setters) are inherited from.
- */
-class InheritanceManager {
-  /**
-   * The [LibraryElement] that is managed by this manager.
-   */
-  LibraryElement _library;
-
-  /**
-   * This is a mapping between each [ClassElement] and a map between the [String] member
-   * names and the associated [ExecutableElement] in the mixin and superclass chain.
-   */
-  HashMap<ClassElement, MemberMap> _classLookup;
-
-  /**
-   * This is a mapping between each [ClassElement] and a map between the [String] member
-   * names and the associated [ExecutableElement] in the interface set.
-   */
-  HashMap<ClassElement, MemberMap> _interfaceLookup;
-
-  /**
-   * A map between each visited [ClassElement] and the set of [AnalysisError]s found on
-   * the class element.
-   */
-  HashMap<ClassElement, HashSet<AnalysisError>> _errorsInClassElement =
-      new HashMap<ClassElement, HashSet<AnalysisError>>();
-
-  /**
-   * Initialize a newly created inheritance manager.
-   *
-   * @param library the library element context that the inheritance mappings are being generated
-   */
-  InheritanceManager(LibraryElement library) {
-    this._library = library;
-    _classLookup = new HashMap<ClassElement, MemberMap>();
-    _interfaceLookup = new HashMap<ClassElement, MemberMap>();
-  }
-
-  /**
-   * Set the new library element context.
-   *
-   * @param library the new library element
-   */
-  void set libraryElement(LibraryElement library) {
-    this._library = library;
-  }
-
-  /**
-   * Return the set of [AnalysisError]s found on the passed [ClassElement], or
-   * `null` if there are none.
-   *
-   * @param classElt the class element to query
-   * @return the set of [AnalysisError]s found on the passed [ClassElement], or
-   *         `null` if there are none
-   */
-  HashSet<AnalysisError> getErrors(ClassElement classElt) =>
-      _errorsInClassElement[classElt];
-
-  /**
-   * Get and return a mapping between the set of all string names of the members inherited from the
-   * passed [ClassElement] superclass hierarchy, and the associated [ExecutableElement].
-   *
-   * @param classElt the class element to query
-   * @return a mapping between the set of all members inherited from the passed [ClassElement]
-   *         superclass hierarchy, and the associated [ExecutableElement]
-   */
-  MemberMap getMapOfMembersInheritedFromClasses(ClassElement classElt) =>
-      _computeClassChainLookupMap(classElt, new HashSet<ClassElement>());
-
-  /**
-   * Get and return a mapping between the set of all string names of the members inherited from the
-   * passed [ClassElement] interface hierarchy, and the associated [ExecutableElement].
-   *
-   * @param classElt the class element to query
-   * @return a mapping between the set of all string names of the members inherited from the passed
-   *         [ClassElement] interface hierarchy, and the associated [ExecutableElement].
-   */
-  MemberMap getMapOfMembersInheritedFromInterfaces(ClassElement classElt) =>
-      _computeInterfaceLookupMap(classElt, new HashSet<ClassElement>());
-
-  /**
-   * Given some [ClassElement] and some member name, this returns the
-   * [ExecutableElement] that the class inherits from the mixins,
-   * superclasses or interfaces, that has the member name, if no member is inherited `null` is
-   * returned.
-   *
-   * @param classElt the class element to query
-   * @param memberName the name of the executable element to find and return
-   * @return the inherited executable element with the member name, or `null` if no such
-   *         member exists
-   */
-  ExecutableElement lookupInheritance(
-      ClassElement classElt, String memberName) {
-    if (memberName == null || memberName.isEmpty) {
-      return null;
-    }
-    ExecutableElement executable =
-        _computeClassChainLookupMap(classElt, new HashSet<ClassElement>())
-            .get(memberName);
-    if (executable == null) {
-      return _computeInterfaceLookupMap(classElt, new HashSet<ClassElement>())
-          .get(memberName);
-    }
-    return executable;
-  }
-
-  /**
-   * Given some [ClassElement] and some member name, this returns the
-   * [ExecutableElement] that the class either declares itself, or
-   * inherits, that has the member name, if no member is inherited `null` is returned.
-   *
-   * @param classElt the class element to query
-   * @param memberName the name of the executable element to find and return
-   * @return the inherited executable element with the member name, or `null` if no such
-   *         member exists
-   */
-  ExecutableElement lookupMember(ClassElement classElt, String memberName) {
-    ExecutableElement element = _lookupMemberInClass(classElt, memberName);
-    if (element != null) {
-      return element;
-    }
-    return lookupInheritance(classElt, memberName);
-  }
-
-  /**
-   * Determine the set of methods which is overridden by the given class member. If no member is
-   * inherited, an empty list is returned. If one of the inherited members is a
-   * [MultiplyInheritedExecutableElement], then it is expanded into its constituent inherited
-   * elements.
-   *
-   * @param classElt the class to query
-   * @param memberName the name of the class member to query
-   * @return a list of overridden methods
-   */
-  List<ExecutableElement> lookupOverrides(
-      ClassElement classElt, String memberName) {
-    List<ExecutableElement> result = new List<ExecutableElement>();
-    if (memberName == null || memberName.isEmpty) {
-      return result;
-    }
-    List<MemberMap> interfaceMaps =
-        _gatherInterfaceLookupMaps(classElt, new HashSet<ClassElement>());
-    if (interfaceMaps != null) {
-      for (MemberMap interfaceMap in interfaceMaps) {
-        ExecutableElement overriddenElement = interfaceMap.get(memberName);
-        if (overriddenElement != null) {
-          if (overriddenElement is MultiplyInheritedExecutableElement) {
-            MultiplyInheritedExecutableElement multiplyInheritedElement =
-                overriddenElement;
-            for (ExecutableElement element
-                in multiplyInheritedElement.inheritedElements) {
-              result.add(element);
-            }
-          } else {
-            result.add(overriddenElement);
-          }
-        }
-      }
-    }
-    return result;
-  }
-
-  /**
-   * This method takes some inherited [FunctionType], and resolves all the parameterized types
-   * in the function type, dependent on the class in which it is being overridden.
-   *
-   * @param baseFunctionType the function type that is being overridden
-   * @param memberName the name of the member, this is used to lookup the inheritance path of the
-   *          override
-   * @param definingType the type that is overriding the member
-   * @return the passed function type with any parameterized types substituted
-   */
-  // TODO(jmesserly): investigate why this is needed in ErrorVerifier's override
-  // checking. There seems to be some rare cases where we get partially
-  // substituted type arguments, and the function types don't compare equally.
-  FunctionType substituteTypeArgumentsInMemberFromInheritance(
-      FunctionType baseFunctionType,
-      String memberName,
-      InterfaceType definingType) {
-    // if the baseFunctionType is null, or does not have any parameters,
-    // return it.
-    if (baseFunctionType == null ||
-        baseFunctionType.typeArguments.length == 0) {
-      return baseFunctionType;
-    }
-    // First, generate the path from the defining type to the overridden member
-    Queue<InterfaceType> inheritancePath = new Queue<InterfaceType>();
-    _computeInheritancePath(inheritancePath, definingType, memberName);
-    if (inheritancePath == null || inheritancePath.isEmpty) {
-      // TODO(jwren) log analysis engine error
-      return baseFunctionType;
-    }
-    FunctionType functionTypeToReturn = baseFunctionType;
-    // loop backward through the list substituting as we go:
-    while (!inheritancePath.isEmpty) {
-      InterfaceType lastType = inheritancePath.removeLast();
-      List<DartType> parameterTypes = lastType.element.type.typeArguments;
-      List<DartType> argumentTypes = lastType.typeArguments;
-      functionTypeToReturn =
-          functionTypeToReturn.substitute2(argumentTypes, parameterTypes);
-    }
-    return functionTypeToReturn;
-  }
-
-  /**
-   * Compute and return a mapping between the set of all string names of the members inherited from
-   * the passed [ClassElement] superclass hierarchy, and the associated
-   * [ExecutableElement].
-   *
-   * @param classElt the class element to query
-   * @param visitedClasses a set of visited classes passed back into this method when it calls
-   *          itself recursively
-   * @return a mapping between the set of all string names of the members inherited from the passed
-   *         [ClassElement] superclass hierarchy, and the associated [ExecutableElement]
-   */
-  MemberMap _computeClassChainLookupMap(
-      ClassElement classElt, HashSet<ClassElement> visitedClasses) {
-    MemberMap resultMap = _classLookup[classElt];
-    if (resultMap != null) {
-      return resultMap;
-    } else {
-      resultMap = new MemberMap();
-    }
-    ClassElement superclassElt = null;
-    InterfaceType supertype = classElt.supertype;
-    if (supertype != null) {
-      superclassElt = supertype.element;
-    } else {
-      // classElt is Object
-      _classLookup[classElt] = resultMap;
-      return resultMap;
-    }
-    if (superclassElt != null) {
-      if (!visitedClasses.contains(superclassElt)) {
-        visitedClasses.add(superclassElt);
-        try {
-          resultMap = new MemberMap.from(
-              _computeClassChainLookupMap(superclassElt, visitedClasses));
-          //
-          // Substitute the super types down the hierarchy.
-          //
-          _substituteTypeParametersDownHierarchy(supertype, resultMap);
-          //
-          // Include the members from the superclass in the resultMap.
-          //
-          _recordMapWithClassMembers(resultMap, supertype, false);
-        } finally {
-          visitedClasses.remove(superclassElt);
-        }
-      } else {
-        // This case happens only when the superclass was previously visited and
-        // not in the lookup, meaning this is meant to shorten the compute for
-        // recursive cases.
-        _classLookup[superclassElt] = resultMap;
-        return resultMap;
-      }
-    }
-    //
-    // Include the members from the mixins in the resultMap.  If there are
-    // multiple mixins, visit them in the order listed so that methods in later
-    // mixins will overwrite identically-named methods in earlier mixins.
-    //
-    List<InterfaceType> mixins = classElt.mixins;
-    for (InterfaceType mixin in mixins) {
-      ClassElement mixinElement = mixin.element;
-      if (mixinElement != null) {
-        if (!visitedClasses.contains(mixinElement)) {
-          visitedClasses.add(mixinElement);
-          try {
-            MemberMap map = new MemberMap.from(
-                _computeClassChainLookupMap(mixinElement, visitedClasses));
-            //
-            // Substitute the super types down the hierarchy.
-            //
-            _substituteTypeParametersDownHierarchy(mixin, map);
-            //
-            // Include the members from the superclass in the resultMap.
-            //
-            _recordMapWithClassMembers(map, mixin, false);
-            //
-            // Add the members from map into result map.
-            //
-            for (int j = 0; j < map.size; j++) {
-              String key = map.getKey(j);
-              ExecutableElement value = map.getValue(j);
-              if (key != null) {
-                ClassElement definingClass = value
-                    .getAncestor((Element element) => element is ClassElement);
-                if (!definingClass.type.isObject) {
-                  ExecutableElement existingValue = resultMap.get(key);
-                  if (existingValue == null ||
-                      (existingValue != null && !_isAbstract(value))) {
-                    resultMap.put(key, value);
-                  }
-                }
-              }
-            }
-          } finally {
-            visitedClasses.remove(mixinElement);
-          }
-        } else {
-          // This case happens only when the superclass was previously visited
-          // and not in the lookup, meaning this is meant to shorten the compute
-          // for recursive cases.
-          _classLookup[mixinElement] = resultMap;
-          return resultMap;
-        }
-      }
-    }
-    _classLookup[classElt] = resultMap;
-    return resultMap;
-  }
-
-  /**
-   * Compute and return the inheritance path given the context of a type and a member that is
-   * overridden in the inheritance path (for which the type is in the path).
-   *
-   * @param chain the inheritance path that is built up as this method calls itself recursively,
-   *          when this method is called an empty [LinkedList] should be provided
-   * @param currentType the current type in the inheritance path
-   * @param memberName the name of the member that is being looked up the inheritance path
-   */
-  void _computeInheritancePath(Queue<InterfaceType> chain,
-      InterfaceType currentType, String memberName) {
-    // TODO (jwren) create a public version of this method which doesn't require
-    // the initial chain to be provided, then provided tests for this
-    // functionality in InheritanceManagerTest
-    chain.add(currentType);
-    ClassElement classElt = currentType.element;
-    InterfaceType supertype = classElt.supertype;
-    // Base case- reached Object
-    if (supertype == null) {
-      // Looked up the chain all the way to Object, return null.
-      // This should never happen.
-      return;
-    }
-    // If we are done, return the chain
-    // We are not done if this is the first recursive call on this method.
-    if (chain.length != 1) {
-      // We are done however if the member is in this classElt
-      if (_lookupMemberInClass(classElt, memberName) != null) {
-        return;
-      }
-    }
-    // Mixins- note that mixins call lookupMemberInClass, not lookupMember
-    List<InterfaceType> mixins = classElt.mixins;
-    for (int i = mixins.length - 1; i >= 0; i--) {
-      ClassElement mixinElement = mixins[i].element;
-      if (mixinElement != null) {
-        ExecutableElement elt = _lookupMemberInClass(mixinElement, memberName);
-        if (elt != null) {
-          // this is equivalent (but faster than) calling this method
-          // recursively
-          // (return computeInheritancePath(chain, mixins[i], memberName);)
-          chain.add(mixins[i]);
-          return;
-        }
-      }
-    }
-    // Superclass
-    ClassElement superclassElt = supertype.element;
-    if (lookupMember(superclassElt, memberName) != null) {
-      _computeInheritancePath(chain, supertype, memberName);
-      return;
-    }
-    // Interfaces
-    List<InterfaceType> interfaces = classElt.interfaces;
-    for (InterfaceType interfaceType in interfaces) {
-      ClassElement interfaceElement = interfaceType.element;
-      if (interfaceElement != null &&
-          lookupMember(interfaceElement, memberName) != null) {
-        _computeInheritancePath(chain, interfaceType, memberName);
-        return;
-      }
-    }
-  }
-
-  /**
-   * Compute and return a mapping between the set of all string names of the members inherited from
-   * the passed [ClassElement] interface hierarchy, and the associated
-   * [ExecutableElement].
-   *
-   * @param classElt the class element to query
-   * @param visitedInterfaces a set of visited classes passed back into this method when it calls
-   *          itself recursively
-   * @return a mapping between the set of all string names of the members inherited from the passed
-   *         [ClassElement] interface hierarchy, and the associated [ExecutableElement]
-   */
-  MemberMap _computeInterfaceLookupMap(
-      ClassElement classElt, HashSet<ClassElement> visitedInterfaces) {
-    MemberMap resultMap = _interfaceLookup[classElt];
-    if (resultMap != null) {
-      return resultMap;
-    }
-    List<MemberMap> lookupMaps =
-        _gatherInterfaceLookupMaps(classElt, visitedInterfaces);
-    if (lookupMaps == null) {
-      resultMap = new MemberMap();
-    } else {
-      HashMap<String, List<ExecutableElement>> unionMap =
-          _unionInterfaceLookupMaps(lookupMaps);
-      resultMap = _resolveInheritanceLookup(classElt, unionMap);
-    }
-    _interfaceLookup[classElt] = resultMap;
-    return resultMap;
-  }
-
-  /**
-   * Collect a list of interface lookup maps whose elements correspond to all of the classes
-   * directly above [classElt] in the class hierarchy (the direct superclass if any, all
-   * mixins, and all direct superinterfaces). Each item in the list is the interface lookup map
-   * returned by [computeInterfaceLookupMap] for the corresponding super, except with type
-   * parameters appropriately substituted.
-   *
-   * @param classElt the class element to query
-   * @param visitedInterfaces a set of visited classes passed back into this method when it calls
-   *          itself recursively
-   * @return `null` if there was a problem (such as a loop in the class hierarchy) or if there
-   *         are no classes above this one in the class hierarchy. Otherwise, a list of interface
-   *         lookup maps.
-   */
-  List<MemberMap> _gatherInterfaceLookupMaps(
-      ClassElement classElt, HashSet<ClassElement> visitedInterfaces) {
-    InterfaceType supertype = classElt.supertype;
-    ClassElement superclassElement =
-        supertype != null ? supertype.element : null;
-    List<InterfaceType> mixins = classElt.mixins;
-    List<InterfaceType> interfaces = classElt.interfaces;
-    // Recursively collect the list of mappings from all of the interface types
-    List<MemberMap> lookupMaps = new List<MemberMap>();
-    //
-    // Superclass element
-    //
-    if (superclassElement != null) {
-      if (!visitedInterfaces.contains(superclassElement)) {
-        try {
-          visitedInterfaces.add(superclassElement);
-          //
-          // Recursively compute the map for the super type.
-          //
-          MemberMap map =
-              _computeInterfaceLookupMap(superclassElement, visitedInterfaces);
-          map = new MemberMap.from(map);
-          //
-          // Substitute the super type down the hierarchy.
-          //
-          _substituteTypeParametersDownHierarchy(supertype, map);
-          //
-          // Add any members from the super type into the map as well.
-          //
-          _recordMapWithClassMembers(map, supertype, true);
-          lookupMaps.add(map);
-        } finally {
-          visitedInterfaces.remove(superclassElement);
-        }
-      } else {
-        return null;
-      }
-    }
-    //
-    // Mixin elements
-    //
-    for (int i = mixins.length - 1; i >= 0; i--) {
-      InterfaceType mixinType = mixins[i];
-      ClassElement mixinElement = mixinType.element;
-      if (mixinElement != null) {
-        if (!visitedInterfaces.contains(mixinElement)) {
-          try {
-            visitedInterfaces.add(mixinElement);
-            //
-            // Recursively compute the map for the mixin.
-            //
-            MemberMap map =
-                _computeInterfaceLookupMap(mixinElement, visitedInterfaces);
-            map = new MemberMap.from(map);
-            //
-            // Substitute the mixin type down the hierarchy.
-            //
-            _substituteTypeParametersDownHierarchy(mixinType, map);
-            //
-            // Add any members from the mixin type into the map as well.
-            //
-            _recordMapWithClassMembers(map, mixinType, true);
-            lookupMaps.add(map);
-          } finally {
-            visitedInterfaces.remove(mixinElement);
-          }
-        } else {
-          return null;
-        }
-      }
-    }
-    //
-    // Interface elements
-    //
-    for (InterfaceType interfaceType in interfaces) {
-      ClassElement interfaceElement = interfaceType.element;
-      if (interfaceElement != null) {
-        if (!visitedInterfaces.contains(interfaceElement)) {
-          try {
-            visitedInterfaces.add(interfaceElement);
-            //
-            // Recursively compute the map for the interfaces.
-            //
-            MemberMap map =
-                _computeInterfaceLookupMap(interfaceElement, visitedInterfaces);
-            map = new MemberMap.from(map);
-            //
-            // Substitute the supertypes down the hierarchy
-            //
-            _substituteTypeParametersDownHierarchy(interfaceType, map);
-            //
-            // And add any members from the interface into the map as well.
-            //
-            _recordMapWithClassMembers(map, interfaceType, true);
-            lookupMaps.add(map);
-          } finally {
-            visitedInterfaces.remove(interfaceElement);
-          }
-        } else {
-          return null;
-        }
-      }
-    }
-    if (lookupMaps.length == 0) {
-      return null;
-    }
-    return lookupMaps;
-  }
-
-  /**
-   * Given some [ClassElement], this method finds and returns the [ExecutableElement] of
-   * the passed name in the class element. Static members, members in super types and members not
-   * accessible from the current library are not considered.
-   *
-   * @param classElt the class element to query
-   * @param memberName the name of the member to lookup in the class
-   * @return the found [ExecutableElement], or `null` if no such member was found
-   */
-  ExecutableElement _lookupMemberInClass(
-      ClassElement classElt, String memberName) {
-    List<MethodElement> methods = classElt.methods;
-    for (MethodElement method in methods) {
-      if (memberName == method.name &&
-          method.isAccessibleIn(_library) &&
-          !method.isStatic) {
-        return method;
-      }
-    }
-    List<PropertyAccessorElement> accessors = classElt.accessors;
-    for (PropertyAccessorElement accessor in accessors) {
-      if (memberName == accessor.name &&
-          accessor.isAccessibleIn(_library) &&
-          !accessor.isStatic) {
-        return accessor;
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Record the passed map with the set of all members (methods, getters and setters) in the type
-   * into the passed map.
-   *
-   * @param map some non-`null` map to put the methods and accessors from the passed
-   *          [ClassElement] into
-   * @param type the type that will be recorded into the passed map
-   * @param doIncludeAbstract `true` if abstract members will be put into the map
-   */
-  void _recordMapWithClassMembers(
-      MemberMap map, InterfaceType type, bool doIncludeAbstract) {
-    List<MethodElement> methods = type.methods;
-    for (MethodElement method in methods) {
-      if (method.isAccessibleIn(_library) &&
-          !method.isStatic &&
-          (doIncludeAbstract || !method.isAbstract)) {
-        map.put(method.name, method);
-      }
-    }
-    List<PropertyAccessorElement> accessors = type.accessors;
-    for (PropertyAccessorElement accessor in accessors) {
-      if (accessor.isAccessibleIn(_library) &&
-          !accessor.isStatic &&
-          (doIncludeAbstract || !accessor.isAbstract)) {
-        map.put(accessor.name, accessor);
-      }
-    }
-  }
-
-  /**
-   * This method is used to report errors on when they are found computing inheritance information.
-   * See [ErrorVerifier.checkForInconsistentMethodInheritance] to see where these generated
-   * error codes are reported back into the analysis engine.
-   *
-   * @param classElt the location of the source for which the exception occurred
-   * @param offset the offset of the location of the error
-   * @param length the length of the location of the error
-   * @param errorCode the error code to be associated with this error
-   * @param arguments the arguments used to build the error message
-   */
-  void _reportError(ClassElement classElt, int offset, int length,
-      ErrorCode errorCode, List<Object> arguments) {
-    HashSet<AnalysisError> errorSet = _errorsInClassElement[classElt];
-    if (errorSet == null) {
-      errorSet = new HashSet<AnalysisError>();
-      _errorsInClassElement[classElt] = errorSet;
-    }
-    errorSet.add(new AnalysisError(
-        classElt.source, offset, length, errorCode, arguments));
-  }
-
-  /**
-   * Given the set of methods defined by classes above [classElt] in the class hierarchy,
-   * apply the appropriate inheritance rules to determine those methods inherited by or overridden
-   * by [classElt]. Also report static warnings
-   * [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE] and
-   * [StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD] if appropriate.
-   *
-   * @param classElt the class element to query.
-   * @param unionMap a mapping from method name to the set of unique (in terms of signature) methods
-   *          defined in superclasses of [classElt].
-   * @return the inheritance lookup map for [classElt].
-   */
-  MemberMap _resolveInheritanceLookup(ClassElement classElt,
-      HashMap<String, List<ExecutableElement>> unionMap) {
-    MemberMap resultMap = new MemberMap();
-    unionMap.forEach((String key, List<ExecutableElement> list) {
-      int numOfEltsWithMatchingNames = list.length;
-      if (numOfEltsWithMatchingNames == 1) {
-        //
-        // Example: class A inherits only 1 method named 'm'.
-        // Since it is the only such method, it is inherited.
-        // Another example: class A inherits 2 methods named 'm' from 2
-        // different interfaces, but they both have the same signature, so it is
-        // the method inherited.
-        //
-        resultMap.put(key, list[0]);
-      } else {
-        //
-        // Then numOfEltsWithMatchingNames > 1, check for the warning cases.
-        //
-        bool allMethods = true;
-        bool allSetters = true;
-        bool allGetters = true;
-        for (ExecutableElement executableElement in list) {
-          if (executableElement is PropertyAccessorElement) {
-            allMethods = false;
-            if (executableElement.isSetter) {
-              allGetters = false;
-            } else {
-              allSetters = false;
-            }
-          } else {
-            allGetters = false;
-            allSetters = false;
-          }
-        }
-        //
-        // If there isn't a mixture of methods with getters, then continue,
-        // otherwise create a warning.
-        //
-        if (allMethods || allGetters || allSetters) {
-          //
-          // Compute the element whose type is the subtype of all of the other
-          // types.
-          //
-          List<ExecutableElement> elements = new List.from(list);
-          List<FunctionType> executableElementTypes =
-              new List<FunctionType>(numOfEltsWithMatchingNames);
-          for (int i = 0; i < numOfEltsWithMatchingNames; i++) {
-            executableElementTypes[i] = elements[i].type;
-          }
-          List<int> subtypesOfAllOtherTypesIndexes = new List<int>();
-          for (int i = 0; i < numOfEltsWithMatchingNames; i++) {
-            FunctionType subtype = executableElementTypes[i];
-            if (subtype == null) {
-              continue;
-            }
-            bool subtypeOfAllTypes = true;
-            TypeSystem typeSystem = _library.context.typeSystem;
-            for (int j = 0;
-                j < numOfEltsWithMatchingNames && subtypeOfAllTypes;
-                j++) {
-              if (i != j) {
-                if (!typeSystem.isSubtypeOf(
-                    subtype, executableElementTypes[j])) {
-                  subtypeOfAllTypes = false;
-                  break;
-                }
-              }
-            }
-            if (subtypeOfAllTypes) {
-              subtypesOfAllOtherTypesIndexes.add(i);
-            }
-          }
-          //
-          // The following is split into three cases determined by the number of
-          // elements in subtypesOfAllOtherTypes
-          //
-          if (subtypesOfAllOtherTypesIndexes.length == 1) {
-            //
-            // Example: class A inherited only 2 method named 'm'.
-            // One has the function type '() -> dynamic' and one has the
-            // function type '([int]) -> dynamic'. Since the second method is a
-            // subtype of all the others, it is the inherited method.
-            // Tests: InheritanceManagerTest.
-            // test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_*
-            //
-            resultMap.put(key, elements[subtypesOfAllOtherTypesIndexes[0]]);
-          } else {
-            if (subtypesOfAllOtherTypesIndexes.isEmpty) {
-              //
-              // Determine if the current class has a method or accessor with
-              // the member name, if it does then then this class does not
-              // "inherit" from any of the supertypes. See issue 16134.
-              //
-              bool classHasMember = false;
-              if (allMethods) {
-                classHasMember = classElt.getMethod(key) != null;
-              } else {
-                List<PropertyAccessorElement> accessors = classElt.accessors;
-                for (int i = 0; i < accessors.length; i++) {
-                  if (accessors[i].name == key) {
-                    classHasMember = true;
-                  }
-                }
-              }
-              //
-              // Example: class A inherited only 2 method named 'm'.
-              // One has the function type '() -> int' and one has the function
-              // type '() -> String'. Since neither is a subtype of the other,
-              // we create a warning, and have this class inherit nothing.
-              //
-              if (!classHasMember) {
-                String firstTwoFuntionTypesStr =
-                    "${executableElementTypes[0]}, ${executableElementTypes[1]}";
-                _reportError(
-                    classElt,
-                    classElt.nameOffset,
-                    classElt.nameLength,
-                    StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE,
-                    [key, firstTwoFuntionTypesStr]);
-              }
-            } else {
-              //
-              // Example: class A inherits 2 methods named 'm'.
-              // One has the function type '(int) -> dynamic' and one has the
-              // function type '(num) -> dynamic'. Since they are both a subtype
-              // of the other, a synthetic function '(dynamic) -> dynamic' is
-              // inherited.
-              // Tests: test_getMapOfMembersInheritedFromInterfaces_
-              // union_multipleSubtypes_*
-              //
-              List<ExecutableElement> elementArrayToMerge =
-                  new List<ExecutableElement>(
-                      subtypesOfAllOtherTypesIndexes.length);
-              for (int i = 0; i < elementArrayToMerge.length; i++) {
-                elementArrayToMerge[i] =
-                    elements[subtypesOfAllOtherTypesIndexes[i]];
-              }
-              ExecutableElement mergedExecutableElement =
-                  _computeMergedExecutableElement(elementArrayToMerge);
-              resultMap.put(key, mergedExecutableElement);
-            }
-          }
-        } else {
-          _reportError(
-              classElt,
-              classElt.nameOffset,
-              classElt.nameLength,
-              StaticWarningCode
-                  .INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD,
-              [key]);
-        }
-      }
-    });
-    return resultMap;
-  }
-
-  /**
-   * Loop through all of the members in some [MemberMap], performing type parameter
-   * substitutions using a passed supertype.
-   *
-   * @param superType the supertype to substitute into the members of the [MemberMap]
-   * @param map the MemberMap to perform the substitutions on
-   */
-  void _substituteTypeParametersDownHierarchy(
-      InterfaceType superType, MemberMap map) {
-    for (int i = 0; i < map.size; i++) {
-      ExecutableElement executableElement = map.getValue(i);
-      if (executableElement is MethodMember) {
-        executableElement =
-            MethodMember.from(executableElement as MethodMember, superType);
-        map.setValue(i, executableElement);
-      } else if (executableElement is PropertyAccessorMember) {
-        executableElement = PropertyAccessorMember.from(
-            executableElement as PropertyAccessorMember, superType);
-        map.setValue(i, executableElement);
-      }
-    }
-  }
-
-  /**
-   * Union all of the [lookupMaps] together into a single map, grouping the ExecutableElements
-   * into a list where none of the elements are equal where equality is determined by having equal
-   * function types. (We also take note too of the kind of the element: ()->int and () -> int may
-   * not be equal if one is a getter and the other is a method.)
-   *
-   * @param lookupMaps the maps to be unioned together.
-   * @return the resulting union map.
-   */
-  HashMap<String, List<ExecutableElement>> _unionInterfaceLookupMaps(
-      List<MemberMap> lookupMaps) {
-    HashMap<String, List<ExecutableElement>> unionMap =
-        new HashMap<String, List<ExecutableElement>>();
-    for (MemberMap lookupMap in lookupMaps) {
-      int lookupMapSize = lookupMap.size;
-      for (int i = 0; i < lookupMapSize; i++) {
-        // Get the string key, if null, break.
-        String key = lookupMap.getKey(i);
-        if (key == null) {
-          break;
-        }
-        // Get the list value out of the unionMap
-        List<ExecutableElement> list = unionMap[key];
-        // If we haven't created such a map for this key yet, do create it and
-        // put the list entry into the unionMap.
-        if (list == null) {
-          list = new List<ExecutableElement>();
-          unionMap[key] = list;
-        }
-        // Fetch the entry out of this lookupMap
-        ExecutableElement newExecutableElementEntry = lookupMap.getValue(i);
-        if (list.isEmpty) {
-          // If the list is empty, just the new value
-          list.add(newExecutableElementEntry);
-        } else {
-          // Otherwise, only add the newExecutableElementEntry if it isn't
-          // already in the list, this covers situation where a class inherits
-          // two methods (or two getters) that are identical.
-          bool alreadyInList = false;
-          bool isMethod1 = newExecutableElementEntry is MethodElement;
-          for (ExecutableElement executableElementInList in list) {
-            bool isMethod2 = executableElementInList is MethodElement;
-            if (isMethod1 == isMethod2 &&
-                executableElementInList.type ==
-                    newExecutableElementEntry.type) {
-              alreadyInList = true;
-              break;
-            }
-          }
-          if (!alreadyInList) {
-            list.add(newExecutableElementEntry);
-          }
-        }
-      }
-    }
-    return unionMap;
-  }
-
-  /**
-   * Given some array of [ExecutableElement]s, this method creates a synthetic element as
-   * described in 8.1.1:
-   *
-   * Let <i>numberOfPositionals</i>(<i>f</i>) denote the number of positional parameters of a
-   * function <i>f</i>, and let <i>numberOfRequiredParams</i>(<i>f</i>) denote the number of
-   * required parameters of a function <i>f</i>. Furthermore, let <i>s</i> denote the set of all
-   * named parameters of the <i>m<sub>1</sub>, &hellip;, m<sub>k</sub></i>. Then let
-   * * <i>h = max(numberOfPositionals(m<sub>i</sub>)),</i>
-   * * <i>r = min(numberOfRequiredParams(m<sub>i</sub>)), for all <i>i</i>, 1 <= i <= k.</i>
-   * Then <i>I</i> has a method named <i>n</i>, with <i>r</i> required parameters of type
-   * <b>dynamic</b>, <i>h</i> positional parameters of type <b>dynamic</b>, named parameters
-   * <i>s</i> of type <b>dynamic</b> and return type <b>dynamic</b>.
-   *
-   */
-  static ExecutableElement _computeMergedExecutableElement(
-      List<ExecutableElement> elementArrayToMerge) {
-    int h = _getNumOfPositionalParameters(elementArrayToMerge[0]);
-    int r = _getNumOfRequiredParameters(elementArrayToMerge[0]);
-    Set<String> namedParametersList = new HashSet<String>();
-    for (int i = 1; i < elementArrayToMerge.length; i++) {
-      ExecutableElement element = elementArrayToMerge[i];
-      int numOfPositionalParams = _getNumOfPositionalParameters(element);
-      if (h < numOfPositionalParams) {
-        h = numOfPositionalParams;
-      }
-      int numOfRequiredParams = _getNumOfRequiredParameters(element);
-      if (r > numOfRequiredParams) {
-        r = numOfRequiredParams;
-      }
-      namedParametersList.addAll(_getNamedParameterNames(element));
-    }
-    return _createSyntheticExecutableElement(
-        elementArrayToMerge,
-        elementArrayToMerge[0].displayName,
-        r,
-        h - r,
-        new List.from(namedParametersList));
-  }
-
-  /**
-   * Used by [computeMergedExecutableElement] to actually create the
-   * synthetic element.
-   *
-   * @param elementArrayToMerge the array used to create the synthetic element
-   * @param name the name of the method, getter or setter
-   * @param numOfRequiredParameters the number of required parameters
-   * @param numOfPositionalParameters the number of positional parameters
-   * @param namedParameters the list of [String]s that are the named parameters
-   * @return the created synthetic element
-   */
-  static ExecutableElement _createSyntheticExecutableElement(
-      List<ExecutableElement> elementArrayToMerge,
-      String name,
-      int numOfRequiredParameters,
-      int numOfPositionalParameters,
-      List<String> namedParameters) {
-    DynamicTypeImpl dynamicType = DynamicTypeImpl.instance;
-    SimpleIdentifier nameIdentifier =
-        new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, name, 0));
-    ExecutableElementImpl executable;
-    if (elementArrayToMerge[0] is MethodElement) {
-      MultiplyInheritedMethodElementImpl unionedMethod =
-          new MultiplyInheritedMethodElementImpl(nameIdentifier);
-      unionedMethod.inheritedElements = elementArrayToMerge;
-      executable = unionedMethod;
-    } else {
-      MultiplyInheritedPropertyAccessorElementImpl unionedPropertyAccessor =
-          new MultiplyInheritedPropertyAccessorElementImpl(nameIdentifier);
-      unionedPropertyAccessor.getter =
-          (elementArrayToMerge[0] as PropertyAccessorElement).isGetter;
-      unionedPropertyAccessor.setter =
-          (elementArrayToMerge[0] as PropertyAccessorElement).isSetter;
-      unionedPropertyAccessor.inheritedElements = elementArrayToMerge;
-      executable = unionedPropertyAccessor;
-    }
-    int numOfParameters = numOfRequiredParameters +
-        numOfPositionalParameters +
-        namedParameters.length;
-    List<ParameterElement> parameters =
-        new List<ParameterElement>(numOfParameters);
-    int i = 0;
-    for (int j = 0; j < numOfRequiredParameters; j++, i++) {
-      ParameterElementImpl parameter = new ParameterElementImpl("", 0);
-      parameter.type = dynamicType;
-      parameter.parameterKind = ParameterKind.REQUIRED;
-      parameters[i] = parameter;
-    }
-    for (int k = 0; k < numOfPositionalParameters; k++, i++) {
-      ParameterElementImpl parameter = new ParameterElementImpl("", 0);
-      parameter.type = dynamicType;
-      parameter.parameterKind = ParameterKind.POSITIONAL;
-      parameters[i] = parameter;
-    }
-    for (int m = 0; m < namedParameters.length; m++, i++) {
-      ParameterElementImpl parameter =
-          new ParameterElementImpl(namedParameters[m], 0);
-      parameter.type = dynamicType;
-      parameter.parameterKind = ParameterKind.NAMED;
-      parameters[i] = parameter;
-    }
-    executable.returnType = dynamicType;
-    executable.parameters = parameters;
-    FunctionTypeImpl methodType = new FunctionTypeImpl(executable);
-    executable.type = methodType;
-    return executable;
-  }
-
-  /**
-   * Given some [ExecutableElement], return the list of named parameters.
-   */
-  static List<String> _getNamedParameterNames(
-      ExecutableElement executableElement) {
-    List<String> namedParameterNames = new List<String>();
-    List<ParameterElement> parameters = executableElement.parameters;
-    for (int i = 0; i < parameters.length; i++) {
-      ParameterElement parameterElement = parameters[i];
-      if (parameterElement.parameterKind == ParameterKind.NAMED) {
-        namedParameterNames.add(parameterElement.name);
-      }
-    }
-    return namedParameterNames;
-  }
-
-  /**
-   * Given some [ExecutableElement] return the number of parameters of the specified kind.
-   */
-  static int _getNumOfParameters(
-      ExecutableElement executableElement, ParameterKind parameterKind) {
-    int parameterCount = 0;
-    List<ParameterElement> parameters = executableElement.parameters;
-    for (int i = 0; i < parameters.length; i++) {
-      ParameterElement parameterElement = parameters[i];
-      if (parameterElement.parameterKind == parameterKind) {
-        parameterCount++;
-      }
-    }
-    return parameterCount;
-  }
-
-  /**
-   * Given some [ExecutableElement] return the number of positional parameters.
-   *
-   * Note: by positional we mean [ParameterKind.REQUIRED] or [ParameterKind.POSITIONAL].
-   */
-  static int _getNumOfPositionalParameters(
-          ExecutableElement executableElement) =>
-      _getNumOfParameters(executableElement, ParameterKind.REQUIRED) +
-      _getNumOfParameters(executableElement, ParameterKind.POSITIONAL);
-
-  /**
-   * Given some [ExecutableElement] return the number of required parameters.
-   */
-  static int _getNumOfRequiredParameters(ExecutableElement executableElement) =>
-      _getNumOfParameters(executableElement, ParameterKind.REQUIRED);
-
-  /**
-   * Given some [ExecutableElement] returns `true` if it is an abstract member of a
-   * class.
-   *
-   * @param executableElement some [ExecutableElement] to evaluate
-   * @return `true` if the given element is an abstract member of a class
-   */
-  static bool _isAbstract(ExecutableElement executableElement) {
-    if (executableElement is MethodElement) {
-      return executableElement.isAbstract;
-    } else if (executableElement is PropertyAccessorElement) {
-      return executableElement.isAbstract;
-    }
-    return false;
-  }
-}
-
-/**
  * This enum holds one of four states of a field initialization state through a constructor
  * signature, not initialized, initialized in the field declaration, initialized in the field
  * formal, and finally, initialized in the initializers list.
@@ -6167,798 +4892,92 @@
 }
 
 /**
- * Instances of the class `LabelScope` represent a scope in which a single label is defined.
+ * An AST visitor that is used to re-resolve the initializers of instance
+ * fields. Although this class is an AST visitor, clients are expected to use
+ * the method [resolveCompilationUnit] to run it over a compilation unit.
  */
-class LabelScope {
+class InstanceFieldResolverVisitor extends ResolverVisitor {
   /**
-   * The label scope enclosing this label scope.
-   */
-  final LabelScope _outerScope;
-
-  /**
-   * The label defined in this scope.
-   */
-  final String _label;
-
-  /**
-   * The element to which the label resolves.
-   */
-  final LabelElement element;
-
-  /**
-   * The AST node to which the label resolves.
-   */
-  final AstNode node;
-
-  /**
-   * Initialize a newly created scope to represent the label [_label].
-   * [_outerScope] is the scope enclosing the new label scope.  [node] is the
-   * AST node the label resolves to.  [element] is the element the label
-   * resolves to.
-   */
-  LabelScope(this._outerScope, this._label, this.node, this.element);
-
-  /**
-   * Return the LabelScope which defines [targetLabel], or `null` if it is not
-   * defined in this scope.
-   */
-  LabelScope lookup(String targetLabel) {
-    if (_label == targetLabel) {
-      return this;
-    } else if (_outerScope != null) {
-      return _outerScope.lookup(targetLabel);
-    } else {
-      return null;
-    }
-  }
-}
-
-/**
- * Instances of the class `LibraryImportScope` represent the scope containing all of the names
- * available from imported libraries.
- */
-class LibraryImportScope extends Scope {
-  /**
-   * The element representing the library in which this scope is enclosed.
-   */
-  final LibraryElement _definingLibrary;
-
-  /**
-   * The listener that is to be informed when an error is encountered.
-   */
-  @override
-  final AnalysisErrorListener errorListener;
-
-  /**
-   * A list of the namespaces representing the names that are available in this scope from imported
-   * libraries.
-   */
-  List<Namespace> _importedNamespaces;
-
-  /**
-   * Initialize a newly created scope representing the names imported into the given library.
+   * Initialize a newly created visitor to resolve the nodes in an AST node.
    *
-   * @param definingLibrary the element representing the library that imports the names defined in
-   *          this scope
-   * @param errorListener the listener that is to be informed when an error is encountered
+   * The [definingLibrary] is the element for the library containing the node
+   * being visited. The [source] is the source representing the compilation unit
+   * containing the node being visited. The [typeProvider] is the object used to
+   * access the types from the core library. The [errorListener] is the error
+   * listener that will be informed of any errors that are found during
+   * resolution. The [nameScope] is the scope used to resolve identifiers in the
+   * node that will first be visited.  If `null` or unspecified, a new
+   * [LibraryScope] will be created based on the [definingLibrary].
    */
-  LibraryImportScope(this._definingLibrary, this.errorListener) {
-    _createImportedNamespaces();
-  }
+  InstanceFieldResolverVisitor(LibraryElement definingLibrary, Source source,
+      TypeProvider typeProvider, AnalysisErrorListener errorListener,
+      {Scope nameScope})
+      : super(definingLibrary, source, typeProvider, errorListener,
+            nameScope: nameScope);
 
-  @override
-  void define(Element element) {
-    if (!Scope.isPrivateName(element.displayName)) {
-      super.define(element);
-    }
-  }
-
-  @override
-  Source getSource(AstNode node) {
-    Source source = super.getSource(node);
-    if (source == null) {
-      source = _definingLibrary.definingCompilationUnit.source;
-    }
-    return source;
-  }
-
-  @override
-  Element internalLookup(
-      Identifier identifier, String name, LibraryElement referencingLibrary) {
-    Element foundElement = localLookup(name, referencingLibrary);
-    if (foundElement != null) {
-      return foundElement;
-    }
-    for (int i = 0; i < _importedNamespaces.length; i++) {
-      Namespace nameSpace = _importedNamespaces[i];
-      Element element = nameSpace.get(name);
-      if (element != null) {
-        if (foundElement == null) {
-          foundElement = element;
-        } else if (!identical(foundElement, element)) {
-          foundElement = MultiplyDefinedElementImpl.fromElements(
-              _definingLibrary.context, foundElement, element);
+  /**
+   * Resolve the instance fields in the given compilation unit [node].
+   */
+  void resolveCompilationUnit(CompilationUnit node) {
+    _overrideManager.enterScope();
+    try {
+      NodeList<CompilationUnitMember> declarations = node.declarations;
+      int declarationCount = declarations.length;
+      for (int i = 0; i < declarationCount; i++) {
+        CompilationUnitMember declaration = declarations[i];
+        if (declaration is ClassDeclaration) {
+          _resolveClassDeclaration(declaration);
         }
       }
-    }
-    if (foundElement is MultiplyDefinedElementImpl) {
-      foundElement = _removeSdkElements(
-          identifier, name, foundElement as MultiplyDefinedElementImpl);
-    }
-    if (foundElement is MultiplyDefinedElementImpl) {
-      String foundEltName = foundElement.displayName;
-      List<Element> conflictingMembers = foundElement.conflictingElements;
-      int count = conflictingMembers.length;
-      List<String> libraryNames = new List<String>(count);
-      for (int i = 0; i < count; i++) {
-        libraryNames[i] = _getLibraryName(conflictingMembers[i]);
-      }
-      libraryNames.sort();
-      errorListener.onError(new AnalysisError(
-          getSource(identifier),
-          identifier.offset,
-          identifier.length,
-          StaticWarningCode.AMBIGUOUS_IMPORT, [
-        foundEltName,
-        StringUtilities.printListOfQuotedNames(libraryNames)
-      ]));
-      return foundElement;
-    }
-    if (foundElement != null) {
-      defineNameWithoutChecking(name, foundElement);
-    }
-    return foundElement;
-  }
-
-  /**
-   * Create all of the namespaces associated with the libraries imported into this library. The
-   * names are not added to this scope, but are stored for later reference.
-   *
-   * @param definingLibrary the element representing the library that imports the libraries for
-   *          which namespaces will be created
-   */
-  void _createImportedNamespaces() {
-    NamespaceBuilder builder = new NamespaceBuilder();
-    List<ImportElement> imports = _definingLibrary.imports;
-    int count = imports.length;
-    _importedNamespaces = new List<Namespace>(count);
-    for (int i = 0; i < count; i++) {
-      _importedNamespaces[i] =
-          builder.createImportNamespaceForDirective(imports[i]);
+    } finally {
+      _overrideManager.exitScope();
     }
   }
 
   /**
-   * Returns the name of the library that defines given element.
-   *
-   * @param element the element to get library name
-   * @return the name of the library that defines given element
+   * Resolve the instance fields in the given class declaration [node].
    */
-  String _getLibraryName(Element element) {
-    if (element == null) {
-      return StringUtilities.EMPTY;
-    }
-    LibraryElement library = element.library;
-    if (library == null) {
-      return StringUtilities.EMPTY;
-    }
-    List<ImportElement> imports = _definingLibrary.imports;
-    int count = imports.length;
-    for (int i = 0; i < count; i++) {
-      if (identical(imports[i].importedLibrary, library)) {
-        return library.definingCompilationUnit.displayName;
-      }
-    }
-    List<String> indirectSources = new List<String>();
-    for (int i = 0; i < count; i++) {
-      LibraryElement importedLibrary = imports[i].importedLibrary;
-      if (importedLibrary != null) {
-        for (LibraryElement exportedLibrary
-            in importedLibrary.exportedLibraries) {
-          if (identical(exportedLibrary, library)) {
-            indirectSources
-                .add(importedLibrary.definingCompilationUnit.displayName);
+  void _resolveClassDeclaration(ClassDeclaration node) {
+    _enclosingClassDeclaration = node;
+    ClassElement outerType = enclosingClass;
+    Scope outerScope = nameScope;
+    try {
+      enclosingClass = node.element;
+      typeAnalyzer.thisType = enclosingClass?.type;
+      if (enclosingClass == null) {
+        AnalysisEngine.instance.logger.logInformation(
+            "Missing element for class declaration ${node.name.name} in ${definingLibrary.source.fullName}",
+            new CaughtException(new AnalysisException(), null));
+        // Don't try to re-resolve the initializers if we cannot set up the
+        // right name scope for resolution.
+      } else {
+        nameScope = new ClassScope(nameScope, enclosingClass);
+        NodeList<ClassMember> members = node.members;
+        int length = members.length;
+        for (int i = 0; i < length; i++) {
+          ClassMember member = members[i];
+          if (member is FieldDeclaration) {
+            _resolveFieldDeclaration(member);
           }
         }
       }
-    }
-    int indirectCount = indirectSources.length;
-    StringBuffer buffer = new StringBuffer();
-    buffer.write(library.definingCompilationUnit.displayName);
-    if (indirectCount > 0) {
-      buffer.write(" (via ");
-      if (indirectCount > 1) {
-        indirectSources.sort();
-        buffer.write(StringUtilities.printListOfQuotedNames(indirectSources));
-      } else {
-        buffer.write(indirectSources[0]);
-      }
-      buffer.write(")");
-    }
-    return buffer.toString();
-  }
-
-  /**
-   * Given a collection of elements (captured by the [foundElement]) that the
-   * [identifier] (with the given [name]) resolved to, remove from the list all
-   * of the names defined in the SDK and return the element(s) that remain.
-   */
-  Element _removeSdkElements(Identifier identifier, String name,
-      MultiplyDefinedElementImpl foundElement) {
-    List<Element> conflictingElements = foundElement.conflictingElements;
-    List<Element> nonSdkElements = new List<Element>();
-    Element sdkElement = null;
-    for (Element member in conflictingElements) {
-      if (member.library.isInSdk) {
-        sdkElement = member;
-      } else {
-        nonSdkElements.add(member);
-      }
-    }
-    if (sdkElement != null && nonSdkElements.length > 0) {
-      String sdkLibName = _getLibraryName(sdkElement);
-      String otherLibName = _getLibraryName(nonSdkElements[0]);
-      errorListener.onError(new AnalysisError(
-          getSource(identifier),
-          identifier.offset,
-          identifier.length,
-          StaticWarningCode.CONFLICTING_DART_IMPORT,
-          [name, sdkLibName, otherLibName]));
-    }
-    if (nonSdkElements.length == conflictingElements.length) {
-      // None of the members were removed
-      return foundElement;
-    } else if (nonSdkElements.length == 1) {
-      // All but one member was removed
-      return nonSdkElements[0];
-    } else if (nonSdkElements.length == 0) {
-      // All members were removed
-      AnalysisEngine.instance.logger
-          .logInformation("Multiply defined SDK element: $foundElement");
-      return foundElement;
-    }
-    return new MultiplyDefinedElementImpl(
-        _definingLibrary.context, nonSdkElements);
-  }
-}
-
-/**
- * Instances of the class `LibraryScope` implement a scope containing all of the names defined
- * in a given library.
- */
-class LibraryScope extends EnclosedScope {
-  /**
-   * Initialize a newly created scope representing the names defined in the given library.
-   *
-   * @param definingLibrary the element representing the library represented by this scope
-   * @param errorListener the listener that is to be informed when an error is encountered
-   */
-  LibraryScope(
-      LibraryElement definingLibrary, AnalysisErrorListener errorListener)
-      : super(new LibraryImportScope(definingLibrary, errorListener)) {
-    _defineTopLevelNames(definingLibrary);
-  }
-
-  @override
-  AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
-    if (existing is PrefixElement) {
-      // TODO(scheglov) consider providing actual 'nameOffset' from the
-      // synthetic accessor
-      int offset = duplicate.nameOffset;
-      if (duplicate is PropertyAccessorElement) {
-        PropertyAccessorElement accessor = duplicate;
-        if (accessor.isSynthetic) {
-          offset = accessor.variable.nameOffset;
-        }
-      }
-      return new AnalysisError(
-          duplicate.source,
-          offset,
-          duplicate.nameLength,
-          CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER,
-          [existing.displayName]);
-    }
-    return super.getErrorForDuplicate(existing, duplicate);
-  }
-
-  /**
-   * Add to this scope all of the public top-level names that are defined in the given compilation
-   * unit.
-   *
-   * @param compilationUnit the compilation unit defining the top-level names to be added to this
-   *          scope
-   */
-  void _defineLocalNames(CompilationUnitElement compilationUnit) {
-    for (PropertyAccessorElement element in compilationUnit.accessors) {
-      define(element);
-    }
-    for (ClassElement element in compilationUnit.enums) {
-      define(element);
-    }
-    for (FunctionElement element in compilationUnit.functions) {
-      define(element);
-    }
-    for (FunctionTypeAliasElement element
-        in compilationUnit.functionTypeAliases) {
-      define(element);
-    }
-    for (ClassElement element in compilationUnit.types) {
-      define(element);
-    }
-  }
-
-  /**
-   * Add to this scope all of the names that are explicitly defined in the given library.
-   *
-   * @param definingLibrary the element representing the library that defines the names in this
-   *          scope
-   */
-  void _defineTopLevelNames(LibraryElement definingLibrary) {
-    for (PrefixElement prefix in definingLibrary.prefixes) {
-      define(prefix);
-    }
-    _defineLocalNames(definingLibrary.definingCompilationUnit);
-    for (CompilationUnitElement compilationUnit in definingLibrary.parts) {
-      _defineLocalNames(compilationUnit);
-    }
-  }
-}
-
-/**
- * This class is used to replace uses of `HashMap<String, ExecutableElement>`
- * which are not as performant as this class.
- */
-class MemberMap {
-  /**
-   * The current size of this map.
-   */
-  int _size = 0;
-
-  /**
-   * The array of keys.
-   */
-  List<String> _keys;
-
-  /**
-   * The array of ExecutableElement values.
-   */
-  List<ExecutableElement> _values;
-
-  /**
-   * Initialize a newly created member map to have the given [initialCapacity].
-   * The map will grow if needed.
-   */
-  MemberMap([int initialCapacity = 10]) {
-    _initArrays(initialCapacity);
-  }
-
-  /**
-   * Initialize a newly created member map to contain the same members as the
-   * given [memberMap].
-   */
-  MemberMap.from(MemberMap memberMap) {
-    _initArrays(memberMap._size + 5);
-    for (int i = 0; i < memberMap._size; i++) {
-      _keys[i] = memberMap._keys[i];
-      _values[i] = memberMap._values[i];
-    }
-    _size = memberMap._size;
-  }
-
-  /**
-   * The size of the map.
-   *
-   * @return the size of the map.
-   */
-  int get size => _size;
-
-  /**
-   * Given some key, return the ExecutableElement value from the map, if the key does not exist in
-   * the map, `null` is returned.
-   *
-   * @param key some key to look up in the map
-   * @return the associated ExecutableElement value from the map, if the key does not exist in the
-   *         map, `null` is returned
-   */
-  ExecutableElement get(String key) {
-    for (int i = 0; i < _size; i++) {
-      if (_keys[i] != null && _keys[i] == key) {
-        return _values[i];
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Get and return the key at the specified location. If the key/value pair has been removed from
-   * the set, then `null` is returned.
-   *
-   * @param i some non-zero value less than size
-   * @return the key at the passed index
-   * @throw ArrayIndexOutOfBoundsException this exception is thrown if the passed index is less than
-   *        zero or greater than or equal to the capacity of the arrays
-   */
-  String getKey(int i) => _keys[i];
-
-  /**
-   * Get and return the ExecutableElement at the specified location. If the key/value pair has been
-   * removed from the set, then then `null` is returned.
-   *
-   * @param i some non-zero value less than size
-   * @return the key at the passed index
-   * @throw ArrayIndexOutOfBoundsException this exception is thrown if the passed index is less than
-   *        zero or greater than or equal to the capacity of the arrays
-   */
-  ExecutableElement getValue(int i) => _values[i];
-
-  /**
-   * Given some key/value pair, store the pair in the map. If the key exists already, then the new
-   * value overrides the old value.
-   *
-   * @param key the key to store in the map
-   * @param value the ExecutableElement value to store in the map
-   */
-  void put(String key, ExecutableElement value) {
-    // If we already have a value with this key, override the value
-    for (int i = 0; i < _size; i++) {
-      if (_keys[i] != null && _keys[i] == key) {
-        _values[i] = value;
-        return;
-      }
-    }
-    // If needed, double the size of our arrays and copy values over in both
-    // arrays
-    if (_size == _keys.length) {
-      int newArrayLength = _size * 2;
-      List<String> keys_new_array = new List<String>(newArrayLength);
-      List<ExecutableElement> values_new_array =
-          new List<ExecutableElement>(newArrayLength);
-      for (int i = 0; i < _size; i++) {
-        keys_new_array[i] = _keys[i];
-      }
-      for (int i = 0; i < _size; i++) {
-        values_new_array[i] = _values[i];
-      }
-      _keys = keys_new_array;
-      _values = values_new_array;
-    }
-    // Put new value at end of array
-    _keys[_size] = key;
-    _values[_size] = value;
-    _size++;
-  }
-
-  /**
-   * Given some [String] key, this method replaces the associated key and value pair with
-   * `null`. The size is not decremented with this call, instead it is expected that the users
-   * check for `null`.
-   *
-   * @param key the key of the key/value pair to remove from the map
-   */
-  void remove(String key) {
-    for (int i = 0; i < _size; i++) {
-      if (_keys[i] == key) {
-        _keys[i] = null;
-        _values[i] = null;
-        return;
-      }
-    }
-  }
-
-  /**
-   * Sets the ExecutableElement at the specified location.
-   *
-   * @param i some non-zero value less than size
-   * @param value the ExecutableElement value to store in the map
-   */
-  void setValue(int i, ExecutableElement value) {
-    _values[i] = value;
-  }
-
-  /**
-   * Initializes [keys] and [values].
-   */
-  void _initArrays(int initialCapacity) {
-    _keys = new List<String>(initialCapacity);
-    _values = new List<ExecutableElement>(initialCapacity);
-  }
-}
-
-/**
- * Instances of the class `Namespace` implement a mapping of identifiers to the elements
- * represented by those identifiers. Namespaces are the building blocks for scopes.
- */
-class Namespace {
-  /**
-   * An empty namespace.
-   */
-  static Namespace EMPTY = new Namespace(new HashMap<String, Element>());
-
-  /**
-   * A table mapping names that are defined in this namespace to the element representing the thing
-   * declared with that name.
-   */
-  final HashMap<String, Element> _definedNames;
-
-  /**
-   * Initialize a newly created namespace to have the given defined names.
-   *
-   * @param definedNames the mapping from names that are defined in this namespace to the
-   *          corresponding elements
-   */
-  Namespace(this._definedNames);
-
-  /**
-   * Return a table containing the same mappings as those defined by this namespace.
-   *
-   * @return a table containing the same mappings as those defined by this namespace
-   */
-  Map<String, Element> get definedNames => _definedNames;
-
-  /**
-   * Return the element in this namespace that is available to the containing scope using the given
-   * name.
-   *
-   * @param name the name used to reference the
-   * @return the element represented by the given identifier
-   */
-  Element get(String name) => _definedNames[name];
-}
-
-/**
- * Instances of the class `NamespaceBuilder` are used to build a `Namespace`. Namespace
- * builders are thread-safe and re-usable.
- */
-class NamespaceBuilder {
-  /**
-   * Create a namespace representing the export namespace of the given [ExportElement].
-   *
-   * @param element the export element whose export namespace is to be created
-   * @return the export namespace that was created
-   */
-  Namespace createExportNamespaceForDirective(ExportElement element) {
-    LibraryElement exportedLibrary = element.exportedLibrary;
-    if (exportedLibrary == null) {
-      //
-      // The exported library will be null if the URI does not reference a valid
-      // library.
-      //
-      return Namespace.EMPTY;
-    }
-    HashMap<String, Element> exportedNames = _getExportMapping(exportedLibrary);
-    exportedNames = _applyCombinators(exportedNames, element.combinators);
-    return new Namespace(exportedNames);
-  }
-
-  /**
-   * Create a namespace representing the export namespace of the given library.
-   *
-   * @param library the library whose export namespace is to be created
-   * @return the export namespace that was created
-   */
-  Namespace createExportNamespaceForLibrary(LibraryElement library) {
-    HashMap<String, Element> exportedNames = _getExportMapping(library);
-    return new Namespace(exportedNames);
-  }
-
-  /**
-   * Create a namespace representing the import namespace of the given library.
-   *
-   * @param library the library whose import namespace is to be created
-   * @return the import namespace that was created
-   */
-  Namespace createImportNamespaceForDirective(ImportElement element) {
-    LibraryElement importedLibrary = element.importedLibrary;
-    if (importedLibrary == null) {
-      //
-      // The imported library will be null if the URI does not reference a valid
-      // library.
-      //
-      return Namespace.EMPTY;
-    }
-    HashMap<String, Element> exportedNames = _getExportMapping(importedLibrary);
-    exportedNames = _applyCombinators(exportedNames, element.combinators);
-    exportedNames = _applyPrefix(exportedNames, element.prefix);
-    return new Namespace(exportedNames);
-  }
-
-  /**
-   * Create a namespace representing the public namespace of the given library.
-   *
-   * @param library the library whose public namespace is to be created
-   * @return the public namespace that was created
-   */
-  Namespace createPublicNamespaceForLibrary(LibraryElement library) {
-    HashMap<String, Element> definedNames = new HashMap<String, Element>();
-    _addPublicNames(definedNames, library.definingCompilationUnit);
-    for (CompilationUnitElement compilationUnit in library.parts) {
-      _addPublicNames(definedNames, compilationUnit);
-    }
-    return new Namespace(definedNames);
-  }
-
-  /**
-   * Add all of the names in the given namespace to the given mapping table.
-   *
-   * @param definedNames the mapping table to which the names in the given namespace are to be added
-   * @param namespace the namespace containing the names to be added to this namespace
-   */
-  void _addAllFromNamespace(
-      Map<String, Element> definedNames, Namespace namespace) {
-    if (namespace != null) {
-      definedNames.addAll(namespace.definedNames);
-    }
-  }
-
-  /**
-   * Add the given element to the given mapping table if it has a publicly visible name.
-   *
-   * @param definedNames the mapping table to which the public name is to be added
-   * @param element the element to be added
-   */
-  void _addIfPublic(Map<String, Element> definedNames, Element element) {
-    String name = element.name;
-    if (name != null && !Scope.isPrivateName(name)) {
-      definedNames[name] = element;
-    }
-  }
-
-  /**
-   * Add to the given mapping table all of the public top-level names that are defined in the given
-   * compilation unit.
-   *
-   * @param definedNames the mapping table to which the public names are to be added
-   * @param compilationUnit the compilation unit defining the top-level names to be added to this
-   *          namespace
-   */
-  void _addPublicNames(Map<String, Element> definedNames,
-      CompilationUnitElement compilationUnit) {
-    for (PropertyAccessorElement element in compilationUnit.accessors) {
-      _addIfPublic(definedNames, element);
-    }
-    for (ClassElement element in compilationUnit.enums) {
-      _addIfPublic(definedNames, element);
-    }
-    for (FunctionElement element in compilationUnit.functions) {
-      _addIfPublic(definedNames, element);
-    }
-    for (FunctionTypeAliasElement element
-        in compilationUnit.functionTypeAliases) {
-      _addIfPublic(definedNames, element);
-    }
-    for (ClassElement element in compilationUnit.types) {
-      _addIfPublic(definedNames, element);
-    }
-  }
-
-  /**
-   * Apply the given combinators to all of the names in the given mapping table.
-   *
-   * @param definedNames the mapping table to which the namespace operations are to be applied
-   * @param combinators the combinators to be applied
-   */
-  HashMap<String, Element> _applyCombinators(
-      HashMap<String, Element> definedNames,
-      List<NamespaceCombinator> combinators) {
-    for (NamespaceCombinator combinator in combinators) {
-      if (combinator is HideElementCombinator) {
-        definedNames = _hide(definedNames, combinator.hiddenNames);
-      } else if (combinator is ShowElementCombinator) {
-        definedNames = _show(definedNames, combinator.shownNames);
-      } else {
-        // Internal error.
-        AnalysisEngine.instance.logger
-            .logError("Unknown type of combinator: ${combinator.runtimeType}");
-      }
-    }
-    return definedNames;
-  }
-
-  /**
-   * Apply the given prefix to all of the names in the table of defined names.
-   *
-   * @param definedNames the names that were defined before this operation
-   * @param prefixElement the element defining the prefix to be added to the names
-   */
-  HashMap<String, Element> _applyPrefix(
-      HashMap<String, Element> definedNames, PrefixElement prefixElement) {
-    if (prefixElement != null) {
-      String prefix = prefixElement.name;
-      HashMap<String, Element> newNames = new HashMap<String, Element>();
-      definedNames.forEach((String name, Element element) {
-        newNames["$prefix.$name"] = element;
-      });
-      return newNames;
-    } else {
-      return definedNames;
-    }
-  }
-
-  /**
-   * Create a mapping table representing the export namespace of the given library.
-   *
-   * @param library the library whose public namespace is to be created
-   * @param visitedElements a set of libraries that do not need to be visited when processing the
-   *          export directives of the given library because all of the names defined by them will
-   *          be added by another library
-   * @return the mapping table that was created
-   */
-  HashMap<String, Element> _computeExportMapping(
-      LibraryElement library, HashSet<LibraryElement> visitedElements) {
-    visitedElements.add(library);
-    try {
-      HashMap<String, Element> definedNames = new HashMap<String, Element>();
-      for (ExportElement element in library.exports) {
-        LibraryElement exportedLibrary = element.exportedLibrary;
-        if (exportedLibrary != null &&
-            !visitedElements.contains(exportedLibrary)) {
-          //
-          // The exported library will be null if the URI does not reference a
-          // valid library.
-          //
-          HashMap<String, Element> exportedNames =
-              _computeExportMapping(exportedLibrary, visitedElements);
-          exportedNames = _applyCombinators(exportedNames, element.combinators);
-          definedNames.addAll(exportedNames);
-        }
-      }
-      _addAllFromNamespace(
-          definedNames,
-          (library.context as InternalAnalysisContext)
-              .getPublicNamespace(library));
-      return definedNames;
     } finally {
-      visitedElements.remove(library);
+      nameScope = outerScope;
+      typeAnalyzer.thisType = outerType?.type;
+      enclosingClass = outerType;
+      _enclosingClassDeclaration = null;
     }
   }
 
-  HashMap<String, Element> _getExportMapping(LibraryElement library) {
-    if (library is LibraryElementImpl) {
-      if (library.exportNamespace != null) {
-        return library.exportNamespace.definedNames;
-      } else {
-        HashMap<String, Element> exportMapping =
-            _computeExportMapping(library, new HashSet<LibraryElement>());
-        library.exportNamespace = new Namespace(exportMapping);
-        return exportMapping;
-      }
-    }
-    return _computeExportMapping(library, new HashSet<LibraryElement>());
-  }
-
   /**
-   * Return a new map of names which has all the names from [definedNames]
-   * with exception of [hiddenNames].
+   * Resolve the instance fields in the given field declaration [node].
    */
-  Map<String, Element> _hide(
-      HashMap<String, Element> definedNames, List<String> hiddenNames) {
-    HashMap<String, Element> newNames =
-        new HashMap<String, Element>.from(definedNames);
-    for (String name in hiddenNames) {
-      newNames.remove(name);
-      newNames.remove("$name=");
-    }
-    return newNames;
-  }
-
-  /**
-   * Return a new map of names which has only [shownNames] from [definedNames].
-   */
-  HashMap<String, Element> _show(
-      HashMap<String, Element> definedNames, List<String> shownNames) {
-    HashMap<String, Element> newNames = new HashMap<String, Element>();
-    for (String name in shownNames) {
-      Element element = definedNames[name];
-      if (element != null) {
-        newNames[name] = element;
-      }
-      String setterName = "$name=";
-      element = definedNames[setterName];
-      if (element != null) {
-        newNames[setterName] = element;
+  void _resolveFieldDeclaration(FieldDeclaration node) {
+    if (!node.isStatic) {
+      for (VariableDeclaration field in node.fields.variables) {
+        field.initializer?.accept(this);
       }
     }
-    return newNames;
   }
 }
 
@@ -7434,13 +5453,6 @@
   TypeSystem typeSystem;
 
   /**
-   * The class element representing the class containing the current node,
-   * or `null` if the current node is not contained in a class.
-   */
-  @override
-  ClassElement enclosingClass = null;
-
-  /**
    * The class declaration representing the class containing the current node, or `null` if
    * the current node is not contained in a class.
    */
@@ -7596,20 +5608,15 @@
     while (expression is ParenthesizedExpression) {
       expression = (expression as ParenthesizedExpression).expression;
     }
-    if (expression is! SimpleIdentifier) {
-      return null;
-    }
-    SimpleIdentifier identifier = expression as SimpleIdentifier;
-    Element element = identifier.staticElement;
-    if (element is! VariableElement) {
-      return null;
-    }
-    ElementKind kind = element.kind;
-    if (kind == ElementKind.LOCAL_VARIABLE) {
-      return element as VariableElement;
-    }
-    if (kind == ElementKind.PARAMETER) {
-      return element as VariableElement;
+    if (expression is SimpleIdentifier) {
+      Element element = expression.staticElement;
+      if (element is VariableElement) {
+        ElementKind kind = element.kind;
+        if (kind == ElementKind.LOCAL_VARIABLE ||
+            kind == ElementKind.PARAMETER) {
+          return element;
+        }
+      }
     }
     return null;
   }
@@ -8080,16 +6087,6 @@
 
   @override
   Object visitCompilationUnit(CompilationUnit node) {
-    //
-    // TODO(brianwilkerson) The goal of the code below is to visit the
-    // declarations in such an order that we can infer type information for
-    // top-level variables before we visit references to them. This is better
-    // than making no effort, but still doesn't completely satisfy that goal
-    // (consider for example "final var a = b; final var b = 0;"; we'll infer a
-    // type of 'int' for 'b', but not for 'a' because of the order of the
-    // visits). Ideally we would create a dependency graph, but that would
-    // require references to be resolved, which they are not.
-    //
     _overrideManager.enterScope();
     try {
       NodeList<Directive> directives = node.directives;
@@ -8100,16 +6097,7 @@
       NodeList<CompilationUnitMember> declarations = node.declarations;
       int declarationCount = declarations.length;
       for (int i = 0; i < declarationCount; i++) {
-        CompilationUnitMember declaration = declarations[i];
-        if (declaration is! ClassDeclaration) {
-          declaration.accept(this);
-        }
-      }
-      for (int i = 0; i < declarationCount; i++) {
-        CompilationUnitMember declaration = declarations[i];
-        if (declaration is ClassDeclaration) {
-          declaration.accept(this);
-        }
+        declarations[i].accept(this);
       }
     } finally {
       _overrideManager.exitScope();
@@ -8518,7 +6506,7 @@
     Expression condition = node.condition;
     condition?.accept(this);
     Map<VariableElement, DartType> thenOverrides =
-        new HashMap<VariableElement, DartType>();
+        const <VariableElement, DartType>{};
     Statement thenStatement = node.thenStatement;
     if (thenStatement != null) {
       _overrideManager.enterScope();
@@ -8542,7 +6530,7 @@
       }
     }
     Map<VariableElement, DartType> elseOverrides =
-        new HashMap<VariableElement, DartType>();
+        const <VariableElement, DartType>{};
     Statement elseStatement = node.elseStatement;
     if (elseStatement != null) {
       _overrideManager.enterScope();
@@ -8567,7 +6555,7 @@
       _overrideManager.applyOverrides(elseOverrides);
     } else if (!thenIsAbrupt && !elseIsAbrupt) {
       List<Map<VariableElement, DartType>> perBranchOverrides =
-          new List<Map<VariableElement, DartType>>();
+          <Map<VariableElement, DartType>>[];
       perBranchOverrides.add(thenOverrides);
       perBranchOverrides.add(elseOverrides);
       _overrideManager.mergeOverrides(perBranchOverrides);
@@ -8864,7 +6852,7 @@
   @override
   visitVariableDeclarationList(VariableDeclarationList node) {
     for (VariableDeclaration decl in node.variables) {
-      InferenceContext.setType(decl, node.type?.type);
+      InferenceContext.setType(decl, decl.element?.type);
     }
     super.visitVariableDeclarationList(node);
   }
@@ -9010,18 +6998,16 @@
   DartType _getIteratorElementType(Expression iteratorExpression) {
     DartType expressionType = iteratorExpression.bestType;
     if (expressionType is InterfaceType) {
-      InterfaceType interfaceType = expressionType;
       PropertyAccessorElement iteratorFunction =
-          interfaceType.lookUpInheritedGetter("iterator");
+          expressionType.lookUpInheritedGetter("iterator");
       if (iteratorFunction == null) {
         // TODO(brianwilkerson) Should we report this error?
         return null;
       }
       DartType iteratorType = iteratorFunction.returnType;
       if (iteratorType is InterfaceType) {
-        InterfaceType iteratorInterfaceType = iteratorType;
         PropertyAccessorElement currentFunction =
-            iteratorInterfaceType.lookUpInheritedGetter("current");
+            iteratorType.lookUpInheritedGetter("current");
         if (currentFunction == null) {
           // TODO(brianwilkerson) Should we report this error?
           return null;
@@ -9285,18 +7271,16 @@
    */
   void _promoteTypes(Expression condition) {
     if (condition is BinaryExpression) {
-      BinaryExpression binary = condition;
-      if (binary.operator.type == TokenType.AMPERSAND_AMPERSAND) {
-        Expression left = binary.leftOperand;
-        Expression right = binary.rightOperand;
+      if (condition.operator.type == TokenType.AMPERSAND_AMPERSAND) {
+        Expression left = condition.leftOperand;
+        Expression right = condition.rightOperand;
         _promoteTypes(left);
         _promoteTypes(right);
         _clearTypePromotionsIfPotentiallyMutatedIn(right);
       }
     } else if (condition is IsExpression) {
-      IsExpression is2 = condition;
-      if (is2.notOperator == null) {
-        _promote(is2.expression, is2.type.type);
+      if (condition.notOperator == null) {
+        _promote(condition.expression, condition.type.type);
       }
     } else if (condition is ParenthesizedExpression) {
       _promoteTypes(condition.expression);
@@ -9311,23 +7295,21 @@
    */
   void _propagateFalseState(Expression condition) {
     if (condition is BinaryExpression) {
-      BinaryExpression binary = condition;
-      if (binary.operator.type == TokenType.BAR_BAR) {
-        _propagateFalseState(binary.leftOperand);
-        _propagateFalseState(binary.rightOperand);
+      if (condition.operator.type == TokenType.BAR_BAR) {
+        _propagateFalseState(condition.leftOperand);
+        _propagateFalseState(condition.rightOperand);
       }
     } else if (condition is IsExpression) {
-      IsExpression is2 = condition;
-      if (is2.notOperator != null) {
+      if (condition.notOperator != null) {
         // Since an is-statement doesn't actually change the type, we don't
         // let it affect the propagated type when it would result in a loss
         // of precision.
-        overrideExpression(is2.expression, is2.type.type, false, false);
+        overrideExpression(
+            condition.expression, condition.type.type, false, false);
       }
     } else if (condition is PrefixExpression) {
-      PrefixExpression prefix = condition;
-      if (prefix.operator.type == TokenType.BANG) {
-        _propagateTrueState(prefix.operand);
+      if (condition.operator.type == TokenType.BANG) {
+        _propagateTrueState(condition.operand);
       }
     } else if (condition is ParenthesizedExpression) {
       _propagateFalseState(condition.expression);
@@ -9352,23 +7334,21 @@
    */
   void _propagateTrueState(Expression condition) {
     if (condition is BinaryExpression) {
-      BinaryExpression binary = condition;
-      if (binary.operator.type == TokenType.AMPERSAND_AMPERSAND) {
-        _propagateTrueState(binary.leftOperand);
-        _propagateTrueState(binary.rightOperand);
+      if (condition.operator.type == TokenType.AMPERSAND_AMPERSAND) {
+        _propagateTrueState(condition.leftOperand);
+        _propagateTrueState(condition.rightOperand);
       }
     } else if (condition is IsExpression) {
-      IsExpression is2 = condition;
-      if (is2.notOperator == null) {
+      if (condition.notOperator == null) {
         // Since an is-statement doesn't actually change the type, we don't
         // let it affect the propagated type when it would result in a loss
         // of precision.
-        overrideExpression(is2.expression, is2.type.type, false, false);
+        overrideExpression(
+            condition.expression, condition.type.type, false, false);
       }
     } else if (condition is PrefixExpression) {
-      PrefixExpression prefix = condition;
-      if (prefix.operator.type == TokenType.BANG) {
-        _propagateFalseState(prefix.operand);
+      if (condition.operator.type == TokenType.BANG) {
+        _propagateFalseState(condition.operand);
       }
     } else if (condition is ParenthesizedExpression) {
       _propagateTrueState(condition.expression);
@@ -9394,38 +7374,42 @@
       List<ParameterElement> parameters,
       void onError(ErrorCode errorCode, AstNode node, [List<Object> arguments]),
       {bool reportAsError: false}) {
-    List<ParameterElement> requiredParameters = new List<ParameterElement>();
-    List<ParameterElement> positionalParameters = new List<ParameterElement>();
-    HashMap<String, ParameterElement> namedParameters =
-        new HashMap<String, ParameterElement>();
+    if (parameters.isEmpty && argumentList.arguments.isEmpty) {
+      return const <ParameterElement>[];
+    }
+    int requiredParameterCount = 0;
+    int unnamedParameterCount = 0;
+    List<ParameterElement> unnamedParameters = new List<ParameterElement>();
+    HashMap<String, ParameterElement> namedParameters = null;
     for (ParameterElement parameter in parameters) {
       ParameterKind kind = parameter.parameterKind;
       if (kind == ParameterKind.REQUIRED) {
-        requiredParameters.add(parameter);
+        unnamedParameters.add(parameter);
+        unnamedParameterCount++;
+        requiredParameterCount++;
       } else if (kind == ParameterKind.POSITIONAL) {
-        positionalParameters.add(parameter);
+        unnamedParameters.add(parameter);
+        unnamedParameterCount++;
       } else {
+        namedParameters ??= new HashMap<String, ParameterElement>();
         namedParameters[parameter.name] = parameter;
       }
     }
-    List<ParameterElement> unnamedParameters =
-        new List<ParameterElement>.from(requiredParameters);
-    unnamedParameters.addAll(positionalParameters);
-    int unnamedParameterCount = unnamedParameters.length;
     int unnamedIndex = 0;
     NodeList<Expression> arguments = argumentList.arguments;
     int argumentCount = arguments.length;
     List<ParameterElement> resolvedParameters =
         new List<ParameterElement>(argumentCount);
     int positionalArgumentCount = 0;
-    HashSet<String> usedNames = new HashSet<String>();
+    HashSet<String> usedNames = null;
     bool noBlankArguments = true;
     for (int i = 0; i < argumentCount; i++) {
       Expression argument = arguments[i];
       if (argument is NamedExpression) {
         SimpleIdentifier nameNode = argument.name.label;
         String name = nameNode.name;
-        ParameterElement element = namedParameters[name];
+        ParameterElement element =
+            namedParameters != null ? namedParameters[name] : null;
         if (element == null) {
           ErrorCode errorCode = (reportAsError
               ? CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER
@@ -9437,6 +7421,7 @@
           resolvedParameters[i] = element;
           nameNode.staticElement = element;
         }
+        usedNames ??= new HashSet<String>();
         if (!usedNames.add(name)) {
           if (onError != null) {
             onError(CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT, nameNode,
@@ -9453,14 +7438,13 @@
         }
       }
     }
-    if (positionalArgumentCount < requiredParameters.length &&
-        noBlankArguments) {
+    if (positionalArgumentCount < requiredParameterCount && noBlankArguments) {
       ErrorCode errorCode = (reportAsError
           ? CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS
           : StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS);
       if (onError != null) {
         onError(errorCode, argumentList,
-            [requiredParameters.length, positionalArgumentCount]);
+            [requiredParameterCount, positionalArgumentCount]);
       }
     } else if (positionalArgumentCount > unnamedParameterCount &&
         noBlankArguments) {
@@ -9477,200 +7461,6 @@
 }
 
 /**
- * The abstract class `Scope` defines the behavior common to name scopes used by the resolver
- * to determine which names are visible at any given point in the code.
- */
-abstract class Scope {
-  /**
-   * The prefix used to mark an identifier as being private to its library.
-   */
-  static int PRIVATE_NAME_PREFIX = 0x5F;
-
-  /**
-   * The suffix added to the declared name of a setter when looking up the setter. Used to
-   * disambiguate between a getter and a setter that have the same name.
-   */
-  static String SETTER_SUFFIX = "=";
-
-  /**
-   * The name used to look up the method used to implement the unary minus operator. Used to
-   * disambiguate between the unary and binary operators.
-   */
-  static String UNARY_MINUS = "unary-";
-
-  /**
-   * A table mapping names that are defined in this scope to the element representing the thing
-   * declared with that name.
-   */
-  HashMap<String, Element> _definedNames = new HashMap<String, Element>();
-
-  /**
-   * A flag indicating whether there are any names defined in this scope.
-   */
-  bool _hasName = false;
-
-  /**
-   * Return the scope in which this scope is lexically enclosed.
-   *
-   * @return the scope in which this scope is lexically enclosed
-   */
-  Scope get enclosingScope => null;
-
-  /**
-   * Return the listener that is to be informed when an error is encountered.
-   *
-   * @return the listener that is to be informed when an error is encountered
-   */
-  AnalysisErrorListener get errorListener;
-
-  /**
-   * Add the given element to this scope. If there is already an element with the given name defined
-   * in this scope, then an error will be generated and the original element will continue to be
-   * mapped to the name. If there is an element with the given name in an enclosing scope, then a
-   * warning will be generated but the given element will hide the inherited element.
-   *
-   * @param element the element to be added to this scope
-   */
-  void define(Element element) {
-    String name = _getName(element);
-    if (name != null && !name.isEmpty) {
-      if (_definedNames.containsKey(name)) {
-        errorListener
-            .onError(getErrorForDuplicate(_definedNames[name], element));
-      } else {
-        _definedNames[name] = element;
-        _hasName = true;
-      }
-    }
-  }
-
-  /**
-   * Add the given element to this scope without checking for duplication or hiding.
-   *
-   * @param name the name of the element to be added
-   * @param element the element to be added to this scope
-   */
-  void defineNameWithoutChecking(String name, Element element) {
-    _definedNames[name] = element;
-    _hasName = true;
-  }
-
-  /**
-   * Add the given element to this scope without checking for duplication or hiding.
-   *
-   * @param element the element to be added to this scope
-   */
-  void defineWithoutChecking(Element element) {
-    _definedNames[_getName(element)] = element;
-    _hasName = true;
-  }
-
-  /**
-   * Return the error code to be used when reporting that a name being defined locally conflicts
-   * with another element of the same name in the local scope.
-   *
-   * @param existing the first element to be declared with the conflicting name
-   * @param duplicate another element declared with the conflicting name
-   * @return the error code used to report duplicate names within a scope
-   */
-  AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
-    // TODO(brianwilkerson) Customize the error message based on the types of
-    // elements that share the same name.
-    // TODO(jwren) There are 4 error codes for duplicate, but only 1 is being
-    // generated.
-    Source source = duplicate.source;
-    return new AnalysisError(source, duplicate.nameOffset, duplicate.nameLength,
-        CompileTimeErrorCode.DUPLICATE_DEFINITION, [existing.displayName]);
-  }
-
-  /**
-   * Return the source that contains the given identifier, or the source associated with this scope
-   * if the source containing the identifier could not be determined.
-   *
-   * @param identifier the identifier whose source is to be returned
-   * @return the source that contains the given identifier
-   */
-  Source getSource(AstNode node) {
-    CompilationUnit unit = node.getAncestor((node) => node is CompilationUnit);
-    if (unit != null) {
-      CompilationUnitElement unitElement = unit.element;
-      if (unitElement != null) {
-        return unitElement.source;
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Return the element with which the given name is associated, or `null` if the name is not
-   * defined within this scope.
-   *
-   * @param identifier the identifier node to lookup element for, used to report correct kind of a
-   *          problem and associate problem with
-   * @param name the name associated with the element to be returned
-   * @param referencingLibrary the library that contains the reference to the name, used to
-   *          implement library-level privacy
-   * @return the element with which the given name is associated
-   */
-  Element internalLookup(
-      Identifier identifier, String name, LibraryElement referencingLibrary);
-
-  /**
-   * Return the element with which the given name is associated, or `null` if the name is not
-   * defined within this scope. This method only returns elements that are directly defined within
-   * this scope, not elements that are defined in an enclosing scope.
-   *
-   * @param name the name associated with the element to be returned
-   * @param referencingLibrary the library that contains the reference to the name, used to
-   *          implement library-level privacy
-   * @return the element with which the given name is associated
-   */
-  Element localLookup(String name, LibraryElement referencingLibrary) {
-    if (_hasName) {
-      return _definedNames[name];
-    }
-    return null;
-  }
-
-  /**
-   * Return the element with which the given identifier is associated, or `null` if the name
-   * is not defined within this scope.
-   *
-   * @param identifier the identifier associated with the element to be returned
-   * @param referencingLibrary the library that contains the reference to the name, used to
-   *          implement library-level privacy
-   * @return the element with which the given identifier is associated
-   */
-  Element lookup(Identifier identifier, LibraryElement referencingLibrary) =>
-      internalLookup(identifier, identifier.name, referencingLibrary);
-
-  /**
-   * Return the name that will be used to look up the given element.
-   *
-   * @param element the element whose look-up name is to be returned
-   * @return the name that will be used to look up the given element
-   */
-  String _getName(Element element) {
-    if (element is MethodElement) {
-      MethodElement method = element;
-      if (method.name == "-" && method.parameters.length == 0) {
-        return UNARY_MINUS;
-      }
-    }
-    return element.name;
-  }
-
-  /**
-   * Return `true` if the given name is a library-private name.
-   *
-   * @param name the name being tested
-   * @return `true` if the given name is a library-private name
-   */
-  static bool isPrivateName(String name) =>
-      name != null && StringUtilities.startsWithChar(name, PRIVATE_NAME_PREFIX);
-}
-
-/**
  * The abstract class `ScopedVisitor` maintains name and label scopes as an AST structure is
  * being visited.
  */
@@ -10348,15 +8138,13 @@
     for (int i = 0; i < statementCount; i++) {
       Statement statement = statements[i];
       if (statement is VariableDeclarationStatement) {
-        VariableDeclarationStatement vds = statement;
-        NodeList<VariableDeclaration> variables = vds.variables.variables;
+        NodeList<VariableDeclaration> variables = statement.variables.variables;
         int variableCount = variables.length;
         for (int j = 0; j < variableCount; j++) {
           scope.hide(variables[j].element);
         }
       } else if (statement is FunctionDeclarationStatement) {
-        FunctionDeclarationStatement fds = statement;
-        scope.hide(fds.functionDeclaration.element);
+        scope.hide(statement.functionDeclaration.element);
       }
     }
   }
@@ -10783,17 +8571,16 @@
    * @return the overridden type of the given element
    */
   DartType getType(Element element) {
-    if (element is PropertyAccessorElement) {
-      element = (element as PropertyAccessorElement).variable;
-    }
-    DartType type = _overridenTypes[element];
-    if (_overridenTypes.containsKey(element)) {
+    Element nonAccessor =
+        element is PropertyAccessorElement ? element.variable : element;
+    DartType type = _overridenTypes[nonAccessor];
+    if (_overridenTypes.containsKey(nonAccessor)) {
       return type;
     }
     if (type != null) {
       return type;
     } else if (_outerScope != null) {
-      return _outerScope.getType(element);
+      return _outerScope.getType(nonAccessor);
     }
     return null;
   }
@@ -10817,37 +8604,6 @@
 }
 
 /**
- * Instances of the class `TypeParameterScope` implement the scope defined by the type
- * parameters in a class.
- */
-class TypeParameterScope extends EnclosedScope {
-  /**
-   * Initialize a newly created scope enclosed within another scope.
-   *
-   * @param enclosingScope the scope in which this scope is lexically enclosed
-   * @param typeElement the element representing the type represented by this scope
-   */
-  TypeParameterScope(Scope enclosingScope, ClassElement typeElement)
-      : super(enclosingScope) {
-    if (typeElement == null) {
-      throw new IllegalArgumentException("class element cannot be null");
-    }
-    _defineTypeParameters(typeElement);
-  }
-
-  /**
-   * Define the type parameters for the class.
-   *
-   * @param typeElement the element representing the type represented by this scope
-   */
-  void _defineTypeParameters(ClassElement typeElement) {
-    for (TypeParameterElement typeParameter in typeElement.typeParameters) {
-      define(typeParameter);
-    }
-  }
-}
-
-/**
  * Instances of the class `TypePromotionManager` manage the ability to promote types of local
  * variables and formal parameters from their declared types based on control flow.
  */
@@ -11572,13 +9328,20 @@
 
   @override
   void visitClassMembersInScope(ClassDeclaration node) {
+    node.documentationComment?.accept(this);
+    node.metadata.accept(this);
     //
     // Process field declarations before constructors and methods so that the
     // types of field formal parameters can be correctly resolved.
     //
     List<ClassMember> nonFields = new List<ClassMember>();
-    node.visitChildren(
-        new _TypeResolverVisitor_visitClassMembersInScope(this, nonFields));
+    for (ClassMember member in node.members) {
+      if (member is ConstructorDeclaration) {
+        nonFields.add(member);
+      } else {
+        member.accept(this);
+      }
+    }
     int count = nonFields.length;
     for (int i = 0; i < count; i++) {
       nonFields[i].accept(this);
@@ -11651,7 +9414,6 @@
     super.visitFieldFormalParameter(node);
     Element element = node.identifier.staticElement;
     if (element is ParameterElementImpl) {
-      ParameterElementImpl parameter = element;
       FormalParameterList parameterList = node.parameters;
       if (parameterList == null) {
         DartType type;
@@ -11659,9 +9421,9 @@
         if (typeName == null) {
           element.hasImplicitType = true;
           type = _dynamicType;
-          if (parameter is FieldFormalParameterElement) {
+          if (element is FieldFormalParameterElement) {
             FieldElement fieldElement =
-                (parameter as FieldFormalParameterElement).field;
+                (element as FieldFormalParameterElement).field;
             if (fieldElement != null) {
               type = fieldElement.type;
             }
@@ -11669,9 +9431,9 @@
         } else {
           type = _getType(typeName);
         }
-        parameter.type = type;
+        element.type = type;
       } else {
-        _setFunctionTypedParameterType(parameter, node.type, node.parameters);
+        _setFunctionTypedParameterType(element, node.type, node.parameters);
       }
     } else {
       // TODO(brianwilkerson) Report this internal error
@@ -11772,8 +9534,8 @@
       declaredType = _getType(typeName);
     }
     Element element = node.identifier.staticElement;
-    if (element is ParameterElement) {
-      (element as ParameterElementImpl).type = declaredType;
+    if (element is ParameterElementImpl) {
+      element.type = declaredType;
     } else {
       // TODO(brianwilkerson) Report the internal error.
     }
@@ -11836,8 +9598,9 @@
           SimpleIdentifier prefix = prefixedIdentifier.prefix;
           element = nameScope.lookup(prefix, definingLibrary);
           if (element is PrefixElement) {
-            if (parent.parent is InstanceCreationExpression &&
-                (parent.parent as InstanceCreationExpression).isConst) {
+            AstNode grandParent = parent.parent;
+            if (grandParent is InstanceCreationExpression &&
+                grandParent.isConst) {
               // If, if this is a const expression, then generate a
               // CompileTimeErrorCode.CONST_WITH_NON_TYPE error.
               reportErrorForNode(
@@ -12066,13 +9829,12 @@
     if (element is VariableElement) {
       (element as VariableElementImpl).type = declaredType;
       if (element is PropertyInducingElement) {
-        PropertyInducingElement variableElement = element;
         PropertyAccessorElementImpl getter =
-            variableElement.getter as PropertyAccessorElementImpl;
+            element.getter as PropertyAccessorElementImpl;
         getter.returnType = declaredType;
         getter.type = new FunctionTypeImpl(getter);
         PropertyAccessorElementImpl setter =
-            variableElement.setter as PropertyAccessorElementImpl;
+            element.setter as PropertyAccessorElementImpl;
         if (setter != null) {
           List<ParameterElement> parameters = setter.parameters;
           if (parameters.length > 0) {
@@ -12119,12 +9881,12 @@
       return null;
     }
     Element element = identifier.staticElement;
-    if (element is! ClassElementImpl) {
-      // TODO(brianwilkerson) Report this
-      // Internal error: Failed to create an element for a class declaration.
-      return null;
+    if (element is ClassElementImpl) {
+      return element;
     }
-    return element as ClassElementImpl;
+    // TODO(brianwilkerson) Report this
+    // Internal error: Failed to create an element for a class declaration.
+    return null;
   }
 
   /**
@@ -12181,11 +9943,10 @@
   RedirectingConstructorKind _getRedirectingConstructorKind(TypeName typeName) {
     AstNode parent = typeName.parent;
     if (parent is ConstructorName) {
-      ConstructorName constructorName = parent as ConstructorName;
-      parent = constructorName.parent;
-      if (parent is ConstructorDeclaration) {
-        if (identical(parent.redirectedConstructor, constructorName)) {
-          if (parent.constKeyword != null) {
+      AstNode grandParent = parent.parent;
+      if (grandParent is ConstructorDeclaration) {
+        if (identical(grandParent.redirectedConstructor, parent)) {
+          if (grandParent.constKeyword != null) {
             return RedirectingConstructorKind.CONST;
           }
           return RedirectingConstructorKind.NORMAL;
@@ -12266,8 +10027,7 @@
   bool _isTypeNameInAsExpression(TypeName typeName) {
     AstNode parent = typeName.parent;
     if (parent is AsExpression) {
-      AsExpression asExpression = parent;
-      return identical(asExpression.type, typeName);
+      return identical(parent.type, typeName);
     }
     return false;
   }
@@ -12281,8 +10041,7 @@
   bool _isTypeNameInCatchClause(TypeName typeName) {
     AstNode parent = typeName.parent;
     if (parent is CatchClause) {
-      CatchClause catchClause = parent;
-      return identical(catchClause.exceptionType, typeName);
+      return identical(parent.exceptionType, typeName);
     }
     return false;
   }
@@ -12298,9 +10057,7 @@
     AstNode parent = typeName.parent;
     if (parent is ConstructorName &&
         parent.parent is InstanceCreationExpression) {
-      ConstructorName constructorName = parent;
-      return constructorName != null &&
-          identical(constructorName.type, typeName);
+      return parent != null && identical(parent.type, typeName);
     }
     return false;
   }
@@ -12314,8 +10071,7 @@
   bool _isTypeNameInIsExpression(TypeName typeName) {
     AstNode parent = typeName.parent;
     if (parent is IsExpression) {
-      IsExpression isExpression = parent;
-      return identical(isExpression.type, typeName);
+      return identical(parent.type, typeName);
     }
     return false;
   }
@@ -12512,11 +10268,9 @@
     AstNode parent = node.parent;
     if (parent is VariableDeclarationList) {
       return identical(parent.type, node);
-    }
-    if (parent is FieldFormalParameter) {
+    } else if (parent is FieldFormalParameter) {
       return identical(parent.type, node);
-    }
-    if (parent is SimpleFormalParameter) {
+    } else if (parent is SimpleFormalParameter) {
       return identical(parent.type, node);
     }
     return false;
@@ -13064,38 +10818,3 @@
     return null;
   }
 }
-
-class _TypeResolverVisitor_visitClassMembersInScope
-    extends UnifyingAstVisitor<Object> {
-  final TypeResolverVisitor TypeResolverVisitor_this;
-
-  List<ClassMember> nonFields;
-
-  _TypeResolverVisitor_visitClassMembersInScope(
-      this.TypeResolverVisitor_this, this.nonFields)
-      : super();
-
-  @override
-  Object visitConstructorDeclaration(ConstructorDeclaration node) {
-    nonFields.add(node);
-    return null;
-  }
-
-  @override
-  Object visitExtendsClause(ExtendsClause node) => null;
-
-  @override
-  Object visitImplementsClause(ImplementsClause node) => null;
-
-  @override
-  Object visitMethodDeclaration(MethodDeclaration node) {
-    nonFields.add(node);
-    return null;
-  }
-
-  @override
-  Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this);
-
-  @override
-  Object visitWithClause(WithClause node) => null;
-}
diff --git a/pkg/analyzer/lib/src/generated/sdk.dart b/pkg/analyzer/lib/src/generated/sdk.dart
index 27577b8..8e1abb2 100644
--- a/pkg/analyzer/lib/src/generated/sdk.dart
+++ b/pkg/analyzer/lib/src/generated/sdk.dart
@@ -10,8 +10,7 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisContext, AnalysisOptions;
-import 'package:analyzer/src/generated/source.dart'
-    show ContentCache, Source, UriKind;
+import 'package:analyzer/src/generated/source.dart' show Source;
 
 /**
  * A function used to create a new DartSdk with the given [options]. If the
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index 0387905..65e8f95 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -217,6 +217,11 @@
   }
 
   /**
+   * The number of lines.
+   */
+  int get lineCount => _lineStarts.length;
+
+  /**
    * Return the location information for the character at the given [offset].
    */
   LineInfo_Location getLocation(int offset) {
@@ -258,7 +263,7 @@
    * [lineNumber].
    */
   int getOffsetOfLine(int lineNumber) {
-    if (lineNumber < 0 || lineNumber >= _lineStarts.length) {
+    if (lineNumber < 0 || lineNumber >= lineCount) {
       throw new ArgumentError('Invalid line number: $lineNumber');
     }
     return _lineStarts[lineNumber];
@@ -750,12 +755,10 @@
   int get hashCode => 31 * offset + length;
 
   @override
-  bool operator ==(Object obj) {
-    if (obj is! SourceRange) {
-      return false;
-    }
-    SourceRange sourceRange = obj as SourceRange;
-    return sourceRange.offset == offset && sourceRange.length == length;
+  bool operator ==(Object other) {
+    return other is SourceRange &&
+        other.offset == offset &&
+        other.length == length;
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/generated/source_io.dart b/pkg/analyzer/lib/src/generated/source_io.dart
index 811a048..5c9c740 100644
--- a/pkg/analyzer/lib/src/generated/source_io.dart
+++ b/pkg/analyzer/lib/src/generated/source_io.dart
@@ -11,7 +11,6 @@
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/java_io.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
 
 export 'package:analyzer/src/generated/source.dart';
 
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index f76cf73..7eb4a8b 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -617,9 +617,11 @@
    */
   @override
   Object visitListLiteral(ListLiteral node) {
-    DartType staticType = _dynamicType;
     TypeArgumentList typeArguments = node.typeArguments;
+
+    // If we have explicit arguments, use them
     if (typeArguments != null) {
+      DartType staticType = _dynamicType;
       NodeList<TypeName> arguments = typeArguments.arguments;
       if (arguments != null && arguments.length == 1) {
         TypeName argumentTypeName = arguments[0];
@@ -628,25 +630,47 @@
           staticType = argumentType;
         }
       }
-    } else if (_strongMode) {
+      _recordStaticType(
+          node, _typeProvider.listType.instantiate(<DartType>[staticType]));
+      return null;
+    }
+
+    // If there are no type arguments and we are in strong mode, try to infer
+    // some arguments.
+    if (_strongMode) {
       DartType contextType = InferenceContext.getType(node);
+
+      // If we have a type from the context, use it.
       if (contextType is InterfaceType &&
           contextType.typeArguments.length == 1 &&
           contextType.element == _typeProvider.listType.element) {
-        staticType = contextType.typeArguments[0];
         _resolver.inferenceContext.recordInference(node, contextType);
-      } else if (node.elements.isNotEmpty) {
+        _recordStaticType(node, contextType);
+        return null;
+      }
+
+      // If we don't have a type from the context, try to infer from the
+      // elements
+      if (node.elements.isNotEmpty) {
         // Infer the list type from the arguments.
-        // TODO(jmesserly): record inference here?
-        staticType =
+        DartType staticType =
             node.elements.map((e) => e.staticType).reduce(_leastUpperBound);
         if (staticType.isBottom) {
           staticType = _dynamicType;
         }
+        DartType listLiteralType =
+            _typeProvider.listType.instantiate(<DartType>[staticType]);
+        if (!staticType.isDynamic) {
+          _resolver.inferenceContext.recordInference(node, listLiteralType);
+        }
+        _recordStaticType(node, listLiteralType);
+        return null;
       }
     }
+
+    // If we have no type arguments and couldn't infer any, use dynamic.
     _recordStaticType(
-        node, _typeProvider.listType.instantiate(<DartType>[staticType]));
+        node, _typeProvider.listType.instantiate(<DartType>[_dynamicType]));
     return null;
   }
 
@@ -664,10 +688,12 @@
    */
   @override
   Object visitMapLiteral(MapLiteral node) {
-    DartType staticKeyType = _dynamicType;
-    DartType staticValueType = _dynamicType;
     TypeArgumentList typeArguments = node.typeArguments;
+
+    // If we have type arguments, use them
     if (typeArguments != null) {
+      DartType staticKeyType = _dynamicType;
+      DartType staticValueType = _dynamicType;
       NodeList<TypeName> arguments = typeArguments.arguments;
       if (arguments != null && arguments.length == 2) {
         TypeName entryKeyTypeName = arguments[0];
@@ -681,20 +707,31 @@
           staticValueType = entryValueType;
         }
       }
-    } else if (_strongMode) {
+      _recordStaticType(
+          node,
+          _typeProvider.mapType
+              .instantiate(<DartType>[staticKeyType, staticValueType]));
+      return null;
+    }
+
+    // If we have no explicit type arguments, and we are in strong mode
+    // then try to infer type arguments.
+    if (_strongMode) {
       DartType contextType = InferenceContext.getType(node);
+      // If we have a context type, use that for inference.
       if (contextType is InterfaceType &&
           contextType.typeArguments.length == 2 &&
           contextType.element == _typeProvider.mapType.element) {
-        staticKeyType = contextType.typeArguments[0] ?? staticKeyType;
-        staticValueType = contextType.typeArguments[1] ?? staticValueType;
         _resolver.inferenceContext.recordInference(node, contextType);
-      } else if (node.entries.isNotEmpty) {
-        // Infer the list type from the arguments.
-        // TODO(jmesserly): record inference here?
-        staticKeyType =
+        _recordStaticType(node, contextType);
+        return null;
+      }
+
+      // Otherwise, try to infer a type from the keys and values.
+      if (node.entries.isNotEmpty) {
+        DartType staticKeyType =
             node.entries.map((e) => e.key.staticType).reduce(_leastUpperBound);
-        staticValueType = node.entries
+        DartType staticValueType = node.entries
             .map((e) => e.value.staticType)
             .reduce(_leastUpperBound);
         if (staticKeyType.isBottom) {
@@ -703,12 +740,21 @@
         if (staticValueType.isBottom) {
           staticValueType = _dynamicType;
         }
+        DartType mapLiteralType = _typeProvider.mapType
+            .instantiate(<DartType>[staticKeyType, staticValueType]);
+        if (!(staticValueType.isDynamic && staticKeyType.isDynamic)) {
+          _resolver.inferenceContext.recordInference(node, mapLiteralType);
+        }
+        _recordStaticType(node, mapLiteralType);
+        return null;
       }
     }
+
+    // If no type arguments and no inference, use dynamic
     _recordStaticType(
         node,
         _typeProvider.mapType
-            .instantiate(<DartType>[staticKeyType, staticValueType]));
+            .instantiate(<DartType>[_dynamicType, _dynamicType]));
     return null;
   }
 
@@ -1471,8 +1517,7 @@
    */
   DartType _computePropagatedReturnTypeOfFunction(FunctionBody body) {
     if (body is ExpressionFunctionBody) {
-      ExpressionFunctionBody expressionBody = body;
-      return expressionBody.expression.bestType;
+      return body.expression.bestType;
     }
     if (body is BlockFunctionBody) {
       _StaticTypeAnalyzer_computePropagatedReturnTypeOfFunction visitor =
@@ -1712,16 +1757,13 @@
    * Return the propagated type of the given [Element], or `null`.
    */
   DartType _getPropertyPropagatedType(Element element, DartType currentType) {
-    if (element is PropertyAccessorElement) {
-      PropertyAccessorElement accessor = element;
-      if (accessor.isGetter) {
-        PropertyInducingElement variable = accessor.variable;
-        DartType propagatedType = variable.propagatedType;
-        if (currentType == null ||
-            propagatedType != null &&
-                propagatedType.isMoreSpecificThan(currentType)) {
-          return propagatedType;
-        }
+    if (element is PropertyAccessorElement && element.isGetter) {
+      PropertyInducingElement variable = element.variable;
+      DartType propagatedType = variable.propagatedType;
+      if (currentType == null ||
+          propagatedType != null &&
+              propagatedType.isMoreSpecificThan(currentType)) {
+        return propagatedType;
       }
     }
     return currentType;
@@ -1878,12 +1920,13 @@
       VariableDeclaration node, Expression initializer) {
     if (initializer != null &&
         (node.parent as VariableDeclarationList).type == null &&
-        (node.element is LocalVariableElementImpl) &&
         (initializer.staticType != null) &&
         (!initializer.staticType.isBottom)) {
-      LocalVariableElementImpl element = node.element;
-      element.type = initializer.staticType;
-      node.name.staticType = initializer.staticType;
+      VariableElement element = node.element;
+      if (element is LocalVariableElementImpl) {
+        element.type = initializer.staticType;
+        node.name.staticType = initializer.staticType;
+      }
     }
   }
 
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 bf2e130..64dadf2 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -480,8 +480,8 @@
   @override
   InterfaceType get stringType {
     if (_stringType == null) {
-      _stringType = ElementFactory.classElement2("String").type;
-      ClassElementImpl stringElement = _stringType.element as ClassElementImpl;
+      ClassElementImpl stringElement = ElementFactory.classElement2("String");
+      _stringType = stringElement.type;
       _setAccessors(stringElement, <PropertyAccessorElement>[
         ElementFactory.getterElement("isEmpty", false, boolType),
         ElementFactory.getterElement("length", false, intType),
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 9caffef..526d067 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -29,6 +29,36 @@
   @override
   bool canPromoteToType(DartType to, DartType from) => isSubtypeOf(to, from);
 
+  @override
+  FunctionType functionTypeToConcreteType(
+      TypeProvider typeProvider, FunctionType t) {
+    // TODO(jmesserly): should we use a real "fuzzyArrow" bit on the function
+    // type? That would allow us to implement this in the subtype relation.
+    // TODO(jmesserly): we'll need to factor this differently if we want to
+    // move CodeChecker's functionality into existing analyzer. Likely we can
+    // let the Expression have a strict arrow, then in places were we do
+    // inference, convert back to a fuzzy arrow.
+
+    if (!t.parameters.any((p) => p.type.isDynamic)) {
+      return t;
+    }
+    ParameterElement shave(ParameterElement p) {
+      if (p.type.isDynamic) {
+        return new ParameterElementImpl.synthetic(
+            p.name, typeProvider.objectType, p.parameterKind);
+      }
+      return p;
+    }
+
+    List<ParameterElement> parameters = t.parameters.map(shave).toList();
+    FunctionElementImpl function = new FunctionElementImpl("", -1);
+    function.synthetic = true;
+    function.returnType = t.returnType;
+    function.shareTypeParameters(t.typeFormals);
+    function.shareParameters(parameters);
+    return function.type = new FunctionTypeImpl(function);
+  }
+
   /**
    * Given a type t, if t is an interface type with a call method
    * defined, return the function type for the call method, otherwise
@@ -95,111 +125,6 @@
   }
 
   /**
-   * This currently does not implement a very complete least upper bound
-   * algorithm, but handles a couple of the very common cases that are
-   * causing pain in real code.  The current algorithm is:
-   * 1. If either of the types is a supertype of the other, return it.
-   *    This is in fact the best result in this case.
-   * 2. If the two types have the same class element, then take the
-   *    pointwise least upper bound of the type arguments.  This is again
-   *    the best result, except that the recursive calls may not return
-   *    the true least uppper bounds.  The result is guaranteed to be a
-   *    well-formed type under the assumption that the input types were
-   *    well-formed (and assuming that the recursive calls return
-   *    well-formed types).
-   * 3. Otherwise return the spec-defined least upper bound.  This will
-   *    be an upper bound, might (or might not) be least, and might
-   *    (or might not) be a well-formed type.
-   *
-   * TODO(leafp): Use matchTypes or something similar here to handle the
-   *  case where one of the types is a superclass (but not supertype) of
-   *  the other, e.g. LUB(Iterable<double>, List<int>) = Iterable<num>
-   * TODO(leafp): Figure out the right final algorithm and implement it.
-   */
-  @override
-  DartType _interfaceLeastUpperBound(
-      TypeProvider provider, InterfaceType type1, InterfaceType type2) {
-    if (isSubtypeOf(type1, type2)) {
-      return type2;
-    }
-    if (isSubtypeOf(type2, type1)) {
-      return type1;
-    }
-    if (type1.element == type2.element) {
-      List<DartType> tArgs1 = type1.typeArguments;
-      List<DartType> tArgs2 = type2.typeArguments;
-
-      assert(tArgs1.length == tArgs2.length);
-      List<DartType> tArgs = new List(tArgs1.length);
-      for (int i = 0; i < tArgs1.length; i++) {
-        tArgs[i] = getLeastUpperBound(provider, tArgs1[i], tArgs2[i]);
-      }
-      InterfaceTypeImpl lub = new InterfaceTypeImpl(type1.element);
-      lub.typeArguments = tArgs;
-      return lub;
-    }
-    return InterfaceTypeImpl.computeLeastUpperBound(type1, type2) ??
-        provider.dynamicType;
-  }
-
-  /**
-   * This currently just implements a simple least upper bound to
-   * handle some common cases.  It also avoids some termination issues
-   * with the naive spec algorithm.  The least upper bound of two types
-   * (at least one of which is a type parameter) is computed here as:
-   * 1. If either type is a supertype of the other, return it.
-   * 2. If the first type is a type parameter, replace it with its bound,
-   *    with recursive occurrences of itself replaced with Object.
-   *    The second part of this should ensure termination.  Informally,
-   *    each type variable instantiation in one of the arguments to the
-   *    least upper bound algorithm now strictly reduces the number
-   *    of bound variables in scope in that argument position.
-   * 3. If the second type is a type parameter, do the symmetric operation
-   *    to #2.
-   *
-   * It's not immediately obvious why this is symmetric in the case that both
-   * of the them are type parameters.  For #1, symmetry holds since subtype
-   * is antisymmetric.  For #2, it's clearly not symmetric if upper bounds of
-   * bottom are allowed.  Ignoring this (for various reasons, not least
-   * of which that there's no way to write it), there's an informal
-   * argument (that might even be right) that you will always either
-   * end up expanding both of them or else returning the same result no matter
-   * which order you expand them in.  A key observation is that
-   * identical(expand(type1), type2) => subtype(type1, type2)
-   * and hence the contra-positive.
-   *
-   * TODO(leafp): Think this through and figure out what's the right
-   * definition.  Be careful about termination.
-   *
-   * I suspect in general a reasonable algorithm is to expand the innermost
-   * type variable first.  Alternatively, you could probably choose to treat
-   * it as just an instance of the interface type upper bound problem, with
-   * the "inheritance" chain extended by the bounds placed on the variables.
-   */
-  @override
-  DartType _typeParameterLeastUpperBound(
-      TypeProvider provider, DartType type1, DartType type2) {
-    if (isSubtypeOf(type1, type2)) {
-      return type2;
-    }
-    if (isSubtypeOf(type2, type1)) {
-      return type1;
-    }
-    if (type1 is TypeParameterType) {
-      type1 = type1
-          .resolveToBound(provider.objectType)
-          .substitute2([provider.objectType], [type1]);
-      return getLeastUpperBound(provider, type1, type2);
-    }
-    // We should only be called when at least one of the types is a
-    // TypeParameterType
-    type2 = type2
-        .resolveToBound(provider.objectType)
-        .substitute2([provider.objectType], [type2]);
-    return getLeastUpperBound(provider, type1, type2);
-  }
-
-  /**
    * Given a generic function type `F<T0, T1, ... Tn>` and a context type C,
    * infer an instantiation of F, such that `F<S0, S1, ..., Sn>` <: C.
    *
@@ -385,8 +310,12 @@
 
   bool isGroundType(DartType t) {
     // TODO(leafp): Revisit this.
-    if (t is TypeParameterType) return false;
-    if (_isTop(t)) return true;
+    if (t is TypeParameterType) {
+      return false;
+    }
+    if (_isTop(t)) {
+      return true;
+    }
 
     if (t is FunctionType) {
       if (!_isTop(t.returnType) ||
@@ -398,8 +327,8 @@
     }
 
     if (t is InterfaceType) {
-      var typeArguments = t.typeArguments;
-      for (var typeArgument in typeArguments) {
+      List<DartType> typeArguments = t.typeArguments;
+      for (DartType typeArgument in typeArguments) {
         if (!_isTop(typeArgument)) return false;
       }
       return true;
@@ -417,6 +346,14 @@
     return _isSubtypeOf(leftType, rightType, null);
   }
 
+  @override
+  DartType typeToConcreteType(TypeProvider typeProvider, DartType t) {
+    if (t is FunctionType) {
+      return functionTypeToConcreteType(typeProvider, t);
+    }
+    return t;
+  }
+
   /**
    * Compute the greatest lower bound of function types [f] and [g].
    *
@@ -561,6 +498,54 @@
     return false;
   }
 
+  /**
+   * This currently does not implement a very complete least upper bound
+   * algorithm, but handles a couple of the very common cases that are
+   * causing pain in real code.  The current algorithm is:
+   * 1. If either of the types is a supertype of the other, return it.
+   *    This is in fact the best result in this case.
+   * 2. If the two types have the same class element, then take the
+   *    pointwise least upper bound of the type arguments.  This is again
+   *    the best result, except that the recursive calls may not return
+   *    the true least uppper bounds.  The result is guaranteed to be a
+   *    well-formed type under the assumption that the input types were
+   *    well-formed (and assuming that the recursive calls return
+   *    well-formed types).
+   * 3. Otherwise return the spec-defined least upper bound.  This will
+   *    be an upper bound, might (or might not) be least, and might
+   *    (or might not) be a well-formed type.
+   *
+   * TODO(leafp): Use matchTypes or something similar here to handle the
+   *  case where one of the types is a superclass (but not supertype) of
+   *  the other, e.g. LUB(Iterable<double>, List<int>) = Iterable<num>
+   * TODO(leafp): Figure out the right final algorithm and implement it.
+   */
+  @override
+  DartType _interfaceLeastUpperBound(
+      TypeProvider provider, InterfaceType type1, InterfaceType type2) {
+    if (isSubtypeOf(type1, type2)) {
+      return type2;
+    }
+    if (isSubtypeOf(type2, type1)) {
+      return type1;
+    }
+    if (type1.element == type2.element) {
+      List<DartType> tArgs1 = type1.typeArguments;
+      List<DartType> tArgs2 = type2.typeArguments;
+
+      assert(tArgs1.length == tArgs2.length);
+      List<DartType> tArgs = new List(tArgs1.length);
+      for (int i = 0; i < tArgs1.length; i++) {
+        tArgs[i] = getLeastUpperBound(provider, tArgs1[i], tArgs2[i]);
+      }
+      InterfaceTypeImpl lub = new InterfaceTypeImpl(type1.element);
+      lub.typeArguments = tArgs;
+      return lub;
+    }
+    return InterfaceTypeImpl.computeLeastUpperBound(type1, type2) ??
+        provider.dynamicType;
+  }
+
   bool _isBottom(DartType t, {bool dynamicIsBottom: false}) {
     return (t.isDynamic && dynamicIsBottom) || t.isBottom;
   }
@@ -716,6 +701,63 @@
     // TODO(leafp): Document the rules in play here
     return (t.isDynamic && !dynamicIsBottom) || t.isObject;
   }
+
+  /**
+   * This currently just implements a simple least upper bound to
+   * handle some common cases.  It also avoids some termination issues
+   * with the naive spec algorithm.  The least upper bound of two types
+   * (at least one of which is a type parameter) is computed here as:
+   * 1. If either type is a supertype of the other, return it.
+   * 2. If the first type is a type parameter, replace it with its bound,
+   *    with recursive occurrences of itself replaced with Object.
+   *    The second part of this should ensure termination.  Informally,
+   *    each type variable instantiation in one of the arguments to the
+   *    least upper bound algorithm now strictly reduces the number
+   *    of bound variables in scope in that argument position.
+   * 3. If the second type is a type parameter, do the symmetric operation
+   *    to #2.
+   *
+   * It's not immediately obvious why this is symmetric in the case that both
+   * of the them are type parameters.  For #1, symmetry holds since subtype
+   * is antisymmetric.  For #2, it's clearly not symmetric if upper bounds of
+   * bottom are allowed.  Ignoring this (for various reasons, not least
+   * of which that there's no way to write it), there's an informal
+   * argument (that might even be right) that you will always either
+   * end up expanding both of them or else returning the same result no matter
+   * which order you expand them in.  A key observation is that
+   * identical(expand(type1), type2) => subtype(type1, type2)
+   * and hence the contra-positive.
+   *
+   * TODO(leafp): Think this through and figure out what's the right
+   * definition.  Be careful about termination.
+   *
+   * I suspect in general a reasonable algorithm is to expand the innermost
+   * type variable first.  Alternatively, you could probably choose to treat
+   * it as just an instance of the interface type upper bound problem, with
+   * the "inheritance" chain extended by the bounds placed on the variables.
+   */
+  @override
+  DartType _typeParameterLeastUpperBound(
+      TypeProvider provider, DartType type1, DartType type2) {
+    if (isSubtypeOf(type1, type2)) {
+      return type2;
+    }
+    if (isSubtypeOf(type2, type1)) {
+      return type1;
+    }
+    if (type1 is TypeParameterType) {
+      type1 = type1
+          .resolveToBound(provider.objectType)
+          .substitute2([provider.objectType], [type1]);
+      return getLeastUpperBound(provider, type1, type2);
+    }
+    // We should only be called when at least one of the types is a
+    // TypeParameterType
+    type2 = type2
+        .resolveToBound(provider.objectType)
+        .substitute2([provider.objectType], [type2]);
+    return getLeastUpperBound(provider, type1, type2);
+  }
 }
 
 /**
@@ -738,6 +780,25 @@
   bool canPromoteToType(DartType to, DartType from);
 
   /**
+   * Make a function type concrete.
+   *
+   * Normally we treat dynamically typed parameters as bottom for function
+   * types. This allows type tests such as `if (f is SingleArgFunction)`.
+   * It also requires a dynamic check on the parameter type to call these
+   * functions.
+   *
+   * When we convert to a strict arrow, dynamically typed parameters become
+   * top. This is safe to do for known functions, like top-level or local
+   * functions and static methods. Those functions must already be essentially
+   * treating dynamic as top.
+   *
+   * Only the outer-most arrow can be strict. Any others must be fuzzy, because
+   * we don't know what function value will be passed there.
+   */
+  FunctionType functionTypeToConcreteType(
+      TypeProvider typeProvider, FunctionType t);
+
+  /**
    * Compute the least upper bound of two types.
    */
   DartType getLeastUpperBound(
@@ -797,21 +858,6 @@
   }
 
   /**
-   * Given two [InterfaceType]s [type1] and [type2] return their least upper
-   * bound in a type system specific manner.
-   */
-  DartType _interfaceLeastUpperBound(
-      TypeProvider provider, InterfaceType type1, InterfaceType type2);
-
-  /**
-   * Given two [DartType]s [type1] and [type2] at least one of which is a
-   * [TypeParameterType], return their least upper bound in a type system
-   * specific manner.
-   */
-  DartType _typeParameterLeastUpperBound(
-      TypeProvider provider, DartType type1, DartType type2);
-
-  /**
    * Given a [DartType] [type], instantiate it with its bounds.
    *
    * The behavior of this method depends on the type system, for example, in
@@ -923,6 +969,14 @@
       TypeParameterTypeImpl.getTypes(typeFormalsAsElements(type));
 
   /**
+   * Make a type concrete.  A type is concrete if it is not a function
+   * type, or if it is a function type with no dynamic parameters.  A
+   * non-concrete function type is made concrete by replacing dynamic
+   * parameters with Object.
+   */
+  DartType typeToConcreteType(TypeProvider typeProvider, DartType t);
+
+  /**
    * Compute the least upper bound of function types [f] and [g].
    *
    * The spec rules for LUB on function types, informally, are pretty simple
@@ -1005,6 +1059,21 @@
       getLeastUpperBound(provider, f, g);
 
   /**
+   * Given two [InterfaceType]s [type1] and [type2] return their least upper
+   * bound in a type system specific manner.
+   */
+  DartType _interfaceLeastUpperBound(
+      TypeProvider provider, InterfaceType type1, InterfaceType type2);
+
+  /**
+   * Given two [DartType]s [type1] and [type2] at least one of which is a
+   * [TypeParameterType], return their least upper bound in a type system
+   * specific manner.
+   */
+  DartType _typeParameterLeastUpperBound(
+      TypeProvider provider, DartType type1, DartType type2);
+
+  /**
    * Create either a strong mode or regular type system based on context.
    */
   static TypeSystem create(AnalysisContext context) {
@@ -1028,6 +1097,11 @@
     return !from.isDynamic && !to.isDynamic && to.isMoreSpecificThan(from);
   }
 
+  @override
+  FunctionType functionTypeToConcreteType(
+          TypeProvider typeProvider, FunctionType t) =>
+      t;
+
   /**
    * Instantiate a parameterized type using `dynamic` for all generic
    * parameters.  Returns the type unchanged if there are no parameters.
@@ -1058,6 +1132,9 @@
   }
 
   @override
+  DartType typeToConcreteType(TypeProvider typeProvider, DartType t) => t;
+
+  @override
   DartType _interfaceLeastUpperBound(
       TypeProvider provider, InterfaceType type1, InterfaceType type2) {
     InterfaceType result =
diff --git a/pkg/analyzer/lib/src/summary/flat_buffers.dart b/pkg/analyzer/lib/src/summary/flat_buffers.dart
index 410d9d4..d573693 100644
--- a/pkg/analyzer/lib/src/summary/flat_buffers.dart
+++ b/pkg/analyzer/lib/src/summary/flat_buffers.dart
@@ -237,9 +237,11 @@
     {
       _currentVTable.computeFieldOffsets(tableTail);
       // Try to find an existing compatible VTable.
-      for (_VTable vTable in _vTables) {
+      for (int i = 0; i < _vTables.length; i++) {
+        _VTable vTable = _vTables[i];
         if (_currentVTable.canUseExistingVTable(vTable)) {
           vTableTail = vTable.tail;
+          break;
         }
       }
       // Write a new VTable.
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index bd866c7..edaf034 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -1782,6 +1782,7 @@
    */
   void flushInformative() {
     _linkedLibraries?.forEach((b) => b.flushInformative());
+    _unlinkedUnitHashes = null;
     _unlinkedUnits?.forEach((b) => b.flushInformative());
   }
 
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index e7e548c..97528d7 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -147,7 +147,12 @@
   /**
    * The synthetic `values` getter of an enum.
    */
-  enumValues
+  enumValues,
+
+  /**
+   * The containing unit itself.
+   */
+  unit
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index ebbe533..d83c9ef 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -341,7 +341,12 @@
   /**
    * The synthetic `values` getter of an enum.
    */
-  enumValues
+  enumValues,
+
+  /**
+   * The containing unit itself.
+   */
+  unit
 }
 
 /**
@@ -622,6 +627,7 @@
    * is encoded as a hexadecimal string using lower case letters.
    */
   @Id(4)
+  @informative
   List<String> get unlinkedUnitHashes;
 
   /**
diff --git a/pkg/analyzer/lib/src/summary/incremental_cache.dart b/pkg/analyzer/lib/src/summary/incremental_cache.dart
index 9900773..1d913be 100644
--- a/pkg/analyzer/lib/src/summary/incremental_cache.dart
+++ b/pkg/analyzer/lib/src/summary/incremental_cache.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.
 
-import 'dart:convert' show UTF8;
+import 'dart:convert' show ChunkedConversionSink, UTF8;
 import 'dart:core' hide Resource;
 
 import 'package:analyzer/dart/element/element.dart';
@@ -12,6 +12,7 @@
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/summarize_elements.dart';
+import 'package:convert/convert.dart';
 import 'package:crypto/crypto.dart';
 
 /**
@@ -242,7 +243,7 @@
    */
   String _getCacheSourceContentKey(Source source) {
     List<int> hash = _getSourceContentHash(source);
-    String hashStr = CryptoUtils.bytesToHex(hash);
+    String hashStr = hex.encode(hash);
     return '$hashStr.content';
   }
 
@@ -267,7 +268,7 @@
    */
   String _getLibraryBundleKey(Source librarySource) {
     List<int> hash = _getLibraryClosureHash(librarySource);
-    String hashStr = CryptoUtils.bytesToHex(hash);
+    String hashStr = hex.encode(hash);
     return '$hashStr.summary';
   }
 
@@ -291,13 +292,31 @@
   List<int> _getLibraryClosureHash(Source librarySource) {
     return _libraryClosureHashMap.putIfAbsent(librarySource, () {
       List<Source> closure = _getLibraryClosure(librarySource);
-      MD5 md5 = new MD5();
+
+      Digest digest;
+
+      var digestSink = new ChunkedConversionSink<Digest>.withCallback(
+          (List<Digest> digests) {
+        digest = digests.single;
+      });
+
+      var byteSink = md5.startChunkedConversion(digestSink);
+
       for (Source source in closure) {
         List<int> sourceHash = _getSourceContentHash(source);
-        md5.add(sourceHash);
+        byteSink.add(sourceHash);
       }
-      md5.add(configSalt);
-      return md5.close();
+      byteSink.add(configSalt);
+
+      byteSink.close();
+      // TODO(paulberry): this call to `close` should not be needed.
+      // Can be removed once
+      //   https://github.com/dart-lang/crypto/issues/33
+      // is fixed – ensure the min version constraint on crypto is updated, tho.
+      // Does not cause any problems in the mean time.
+      digestSink.close();
+
+      return digest.bytes;
     });
   }
 
@@ -308,7 +327,7 @@
     return _sourceContentHashMap.putIfAbsent(source, () {
       String sourceText = source.contents.data;
       List<int> sourceBytes = UTF8.encode(sourceText);
-      return (new MD5()..add(sourceBytes)).close();
+      return md5.convert(sourceBytes).bytes;
     });
   }
 
diff --git a/pkg/analyzer/lib/src/summary/index_unit.dart b/pkg/analyzer/lib/src/summary/index_unit.dart
index 610fba4..bc09ee3 100644
--- a/pkg/analyzer/lib/src/summary/index_unit.dart
+++ b/pkg/analyzer/lib/src/summary/index_unit.dart
@@ -204,6 +204,7 @@
    * This method is static, so it cannot add any information to the index.
    */
   static ElementInfo newElementInfo(int unitId, Element element) {
+    int offset = null;
     IndexSyntheticElementKind kind = IndexSyntheticElementKind.notSynthetic;
     if (element.isSynthetic) {
       if (element is ConstructorElement) {
@@ -242,11 +243,11 @@
         throw new ArgumentError(
             'Unsupported synthetic element ${element.runtimeType}');
       }
-    }
-    int offset = element.nameOffset;
-    if (element is LibraryElement || element is CompilationUnitElement) {
+    } else if (element is LibraryElement || element is CompilationUnitElement) {
+      kind = IndexSyntheticElementKind.unit;
       offset = 0;
     }
+    offset ??= element.nameOffset;
     return new ElementInfo(unitId, offset, kind);
   }
 }
diff --git a/pkg/analyzer/lib/src/summary/inspect.dart b/pkg/analyzer/lib/src/summary/inspect.dart
new file mode 100644
index 0000000..799c15e
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary/inspect.dart
@@ -0,0 +1,441 @@
+// 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:convert';
+import 'dart:mirrors';
+
+import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/summary/base.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+
+const int MAX_LINE_LENGTH = 80;
+
+/**
+ * Cache used to speed up [isEnum].
+ */
+Map<Type, bool> _isEnumCache = <Type, bool>{};
+
+/**
+ * Determine if the given [obj] has an enumerated type.
+ */
+bool isEnum(Object obj) {
+  return _isEnumCache.putIfAbsent(
+      obj.runtimeType, () => reflect(obj).type.isEnum);
+}
+
+/**
+ * Decoded reprensentation of a part of a summary that occupies multiple lines
+ * of output.
+ */
+class BrokenEntity implements DecodedEntity {
+  final String opener;
+  final Map<String, DecodedEntity> parts;
+  final String closer;
+
+  BrokenEntity(this.opener, this.parts, this.closer);
+
+  @override
+  List<String> getLines() {
+    List<String> result = <String>[opener];
+    bool first = true;
+    for (String key in parts.keys) {
+      if (first) {
+        first = false;
+      } else {
+        result[result.length - 1] += ',';
+      }
+      List<String> subResult = parts[key].getLines();
+      subResult[0] = '$key: ${subResult[0]}';
+      result.addAll(subResult.map((String s) => '  $s'));
+    }
+    result.add(closer);
+    return result;
+  }
+}
+
+/**
+ * Decoded representation of a part of a summary.
+ */
+abstract class DecodedEntity {
+  /**
+   * Create a representation of a part of the summary that consists of a group
+   * of entities (represented by [parts]) contained between [opener] and
+   * [closer].
+   *
+   * If [forceKeys] is `true`, the keys in [parts] will always be shown.  If
+   * [forceKeys] is `false`, they keys will only be shown if the output is
+   * broken into multiple lines.
+   */
+  factory DecodedEntity.group(String opener, Map<String, DecodedEntity> parts,
+      String closer, bool forceKeys) {
+    // Attempt to format the entity in a single line; if not bail out and
+    // construct a _BrokenEntity.
+    DecodedEntity bailout() => new BrokenEntity(opener, parts, closer);
+    String short = opener;
+    bool first = true;
+    for (String key in parts.keys) {
+      if (first) {
+        first = false;
+      } else {
+        short += ', ';
+      }
+      DecodedEntity value = parts[key];
+      if (forceKeys) {
+        short += '$key: ';
+      }
+      if (value is UnbrokenEntity) {
+        short += value._s;
+      } else {
+        return bailout();
+      }
+      if (short.length > MAX_LINE_LENGTH) {
+        return bailout();
+      }
+    }
+    return new DecodedEntity.short(short + closer);
+  }
+
+  /**
+   * Create a representation of a part of the summary that is represented by a
+   * single unbroken string.
+   */
+  factory DecodedEntity.short(String s) = UnbrokenEntity;
+
+  /**
+   * Format this entity into a sequence of strings (one per output line).
+   */
+  List<String> getLines();
+}
+
+/**
+ * Wrapper around a [LinkedLibrary] and its constituent [UnlinkedUnit]s.
+ */
+class LibraryWrapper {
+  final LinkedLibrary _linked;
+  final List<UnlinkedUnit> _unlinked;
+
+  LibraryWrapper(this._linked, this._unlinked);
+}
+
+/**
+ * Wrapper around a [LinkedReference] and its corresponding [UnlinkedReference].
+ */
+class ReferenceWrapper {
+  final LinkedReference _linked;
+  final UnlinkedReference _unlinked;
+
+  ReferenceWrapper(this._linked, this._unlinked);
+
+  String get name {
+    if (_linked != null && _linked.name.isNotEmpty) {
+      return _linked.name;
+    } else if (_unlinked != null && _unlinked.name.isNotEmpty) {
+      return _unlinked.name;
+    } else {
+      return '???';
+    }
+  }
+}
+
+/**
+ * Instances of [SummaryInspector] are capable of traversing a summary and
+ * converting it to semi-human-readable output.
+ */
+class SummaryInspector {
+  /**
+   * The dependencies of the library currently being visited.
+   */
+  List<LinkedDependency> _dependencies;
+
+  /**
+   * The references of the unit currently being visited.
+   */
+  List<ReferenceWrapper> _references;
+
+  /**
+   * Indicates whether summary inspection should operate in "raw" mode.  In this
+   * mode, the structure of the summary file is not altered for easier
+   * readability; everything is output in exactly the form in which it appears
+   * in the file.
+   */
+  final bool raw;
+
+  SummaryInspector(this.raw);
+
+  /**
+   * Decode the object [obj], which was reached by examining [key] inside
+   * another object.
+   */
+  DecodedEntity decode(Object obj, String key) {
+    if (!raw && obj is PackageBundle) {
+      return decodePackageBundle(obj);
+    }
+    if (obj is LibraryWrapper) {
+      return decodeLibrary(obj);
+    }
+    if (obj is UnitWrapper) {
+      return decodeUnit(obj);
+    }
+    if (obj is ReferenceWrapper) {
+      return decodeReference(obj);
+    }
+    if (obj is DecodedEntity) {
+      return obj;
+    }
+    if (obj is SummaryClass) {
+      Map<String, Object> map = obj.toMap();
+      return decodeMap(map);
+    } else if (obj is List) {
+      Map<String, DecodedEntity> parts = <String, DecodedEntity>{};
+      for (int i = 0; i < obj.length; i++) {
+        parts[i.toString()] = decode(obj[i], key);
+      }
+      return new DecodedEntity.group('[', parts, ']', false);
+    } else if (obj is String) {
+      return new DecodedEntity.short(JSON.encode(obj));
+    } else if (isEnum(obj)) {
+      return new DecodedEntity.short(obj.toString().split('.')[1]);
+    } else if (obj is int &&
+        key == 'dependency' &&
+        _dependencies != null &&
+        obj < _dependencies.length) {
+      return new DecodedEntity.short('$obj (${_dependencies[obj].uri})');
+    } else if (obj is int &&
+        key == 'reference' &&
+        _references != null &&
+        obj < _references.length) {
+      return new DecodedEntity.short('$obj (${_references[obj].name})');
+    } else {
+      return new DecodedEntity.short(obj.toString());
+    }
+  }
+
+  /**
+   * Decode the given [LibraryWrapper].
+   */
+  DecodedEntity decodeLibrary(LibraryWrapper obj) {
+    try {
+      LinkedLibrary linked = obj._linked;
+      List<UnlinkedUnit> unlinked = obj._unlinked;
+      _dependencies = linked.dependencies;
+      Map<String, Object> result = linked.toMap();
+      result.remove('units');
+      result['defining compilation unit'] =
+          new UnitWrapper(linked.units[0], unlinked[0]);
+      for (int i = 1; i < linked.units.length; i++) {
+        String partUri = unlinked[0].publicNamespace.parts[i - 1];
+        result['part ${JSON.encode(partUri)}'] =
+            new UnitWrapper(linked.units[i], unlinked[i]);
+      }
+      return decodeMap(result);
+    } finally {
+      _dependencies = null;
+    }
+  }
+
+  /**
+   * Decode the given [map].
+   */
+  DecodedEntity decodeMap(Map<String, Object> map) {
+    Map<String, DecodedEntity> parts = <String, DecodedEntity>{};
+    map = reorderMap(map);
+    map.forEach((String key, Object value) {
+      if (value is String && value.isEmpty) {
+        return;
+      }
+      if (isEnum(value) && (value as dynamic).index == 0) {
+        return;
+      }
+      if (value is int && value == 0) {
+        return;
+      }
+      if (value is bool && value == false) {
+        return;
+      }
+      if (value == null) {
+        return;
+      }
+      if (value is List) {
+        if (value.isEmpty) {
+          return;
+        }
+        DecodedEntity entity = decode(value, key);
+        if (entity is BrokenEntity) {
+          for (int i = 0; i < value.length; i++) {
+            parts['$key[$i]'] = decode(value[i], key);
+          }
+          return;
+        } else {
+          parts[key] = entity;
+        }
+      }
+      parts[key] = decode(value, key);
+    });
+    return new DecodedEntity.group('{', parts, '}', true);
+  }
+
+  /**
+   * Decode the given [PackageBundle].
+   */
+  DecodedEntity decodePackageBundle(PackageBundle bundle) {
+    Map<String, UnlinkedUnit> units = <String, UnlinkedUnit>{};
+    Set<String> seenUnits = new Set<String>();
+    for (int i = 0; i < bundle.unlinkedUnits.length; i++) {
+      units[bundle.unlinkedUnitUris[i]] = bundle.unlinkedUnits[i];
+    }
+    Map<String, Object> restOfMap = bundle.toMap();
+    Map<String, Object> result = <String, Object>{};
+    result['version'] = new DecodedEntity.short(
+        '${bundle.majorVersion}.${bundle.minorVersion}');
+    restOfMap.remove('majorVersion');
+    restOfMap.remove('minorVersion');
+    result['linkedLibraryUris'] = restOfMap['linkedLibraryUris'];
+    result['unlinkedUnitUris'] = restOfMap['unlinkedUnitUris'];
+    for (int i = 0; i < bundle.linkedLibraries.length; i++) {
+      String libraryUriString = bundle.linkedLibraryUris[i];
+      Uri libraryUri = Uri.parse(libraryUriString);
+      UnlinkedUnit unlinkedDefiningUnit = units[libraryUriString];
+      seenUnits.add(libraryUriString);
+      List<UnlinkedUnit> libraryUnits = <UnlinkedUnit>[unlinkedDefiningUnit];
+      LinkedLibrary linkedLibrary = bundle.linkedLibraries[i];
+      for (int j = 1; j < linkedLibrary.units.length; j++) {
+        String partUriString = resolveRelativeUri(libraryUri,
+                Uri.parse(unlinkedDefiningUnit.publicNamespace.parts[j - 1]))
+            .toString();
+        libraryUnits.add(units[partUriString]);
+        seenUnits.add(partUriString);
+      }
+      result['library ${JSON.encode(libraryUriString)}'] =
+          new LibraryWrapper(linkedLibrary, libraryUnits);
+    }
+    for (String uriString in units.keys) {
+      if (seenUnits.contains(uriString)) {
+        continue;
+      }
+      result['orphan unit ${JSON.encode(uriString)}'] =
+          new UnitWrapper(null, units[uriString]);
+    }
+    restOfMap.remove('linkedLibraries');
+    restOfMap.remove('linkedLibraryUris');
+    restOfMap.remove('unlinkedUnits');
+    restOfMap.remove('unlinkedUnitUris');
+    result.addAll(restOfMap);
+    return decodeMap(result);
+  }
+
+  /**
+   * Decode the given [ReferenceWrapper].
+   */
+  DecodedEntity decodeReference(ReferenceWrapper obj) {
+    Map<String, Object> result = obj._unlinked != null
+        ? obj._unlinked.toMap()
+        : <String, Object>{'linkedOnly': true};
+    if (obj._linked != null) {
+      mergeMaps(result, obj._linked.toMap());
+    }
+    return decodeMap(result);
+  }
+
+  /**
+   * Decode the given [UnitWrapper].
+   */
+  DecodedEntity decodeUnit(UnitWrapper obj) {
+    try {
+      LinkedUnit linked = obj._linked;
+      UnlinkedUnit unlinked = obj._unlinked ?? new UnlinkedUnitBuilder();
+      Map<String, Object> unlinkedMap = unlinked.toMap();
+      Map<String, Object> linkedMap =
+          linked != null ? linked.toMap() : <String, Object>{};
+      Map<String, Object> result = <String, Object>{};
+      List<ReferenceWrapper> references = <ReferenceWrapper>[];
+      int numReferences = linked != null
+          ? linked.references.length
+          : unlinked.references.length;
+      for (int i = 0; i < numReferences; i++) {
+        references.add(new ReferenceWrapper(
+            linked != null ? linked.references[i] : null,
+            i < unlinked.references.length ? unlinked.references[i] : null));
+      }
+      result['references'] = references;
+      _references = references;
+      unlinkedMap.remove('references');
+      linkedMap.remove('references');
+      linkedMap.forEach((String key, Object value) {
+        result['linked $key'] = value;
+      });
+      unlinkedMap.forEach((String key, Object value) {
+        result[key] = value;
+      });
+      return decodeMap(result);
+    } finally {
+      _references = null;
+    }
+  }
+
+  /**
+   * Decode the given [PackageBundle] and dump it to a list of strings.
+   */
+  List<String> dumpPackageBundle(PackageBundle bundle) {
+    DecodedEntity decoded = decode(bundle, 'PackageBundle');
+    return decoded.getLines();
+  }
+
+  /**
+   * Merge the contents of [other] into [result], discarding empty entries.
+   */
+  void mergeMaps(Map<String, Object> result, Map<String, Object> other) {
+    other.forEach((String key, Object value) {
+      if (value is String && value.isEmpty) {
+        return;
+      }
+      if (result.containsKey(key)) {
+        Object oldValue = result[key];
+        if (oldValue is String && oldValue.isEmpty) {
+          result[key] = value;
+        } else {
+          throw new Exception(
+              'Duplicate values for $key: $oldValue and $value');
+        }
+      } else {
+        result[key] = value;
+      }
+    });
+  }
+
+  /**
+   * Reorder [map] for more intuitive display.
+   */
+  Map<String, Object> reorderMap(Map<String, Object> map) {
+    Map<String, Object> result = <String, Object>{};
+    if (map.containsKey('name')) {
+      result['name'] = map['name'];
+    }
+    result.addAll(map);
+    return result;
+  }
+}
+
+/**
+ * Decoded reprensentation of a part of a summary that occupies a single line of
+ * output.
+ */
+class UnbrokenEntity implements DecodedEntity {
+  final String _s;
+
+  UnbrokenEntity(this._s);
+
+  @override
+  List<String> getLines() => <String>[_s];
+}
+
+/**
+ * Wrapper around a [LinkedUnit] and its corresponding [UnlinkedUnit].
+ */
+class UnitWrapper {
+  final LinkedUnit _linked;
+  final UnlinkedUnit _unlinked;
+
+  UnitWrapper(this._linked, this._unlinked);
+}
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index 8d7d33e..0aff6d2 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -64,6 +64,8 @@
 import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/inheritance_manager.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/format.dart';
@@ -164,12 +166,8 @@
   if (type is InterfaceType) {
     ClassElementForLink element = type.element;
     result.reference = compilationUnit.addReference(element);
-    if (type.typeArguments.isNotEmpty) {
-      result.typeArguments = type.typeArguments
-          .map((DartType t) =>
-              _createLinkedType(t, compilationUnit, typeParameterContext))
-          .toList();
-    }
+    _storeTypeArguments(
+        type.typeArguments, result, compilationUnit, typeParameterContext);
     return result;
   } else if (type is DynamicTypeImpl) {
     result.reference = compilationUnit.addRawReference('dynamic');
@@ -189,24 +187,22 @@
     Element element = type.element;
     if (element is FunctionElementForLink_FunctionTypedParam) {
       result.reference =
-          compilationUnit.addReference(element.enclosingExecutable);
+          compilationUnit.addReference(element.innermostExecutable);
       result.implicitFunctionTypeIndices = element.implicitFunctionTypeIndices;
-      if (type.typeArguments.isNotEmpty) {
-        result.typeArguments = type.typeArguments
-            .map((DartType t) =>
-                _createLinkedType(t, compilationUnit, typeParameterContext))
-            .toList();
-      }
+      _storeTypeArguments(
+          type.typeArguments, result, compilationUnit, typeParameterContext);
+      return result;
+    }
+    if (element is TopLevelFunctionElementForLink) {
+      result.reference = compilationUnit.addReference(element);
+      _storeTypeArguments(
+          type.typeArguments, result, compilationUnit, typeParameterContext);
       return result;
     }
     if (element is MethodElementForLink) {
       result.reference = compilationUnit.addReference(element);
-      if (type.typeArguments.isNotEmpty) {
-        result.typeArguments = type.typeArguments
-            .map((DartType t) =>
-                _createLinkedType(t, compilationUnit, typeParameterContext))
-            .toList();
-      }
+      _storeTypeArguments(
+          type.typeArguments, result, compilationUnit, typeParameterContext);
       return result;
     }
     // TODO(paulberry): implement other cases.
@@ -217,6 +213,34 @@
 }
 
 /**
+ * Store the given [typeArguments] in [encodedType], using [compilationUnit] and
+ * [typeParameterContext] to serialize them.
+ *
+ * Trailing arguments of type `dynamic` are dropped.
+ */
+void _storeTypeArguments(
+    List<DartType> typeArguments,
+    EntityRefBuilder encodedType,
+    CompilationUnitElementInBuildUnit compilationUnit,
+    TypeParameterizedElementForLink typeParameterContext) {
+  int count = typeArguments.length;
+  while (count > 0) {
+    if (typeArguments[count - 1].isDynamic) {
+      count--;
+    } else {
+      List<EntityRefBuilder> encodedTypeArguments =
+          new List<EntityRefBuilder>(count);
+      for (int i = 0; i < count; i++) {
+        encodedTypeArguments[i] = _createLinkedType(
+            typeArguments[i], compilationUnit, typeParameterContext);
+      }
+      encodedType.typeArguments = encodedTypeArguments;
+      break;
+    }
+  }
+}
+
+/**
  * Type of the callback used by [link] and [relink] to request
  * [LinkedLibrary] objects from other build units.
  */
@@ -419,6 +443,9 @@
   }
 
   @override
+  String get identifier => name;
+
+  @override
   List<InterfaceType> get interfaces => _interfaces ??=
       _unlinkedClass.interfaces.map(_computeInterfaceType).toList();
 
@@ -535,6 +562,9 @@
     }
   }
 
+  @override
+  String toString() => '$enclosingElement.$name';
+
   /**
    * Convert [typeRef] into an [InterfaceType].
    */
@@ -627,13 +657,17 @@
 
   @override
   void link(CompilationUnitElementInBuildUnit compilationUnit) {}
+
+  @override
+  String toString() => '$enclosingElement.$name';
 }
 
 /**
  * Element representing a compilation unit resynthesized from a
  * summary during linking.
  */
-abstract class CompilationUnitElementForLink implements CompilationUnitElement {
+abstract class CompilationUnitElementForLink
+    implements CompilationUnitElementImpl {
   /**
    * The unlinked representation of the compilation unit in the
    * summary.
@@ -646,19 +680,24 @@
    */
   final List<ReferenceableElementForLink> _references;
 
-  List<ClassElementForLink_Class> _types;
+  /**
+   * The absolute URI of this compilation unit.
+   */
+  final String _absoluteUri;
 
+  List<ClassElementForLink_Class> _types;
   Map<String, ReferenceableElementForLink> _containedNames;
   List<TopLevelVariableElementForLink> _topLevelVariables;
   List<ClassElementForLink_Enum> _enums;
+  List<TopLevelFunctionElementForLink> _functions;
 
   /**
    * Index of this unit in the list of units in the enclosing library.
    */
   final int unitNum;
 
-  CompilationUnitElementForLink(
-      UnlinkedUnit unlinkedUnit, this.unitNum, int numReferences)
+  CompilationUnitElementForLink(UnlinkedUnit unlinkedUnit, this.unitNum,
+      int numReferences, this._absoluteUri)
       : _references = new List<ReferenceableElementForLink>(numReferences),
         _unlinkedUnit = unlinkedUnit;
 
@@ -676,6 +715,22 @@
     return _enums;
   }
 
+  @override
+  List<TopLevelFunctionElementForLink> get functions {
+    if (_functions == null) {
+      _functions = <TopLevelFunctionElementForLink>[];
+      for (UnlinkedExecutable executable in _unlinkedUnit.executables) {
+        if (executable.kind == UnlinkedExecutableKind.functionOrMethod) {
+          _functions.add(new TopLevelFunctionElementForLink(this, executable));
+        }
+      }
+    }
+    return _functions;
+  }
+
+  @override
+  String get identifier => _absoluteUri;
+
   /**
    * Indicates whether this compilation element is part of the build unit
    * currently being linked.
@@ -743,6 +798,9 @@
       for (TopLevelVariableElementForLink variable in topLevelVariables) {
         _containedNames[variable.name] = variable;
       }
+      for (TopLevelFunctionElementForLink function in functions) {
+        _containedNames[function.name] = function;
+      }
       // TODO(paulberry): fill in other top level entities (typedefs
       // and executables).
     }
@@ -761,6 +819,9 @@
   @override
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 
+  @override
+  String toString() => enclosingElement.toString();
+
   /**
    * Return the element referred to by the given [index] in
    * [UnlinkedUnit.references].  If the reference is unresolved,
@@ -854,9 +915,14 @@
   @override
   final LibraryElementInBuildUnit enclosingElement;
 
-  CompilationUnitElementInBuildUnit(this.enclosingElement,
-      UnlinkedUnit unlinkedUnit, this._linkedUnit, int unitNum)
-      : super(unlinkedUnit, unitNum, unlinkedUnit.references.length);
+  CompilationUnitElementInBuildUnit(
+      this.enclosingElement,
+      UnlinkedUnit unlinkedUnit,
+      this._linkedUnit,
+      int unitNum,
+      String absoluteUri)
+      : super(
+            unlinkedUnit, unitNum, unlinkedUnit.references.length, absoluteUri);
 
   @override
   bool get isInBuildUnit => true;
@@ -918,13 +984,13 @@
           numTypeParameters: element.typeParameters.length,
           unitNum: element.enclosingElement.unitNum);
     } else if (element is ExecutableElementForLink) {
-      // TODO(paulberry): will this code ever be executed for an executable
-      // element that's not inside a class?
-      assert(element.enclosingElement is ClassElementForLink_Class);
+      ClassElementForLink_Class enclosingClass = element.enclosingClass;
       ReferenceKind kind;
       switch (element._unlinkedExecutable.kind) {
         case UnlinkedExecutableKind.functionOrMethod:
-          kind = ReferenceKind.method;
+          kind = enclosingClass != null
+              ? ReferenceKind.method
+              : ReferenceKind.topLevelFunction;
           break;
         case UnlinkedExecutableKind.setter:
           kind = ReferenceKind.propertyAccessor;
@@ -935,7 +1001,8 @@
       }
       return addRawReference(element.name,
           numTypeParameters: element.typeParameters.length,
-          containingReference: addReference(element.enclosingElement),
+          containingReference:
+              enclosingClass != null ? addReference(enclosingClass) : null,
           kind: kind);
     }
     // TODO(paulberry): implement other cases
@@ -1020,10 +1087,15 @@
   @override
   final LibraryElementInDependency enclosingElement;
 
-  CompilationUnitElementInDependency(this.enclosingElement,
-      UnlinkedUnit unlinkedUnit, LinkedUnit linkedUnit, int unitNum)
+  CompilationUnitElementInDependency(
+      this.enclosingElement,
+      UnlinkedUnit unlinkedUnit,
+      LinkedUnit linkedUnit,
+      int unitNum,
+      String absoluteUri)
       : _linkedUnit = linkedUnit,
-        super(unlinkedUnit, unitNum, linkedUnit.references.length) {
+        super(
+            unlinkedUnit, unitNum, linkedUnit.references.length, absoluteUri) {
     // Make one pass through the linked types to determine the lengths for
     // _linkedTypeRefs and _linkedTypes.  TODO(paulberry): add an int to the
     // summary to make this unnecessary.
@@ -1115,7 +1187,7 @@
             UnlinkedConstructorInitializerKind.thisInvocation) {
           defaultSuperInvocationNeeded = false;
           ConstructorElementForLink constructor = constructorElement
-              .enclosingElement
+              .enclosingClass
               .getContainedName(constructorInitializer.name)
               .asConstructor;
           safeAddDependency(constructor?._constNode);
@@ -1161,7 +1233,7 @@
     EntityRef redirectedConstructor =
         constructorElement._unlinkedExecutable.redirectedConstructor;
     if (redirectedConstructor != null) {
-      return constructorElement.enclosingElement.enclosingElement
+      return constructorElement.enclosingUnit
           ._resolveRef(redirectedConstructor.reference)
           .asConstructor;
     } else {
@@ -1283,10 +1355,11 @@
    */
   ConstConstructorNode _constNode;
 
-  ConstructorElementForLink(ClassElementForLink_Class enclosingElement,
+  ConstructorElementForLink(ClassElementForLink_Class enclosingClass,
       UnlinkedExecutable unlinkedExecutable)
-      : super(enclosingElement, unlinkedExecutable) {
-    if (enclosingElement.enclosingElement.isInBuildUnit &&
+      : super(enclosingClass.enclosingElement, enclosingClass,
+            unlinkedExecutable) {
+    if (enclosingClass.enclosingElement.isInBuildUnit &&
         _unlinkedExecutable != null &&
         _unlinkedExecutable.constCycleSlot != 0) {
       _constNode = new ConstConstructorNode(this);
@@ -1380,6 +1453,22 @@
 }
 
 /**
+ * Stub implementation of [AnalysisContext] which provides just those methods
+ * needed during linking.
+ */
+class ContextForLink implements AnalysisContext {
+  final Linker _linker;
+
+  ContextForLink(this._linker);
+
+  @override
+  TypeSystem get typeSystem => _linker.typeSystem;
+
+  @override
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+/**
  * An instance of [DependencyWalker] contains the core algorithms for
  * walking a dependency graph and evaluating nodes in a safe order.
  */
@@ -1510,7 +1599,7 @@
  * linking.
  */
 abstract class ExecutableElementForLink extends Object
-    with TypeParameterizedElementForLink
+    with TypeParameterizedElementForLink, ParameterParentElementForLink
     implements ExecutableElementImpl {
   /**
    * The unlinked representation of the method in the summary.
@@ -1522,30 +1611,92 @@
   FunctionTypeImpl _type;
   List<TypeParameterElementForLink> _typeParameters;
   String _name;
-  List<ParameterElementForLink> _parameters;
+  String _displayName;
 
   /**
-   * TODO(paulberry): this won't always be a class element.
+   * Return the class in which this executable appears, maybe `null` for a
+   * top-level function.
    */
-  @override
-  final ClassElementForLink_Class enclosingElement;
-
-  ExecutableElementForLink(this.enclosingElement, this._unlinkedExecutable);
+  final ClassElementForLink_Class enclosingClass;
 
   /**
    * Return the compilation unit in which this executable appears.
    */
-  CompilationUnitElementForLink get compilationUnit =>
-      enclosingElement.enclosingElement;
+  final CompilationUnitElementForLink enclosingUnit;
+
+  ExecutableElementForLink(
+      this.enclosingUnit, this.enclosingClass, this._unlinkedExecutable);
+
+  /**
+   * If the executable element had an explicitly declared return type, return
+   * it.  Otherwise return `null`.
+   */
+  DartType get declaredReturnType {
+    if (_unlinkedExecutable.returnType == null) {
+      return null;
+    } else {
+      return _declaredReturnType ??=
+          enclosingUnit._resolveTypeRef(_unlinkedExecutable.returnType, this);
+    }
+  }
+
+  @override
+  String get displayName {
+    if (_displayName == null) {
+      _displayName = _unlinkedExecutable.name;
+      if (_unlinkedExecutable.kind == UnlinkedExecutableKind.setter) {
+        _displayName = _displayName.substring(0, _displayName.length - 1);
+      }
+    }
+    return _displayName;
+  }
+
+  @override
+  Element get enclosingElement => enclosingClass ?? enclosingUnit;
 
   @override
   TypeParameterizedElementForLink get enclosingTypeParameterContext =>
-      enclosingElement;
+      enclosingClass;
 
   @override
   bool get hasImplicitReturnType => _unlinkedExecutable.returnType == null;
 
   @override
+  List<int> get implicitFunctionTypeIndices => const <int>[];
+
+  /**
+   * Return the inferred return type of the executable element.  Should only be
+   * called if no return type was explicitly declared.
+   */
+  DartType get inferredReturnType {
+    // We should only try to infer a return type when none is explicitly
+    // declared.
+    assert(_unlinkedExecutable.returnType == null);
+    if (Linker._initializerTypeInferenceCycle != null &&
+        Linker._initializerTypeInferenceCycle ==
+            enclosingUnit.library.libraryCycleForLink) {
+      // We are currently computing the type of an initializer expression in the
+      // current library cycle, so type inference results should be ignored.
+      return _computeDefaultReturnType();
+    }
+    if (_inferredReturnType == null) {
+      if (_unlinkedExecutable.kind == UnlinkedExecutableKind.constructor) {
+        // TODO(paulberry): implement.
+        throw new UnimplementedError();
+      } else if (enclosingUnit.isInBuildUnit) {
+        _inferredReturnType = _computeDefaultReturnType();
+      } else {
+        _inferredReturnType = enclosingUnit.getLinkedType(
+            _unlinkedExecutable.inferredReturnTypeSlot, this);
+      }
+    }
+    return _inferredReturnType;
+  }
+
+  @override
+  ExecutableElementForLink get innermostExecutable => this;
+
+  @override
   bool get isStatic => _unlinkedExecutable.isStatic;
 
   @override
@@ -1566,47 +1717,7 @@
   }
 
   @override
-  List<ParameterElementForLink> get parameters {
-    if (_parameters == null) {
-      int numParameters = _unlinkedExecutable.parameters.length;
-      _parameters = new List<ParameterElementForLink>(numParameters);
-      for (int i = 0; i < numParameters; i++) {
-        UnlinkedParam unlinkedParam = _unlinkedExecutable.parameters[i];
-        _parameters[i] = new ParameterElementForLink(
-            this, unlinkedParam, this, enclosingElement.enclosingElement, i);
-      }
-    }
-    return _parameters;
-  }
-
-  @override
-  DartType get returnType {
-    if (_inferredReturnType != null) {
-      return _inferredReturnType;
-    } else if (_declaredReturnType == null) {
-      if (_unlinkedExecutable.returnType == null) {
-        if (_unlinkedExecutable.kind == UnlinkedExecutableKind.constructor) {
-          // TODO(paulberry): implement.
-          throw new UnimplementedError();
-        } else if (!compilationUnit.isInBuildUnit) {
-          _inferredReturnType = compilationUnit.getLinkedType(
-              _unlinkedExecutable.inferredReturnTypeSlot, this);
-          return _inferredReturnType;
-        } else if (_unlinkedExecutable.kind == UnlinkedExecutableKind.setter &&
-            library._linker.strongMode) {
-          // In strong mode, setters without an explicit return type are
-          // considered to return `void`.
-          _declaredReturnType = VoidTypeImpl.instance;
-        } else {
-          _declaredReturnType = DynamicTypeImpl.instance;
-        }
-      } else {
-        _declaredReturnType = enclosingElement.enclosingElement
-            ._resolveTypeRef(_unlinkedExecutable.returnType, this);
-      }
-    }
-    return _declaredReturnType;
-  }
+  DartType get returnType => declaredReturnType ?? inferredReturnType;
 
   @override
   void set returnType(DartType inferredType) {
@@ -1618,6 +1729,9 @@
   FunctionTypeImpl get type => _type ??= new FunctionTypeImpl(this);
 
   @override
+  List<UnlinkedParam> get unlinkedParameters => _unlinkedExecutable.parameters;
+
+  @override
   List<UnlinkedTypeParam> get _unlinkedTypeParams =>
       _unlinkedExecutable.typeParameters;
 
@@ -1629,12 +1743,30 @@
    * Store the results of type inference for this method in [compilationUnit].
    */
   void link(CompilationUnitElementInBuildUnit compilationUnit) {
-    compilationUnit._storeLinkedType(
-        _unlinkedExecutable.inferredReturnTypeSlot, returnType, this);
+    if (_unlinkedExecutable.returnType == null) {
+      compilationUnit._storeLinkedType(
+          _unlinkedExecutable.inferredReturnTypeSlot, inferredReturnType, this);
+    }
     for (ParameterElementForLink parameterElement in parameters) {
       parameterElement.link(compilationUnit);
     }
   }
+
+  /**
+   * Compute the default return type for this type of executable element (if no
+   * return type is declared and strong mode type inference cannot infer a
+   * better return type).
+   */
+  DartType _computeDefaultReturnType() {
+    if (_unlinkedExecutable.kind == UnlinkedExecutableKind.setter &&
+        library._linker.strongMode) {
+      // In strong mode, setters without an explicit return type are
+      // considered to return `void`.
+      return VoidTypeImpl.instance;
+    } else {
+      return DynamicTypeImpl.instance;
+    }
+  }
 }
 
 class ExprTypeComputer {
@@ -1962,11 +2094,11 @@
     // to infer the type of type arguments.
     stack.length -= numNamed + numPositional;
     strPtr += numNamed;
-    EntityRef ref = unlinkedConst.references[refPtr++];
+    EntityRef ref = _getNextRef();
     ConstructorElementForLink element =
         unit._resolveRef(ref.reference).asConstructor;
     if (element != null) {
-      stack.add(element.enclosingElement.buildType(
+      stack.add(element.enclosingClass.buildType(
           (int i) => i >= ref.typeArguments.length
               ? DynamicTypeImpl.instance
               : unit._resolveTypeRef(
@@ -1983,50 +2115,18 @@
     List<String> namedArgNames = _getNextStrings(numNamed);
     List<DartType> namedArgTypeList = _popList(numNamed);
     List<DartType> positionalArgTypes = _popList(numPositional);
+    // TODO(scheglov) if we pushed target and method name first, we might be
+    // able to move work with arguments in _inferExecutableType()
     String methodName = _getNextString();
     DartType target = stack.removeLast();
     stack.add(() {
       if (target is InterfaceType) {
         MethodElement method = target.lookUpMethod(methodName, library);
-        DartType rawMethodType = method?.type;
-        TypeSystem ts = linker.typeSystem;
-        if (rawMethodType is FunctionType) {
-          if (rawMethodType.typeFormals.isNotEmpty &&
-              ts is StrongTypeSystemImpl) {
-            List<DartType> paramTypes = <DartType>[];
-            List<DartType> argTypes = <DartType>[];
-            // Add positional parameter and argument types.
-            for (int i = 0; i < numPositional; i++) {
-              ParameterElement parameter = rawMethodType.parameters[i];
-              if (parameter != null) {
-                paramTypes.add(parameter.type);
-                argTypes.add(positionalArgTypes[i]);
-              }
-            }
-            // Prepare named argument types map.
-            Map<String, DartType> namedArgTypes = <String, DartType>{};
-            for (int i = 0; i < numNamed; i++) {
-              String name = namedArgNames[i];
-              DartType type = namedArgTypeList[i];
-              namedArgTypes[name] = type;
-            }
-            // Add named parameter and argument types.
-            Map<String, DartType> namedParameterTypes =
-                rawMethodType.namedParameterTypes;
-            namedArgTypes.forEach((String name, DartType argType) {
-              DartType parameterType = namedParameterTypes[name];
-              if (parameterType != null) {
-                paramTypes.add(parameterType);
-                argTypes.add(argType);
-              }
-            });
-            // Perform inference.
-            FunctionType inferred = ts.inferGenericFunctionCall(
-                typeProvider, rawMethodType, paramTypes, argTypes, null);
-            return inferred.returnType;
-          }
-          // Not a generic method, use the raw return type.
-          return rawMethodType.returnType;
+        FunctionType rawType = method?.type;
+        FunctionType inferredType = _inferExecutableType(rawType, numNamed,
+            numPositional, namedArgNames, namedArgTypeList, positionalArgTypes);
+        if (inferredType != null) {
+          return inferredType.returnType;
         }
       }
       return DynamicTypeImpl.instance;
@@ -2036,13 +2136,22 @@
   void _doInvokeMethodRef() {
     int numNamed = _getNextInt();
     int numPositional = _getNextInt();
-    // TODO(paulberry): don't just pop the args; use their types
-    // to infer the type of type arguments.
-    stack.length -= numNamed + numPositional;
-    strPtr += numNamed;
-    refPtr++;
-    // TODO(paulberry): implement.
-    stack.add(DynamicTypeImpl.instance);
+    List<String> namedArgNames = _getNextStrings(numNamed);
+    List<DartType> namedArgTypeList = _popList(numNamed);
+    List<DartType> positionalArgTypes = _popList(numPositional);
+    EntityRef ref = _getNextRef();
+    ReferenceableElementForLink element = unit._resolveRef(ref.reference);
+    stack.add(() {
+      DartType rawType = element.asStaticType;
+      if (rawType is FunctionType) {
+        FunctionType inferredType = _inferExecutableType(rawType, numNamed,
+            numPositional, namedArgNames, namedArgTypeList, positionalArgTypes);
+        if (inferredType != null) {
+          return inferredType.returnType;
+        }
+      }
+      return DynamicTypeImpl.instance;
+    }());
   }
 
   void _doMakeTypedList() {
@@ -2087,7 +2196,7 @@
   }
 
   void _doPushReference() {
-    EntityRef ref = unlinkedConst.references[refPtr++];
+    EntityRef ref = _getNextRef();
     if (ref.paramReference != 0) {
       stack.add(typeProvider.typeType);
     } else {
@@ -2097,8 +2206,7 @@
       // Nor can implicit function types derived from
       // function-typed parameters.
       assert(ref.implicitFunctionTypeIndices.isEmpty);
-      ReferenceableElementForLink element =
-          variable.compilationUnit._resolveRef(ref.reference);
+      ReferenceableElementForLink element = unit._resolveRef(ref.reference);
       stack.add(element.asStaticType);
     }
   }
@@ -2107,6 +2215,8 @@
     return unlinkedConst.ints[intPtr++];
   }
 
+  EntityRef _getNextRef() => unlinkedConst.references[refPtr++];
+
   String _getNextString() {
     return unlinkedConst.strings[strPtr++];
   }
@@ -2120,7 +2230,7 @@
   }
 
   DartType _getNextTypeRef() {
-    EntityRef ref = unlinkedConst.references[refPtr++];
+    EntityRef ref = _getNextRef();
     return unit._resolveTypeRef(ref, variable._typeParameterContext);
   }
 
@@ -2135,6 +2245,53 @@
         : DynamicTypeImpl.instance;
   }
 
+  FunctionType _inferExecutableType(
+      FunctionType rawMethodType,
+      int numNamed,
+      int numPositional,
+      List<String> namedArgNames,
+      List<DartType> namedArgTypeList,
+      List<DartType> positionalArgTypes) {
+    TypeSystem ts = linker.typeSystem;
+    if (rawMethodType != null) {
+      if (rawMethodType.typeFormals.isNotEmpty && ts is StrongTypeSystemImpl) {
+        List<DartType> paramTypes = <DartType>[];
+        List<DartType> argTypes = <DartType>[];
+        // Add positional parameter and argument types.
+        for (int i = 0; i < numPositional; i++) {
+          ParameterElement parameter = rawMethodType.parameters[i];
+          if (parameter != null) {
+            paramTypes.add(parameter.type);
+            argTypes.add(positionalArgTypes[i]);
+          }
+        }
+        // Prepare named argument types map.
+        Map<String, DartType> namedArgTypes = <String, DartType>{};
+        for (int i = 0; i < numNamed; i++) {
+          String name = namedArgNames[i];
+          DartType type = namedArgTypeList[i];
+          namedArgTypes[name] = type;
+        }
+        // Add named parameter and argument types.
+        Map<String, DartType> namedParameterTypes =
+            rawMethodType.namedParameterTypes;
+        namedArgTypes.forEach((String name, DartType argType) {
+          DartType parameterType = namedParameterTypes[name];
+          if (parameterType != null) {
+            paramTypes.add(parameterType);
+            argTypes.add(argType);
+          }
+        });
+        // Perform inference.
+        FunctionType inferred = ts.inferGenericFunctionCall(
+            typeProvider, rawMethodType, paramTypes, argTypes, null);
+        return inferred;
+      }
+    }
+    // Not a generic function type, use the raw type.
+    return rawMethodType;
+  }
+
   DartType _leastUpperBound(DartType s, DartType t) {
     return linker.typeSystem.getLeastUpperBound(typeProvider, s, t);
   }
@@ -2264,12 +2421,10 @@
 
   /**
    * If this is an instance field, the type that was computed by
-   * [InstanceMemberInferrer].
+   * [InstanceMemberInferrer] (if any).  Otherwise `null`.
    */
   DartType _inferredInstanceType;
 
-  DartType _declaredType;
-
   FieldElementForLink_ClassField(ClassElementForLink_Class enclosingElement,
       UnlinkedVariable unlinkedVariable)
       : enclosingElement = enclosingElement,
@@ -2279,29 +2434,6 @@
   bool get isStatic => unlinkedVariable.isStatic;
 
   @override
-  DartType get type {
-    // TODO(paulberry): can this be unified with
-    // [VariableElementForLink.asStaticType]?
-    assert(!isStatic);
-    if (_inferredInstanceType != null) {
-      return _inferredInstanceType;
-    } else if (_declaredType == null) {
-      if (unlinkedVariable.type == null) {
-        if (!compilationUnit.isInBuildUnit) {
-          _inferredInstanceType = compilationUnit.getLinkedType(
-              unlinkedVariable.inferredTypeSlot, enclosingElement);
-          return _inferredInstanceType;
-        }
-        _declaredType = DynamicTypeImpl.instance;
-      } else {
-        _declaredType = compilationUnit._resolveTypeRef(
-            unlinkedVariable.type, enclosingElement);
-      }
-    }
-    return _declaredType;
-  }
-
-  @override
   void set type(DartType inferredType) {
     assert(!isStatic);
     assert(_inferredInstanceType == null);
@@ -2317,18 +2449,15 @@
    */
   void link(CompilationUnitElementInBuildUnit compilationUnit) {
     if (hasImplicitType) {
-      if (isStatic) {
-        TypeInferenceNode typeInferenceNode = this.asTypeInferenceNode;
-        if (typeInferenceNode != null) {
-          compilationUnit._storeLinkedType(unlinkedVariable.inferredTypeSlot,
-              typeInferenceNode.inferredType, enclosingElement);
-        }
-      } else {
-        compilationUnit._storeLinkedType(unlinkedVariable.inferredTypeSlot,
-            _inferredInstanceType, enclosingElement);
-      }
+      compilationUnit._storeLinkedType(
+          unlinkedVariable.inferredTypeSlot,
+          isStatic ? inferredType : _inferredInstanceType,
+          _typeParameterContext);
     }
   }
+
+  @override
+  String toString() => '$enclosingElement.$name';
 }
 
 /**
@@ -2385,32 +2514,43 @@
 
   @override
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+
+  @override
+  String toString() => '$enclosingElement.$name';
 }
 
 /**
  * Element representing a function-typed parameter resynthesied from a summary
  * during linking.
  */
-class FunctionElementForLink_FunctionTypedParam implements FunctionElement {
+class FunctionElementForLink_FunctionTypedParam extends Object
+    with ParameterParentElementForLink
+    implements FunctionElement {
   @override
   final ParameterElementForLink enclosingElement;
 
-  /**
-   * The executable element containing this function-typed parameter.
-   */
-  final Element enclosingExecutable;
+  @override
+  final ExecutableElementForLink innermostExecutable;
 
-  /**
-   * The appropriate integer list to store in
-   * [EntityRef.implicitFunctionTypeIndices] to refer to this function-typed
-   * parameter.
-   */
-  final List<int> implicitFunctionTypeIndices;
+  @override
+  final List<UnlinkedParam> unlinkedParameters;
 
   DartType _returnType;
+  List<int> _implicitFunctionTypeIndices;
 
-  FunctionElementForLink_FunctionTypedParam(this.enclosingElement,
-      this.enclosingExecutable, this.implicitFunctionTypeIndices);
+  FunctionElementForLink_FunctionTypedParam(
+      this.enclosingElement, this.innermostExecutable, this.unlinkedParameters);
+
+  @override
+  List<int> get implicitFunctionTypeIndices {
+    if (_implicitFunctionTypeIndices == null) {
+      _implicitFunctionTypeIndices = enclosingElement
+          .enclosingElement.implicitFunctionTypeIndices
+          .toList();
+      _implicitFunctionTypeIndices.add(enclosingElement._parameterIndex);
+    }
+    return _implicitFunctionTypeIndices;
+  }
 
   @override
   DartType get returnType {
@@ -2419,8 +2559,7 @@
         _returnType = DynamicTypeImpl.instance;
       } else {
         _returnType = enclosingElement.compilationUnit._resolveTypeRef(
-            enclosingElement._unlinkedParam.type,
-            enclosingElement._typeParameterContext);
+            enclosingElement._unlinkedParam.type, innermostExecutable);
       }
     }
     return _returnType;
@@ -2447,9 +2586,8 @@
   @override
   DartType get returnType {
     // If this is a variable whose type needs inferring, infer it.
-    TypeInferenceNode typeInferenceNode = _variable._typeInferenceNode;
-    if (typeInferenceNode != null) {
-      return typeInferenceNode.inferredType;
+    if (_variable.hasImplicitType) {
+      return _variable.inferredType;
     } else {
       // There's no reason linking should need to access the type of
       // this FunctionElement, since the variable doesn't need its
@@ -2462,7 +2600,8 @@
 
   @override
   void set returnType(DartType newType) {
-    // TODO(paulberry): store inferred type.
+    // InstanceMemberInferrer stores the new type both here and on the variable
+    // element.  We don't need to record both values, so we ignore it here.
   }
 
   @override
@@ -2592,7 +2731,7 @@
  */
 abstract class LibraryElementForLink<
         UnitElement extends CompilationUnitElementForLink>
-    implements LibraryElement {
+    implements LibraryElementImpl {
   /**
    * Pointer back to the linker.
    */
@@ -2617,6 +2756,9 @@
     }
   }
 
+  @override
+  ContextForLink get context => _linker.context;
+
   /**
    * Get the [UnlinkedUnit] for the defining compilation unit of this library.
    */
@@ -2631,9 +2773,15 @@
       _linkedLibrary.exportDependencies.map(_getDependency).toList();
 
   @override
+  String get identifier => _absoluteUri.toString();
+
+  @override
   List<LibraryElementForLink> get importedLibraries => _importedLibraries ??=
       _linkedLibrary.importDependencies.map(_getDependency).toList();
 
+  @override
+  bool get isDartAsync => _absoluteUri == 'dart:async';
+
   /**
    * If this library is part of the build unit being linked, return the library
    * cycle it is part of.  Otherwise return `null`.
@@ -2644,17 +2792,20 @@
   List<UnitElement> get units {
     if (_units == null) {
       UnlinkedUnit definingUnit = definingUnlinkedUnit;
-      _units = <UnitElement>[_makeUnitElement(definingUnit, 0)];
+      _units = <UnitElement>[
+        _makeUnitElement(definingUnit, 0, _absoluteUri.toString())
+      ];
       int numParts = definingUnit.parts.length;
       for (int i = 0; i < numParts; i++) {
         // TODO(paulberry): make sure we handle the case where Uri.parse fails.
         // TODO(paulberry): make sure we handle the case where
         // resolveRelativeUri fails.
-        UnlinkedUnit partUnit = _linker.getUnit(resolveRelativeUri(
+        String partAbsoluteUri = resolveRelativeUri(
                 _absoluteUri, Uri.parse(definingUnit.publicNamespace.parts[i]))
-            .toString());
-        _units.add(
-            _makeUnitElement(partUnit ?? new UnlinkedUnitBuilder(), i + 1));
+            .toString();
+        UnlinkedUnit partUnit = _linker.getUnit(partAbsoluteUri);
+        _units.add(_makeUnitElement(
+            partUnit ?? new UnlinkedUnitBuilder(), i + 1, partAbsoluteUri));
       }
     }
     return _units;
@@ -2684,6 +2835,9 @@
   @override
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 
+  @override
+  String toString() => _absoluteUri.toString();
+
   /**
    * Return the [LibraryElement] corresponding to the given dependency [index].
    */
@@ -2696,7 +2850,8 @@
    * Create a [UnitElement] for one of the library's compilation
    * units.
    */
-  UnitElement _makeUnitElement(UnlinkedUnit unlinkedUnit, int i);
+  UnitElement _makeUnitElement(
+      UnlinkedUnit unlinkedUnit, int i, String absoluteUri);
 }
 
 /**
@@ -2777,9 +2932,9 @@
 
   @override
   CompilationUnitElementInBuildUnit _makeUnitElement(
-          UnlinkedUnit unlinkedUnit, int i) =>
+          UnlinkedUnit unlinkedUnit, int i, String absoluteUri) =>
       new CompilationUnitElementInBuildUnit(
-          this, unlinkedUnit, _linkedLibrary.units[i], i);
+          this, unlinkedUnit, _linkedLibrary.units[i], i, absoluteUri);
 }
 
 /**
@@ -2800,9 +2955,9 @@
 
   @override
   CompilationUnitElementInDependency _makeUnitElement(
-          UnlinkedUnit unlinkedUnit, int i) =>
+          UnlinkedUnit unlinkedUnit, int i, String absoluteUri) =>
       new CompilationUnitElementInDependency(
-          this, unlinkedUnit, _linkedLibrary.units[i], i);
+          this, unlinkedUnit, _linkedLibrary.units[i], i, absoluteUri);
 }
 
 /**
@@ -2851,6 +3006,17 @@
  */
 class Linker {
   /**
+   * During linking, if type inference is currently being performed on the
+   * initializer of a static or instance variable, the library cycle in
+   * which inference is being performed.  Otherwise, `null`.
+   *
+   * This allows us to suppress instance member type inference results from a
+   * library cycle while doing inference on the right hand sides of static and
+   * instance variables in that same cycle.
+   */
+  static LibraryCycleForLink _initializerTypeInferenceCycle;
+
+  /**
    * Callback to ask the client for a [LinkedLibrary] for a
    * dependency.
    */
@@ -2888,6 +3054,7 @@
   SpecialTypeElementForLink _voidElement;
   SpecialTypeElementForLink _dynamicElement;
   SpecialTypeElementForLink _bottomElement;
+  ContextForLink _context;
 
   Linker(Map<String, LinkedLibraryBuilder> linkedLibraries, this.getDependency,
       this.getUnit, this.strongMode) {
@@ -2914,6 +3081,12 @@
       new SpecialTypeElementForLink(this, BottomTypeImpl.instance);
 
   /**
+   * Get a stub implementation of [AnalysisContext] which can be used during
+   * linking.
+   */
+  get context => _context ??= new ContextForLink(this);
+
+  /**
    * Get the library element for `dart:core`.
    */
   LibraryElementForLink get coreLibrary =>
@@ -2979,15 +3152,22 @@
  */
 class MethodElementForLink extends ExecutableElementForLink
     implements MethodElementImpl {
-  MethodElementForLink(ClassElementForLink_Class enclosingElement,
+  MethodElementForLink(ClassElementForLink_Class enclosingClass,
       UnlinkedExecutable unlinkedExecutable)
-      : super(enclosingElement, unlinkedExecutable);
+      : super(enclosingClass.enclosingElement, enclosingClass,
+            unlinkedExecutable);
+
+  @override
+  String get identifier => name;
 
   @override
   ElementKind get kind => ElementKind.METHOD;
 
   @override
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+
+  @override
+  String toString() => '$enclosingElement.$name';
 }
 
 /**
@@ -3030,18 +3210,23 @@
 }
 
 /**
- * Element used for references that result from trying to access a nonstatic
+ * Element used for references that result from trying to access a non-static
  * member of an element that is not a container (e.g. accessing the "length"
  * property of a constant).
  */
 class NonstaticMemberElementForLink implements ReferenceableElementForLink {
   /**
+   * The non-static element of this link element.
+   */
+  final Element element;
+
+  /**
    * If the thing from which a member was accessed is a constant, the
    * associated [ConstNode].  Otherwise `null`.
    */
   final ConstVariableNode _constNode;
 
-  NonstaticMemberElementForLink(this._constNode);
+  NonstaticMemberElementForLink(this.element, this._constNode);
 
   @override
   ConstructorElementForLink get asConstructor => null;
@@ -3051,7 +3236,16 @@
 
   @override
   DartType get asStaticType {
-    // TODO(paulberry): implement.
+    Element element = this.element;
+    if (element is PropertyAccessorElement) {
+      if (element.isGetter) {
+        return element.returnType;
+      }
+      return DynamicTypeImpl.instance;
+    }
+    if (element is MethodElement) {
+      return element.type;
+    }
     return DynamicTypeImpl.instance;
   }
 
@@ -3067,7 +3261,17 @@
       DynamicTypeImpl.instance;
 
   @override
-  ReferenceableElementForLink getContainedName(String name) => this;
+  ReferenceableElementForLink getContainedName(String name) {
+    if (element != null) {
+      DartType type = asStaticType;
+      if (type is InterfaceType) {
+        Element nameElement = type.lookUpGetter(name, element.library);
+        nameElement ??= type.lookUpMethod(name, element.library);
+        return new NonstaticMemberElementForLink(nameElement, _constNode);
+      }
+    }
+    return this;
+  }
 }
 
 /**
@@ -3081,9 +3285,9 @@
   final UnlinkedParam _unlinkedParam;
 
   /**
-   * The context in which type parameters should be interpreted.
+   * The innermost executable element containing this parameter.
    */
-  final TypeParameterizedElementForLink _typeParameterContext;
+  final ExecutableElementForLink _innermostExecutable;
 
   /**
    * If this parameter has a default value and the enclosing library
@@ -3103,13 +3307,13 @@
   final int _parameterIndex;
 
   @override
-  final ExecutableElementForLink enclosingElement;
+  final ParameterParentElementForLink enclosingElement;
 
   DartType _inferredType;
   DartType _declaredType;
 
   ParameterElementForLink(this.enclosingElement, this._unlinkedParam,
-      this._typeParameterContext, this.compilationUnit, this._parameterIndex) {
+      this._innermostExecutable, this.compilationUnit, this._parameterIndex) {
     if (_unlinkedParam.defaultValue != null) {
       _constNode = new ConstParameterNode(this);
     }
@@ -3142,18 +3346,18 @@
       if (_unlinkedParam.isFunctionTyped) {
         _declaredType = new FunctionTypeImpl(
             new FunctionElementForLink_FunctionTypedParam(
-                this, enclosingElement, <int>[_parameterIndex]));
+                this, _innermostExecutable, _unlinkedParam.parameters));
       } else if (_unlinkedParam.type == null) {
         if (!compilationUnit.isInBuildUnit) {
           _inferredType = compilationUnit.getLinkedType(
-              _unlinkedParam.inferredTypeSlot, _typeParameterContext);
+              _unlinkedParam.inferredTypeSlot, _innermostExecutable);
           return _inferredType;
         } else {
           _declaredType = DynamicTypeImpl.instance;
         }
       } else {
         _declaredType = compilationUnit._resolveTypeRef(
-            _unlinkedParam.type, _typeParameterContext);
+            _unlinkedParam.type, _innermostExecutable);
       }
     }
     return _declaredType;
@@ -3171,7 +3375,7 @@
    */
   void link(CompilationUnitElementInBuildUnit compilationUnit) {
     compilationUnit._storeLinkedType(
-        _unlinkedParam.inferredTypeSlot, _inferredType, _typeParameterContext);
+        _unlinkedParam.inferredTypeSlot, _inferredType, _innermostExecutable);
   }
 
   @override
@@ -3179,6 +3383,76 @@
 }
 
 /**
+ * Element representing the parameter of a synthetic setter for a variable
+ * resynthesized during linking.
+ */
+class ParameterElementForLink_VariableSetter implements ParameterElementImpl {
+  @override
+  final PropertyAccessorElementForLink_Variable enclosingElement;
+
+  ParameterElementForLink_VariableSetter(this.enclosingElement);
+
+  @override
+  bool get isSynthetic => true;
+
+  @override
+  String get name => 'x';
+
+  @override
+  ParameterKind get parameterKind => ParameterKind.REQUIRED;
+
+  @override
+  DartType get type => enclosingElement.computeVariableType();
+
+  @override
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+/**
+ * Mixin used by elements that can have parameters.
+ */
+abstract class ParameterParentElementForLink implements Element {
+  List<ParameterElementForLink> _parameters;
+
+  /**
+   * Get the appropriate integer list to store in
+   * [EntityRef.implicitFunctionTypeIndices] to refer to this element.  For an
+   * element representing a function-typed parameter, this should return a
+   * non-empty list.  For an element representing an executable, this should
+   * return the empty list.
+   */
+  List<int> get implicitFunctionTypeIndices;
+
+  /**
+   * Get the innermost enclosing ExecutableElement (which may be [this], or may
+   * be a parent when there are function-typed parameters).
+   */
+  ExecutableElementForLink get innermostExecutable;
+
+  /**
+   * Get all the parameters of this element.
+   */
+  List<ParameterElementForLink> get parameters {
+    if (_parameters == null) {
+      List<UnlinkedParam> unlinkedParameters = this.unlinkedParameters;
+      int numParameters = unlinkedParameters.length;
+      _parameters = new List<ParameterElementForLink>(numParameters);
+      for (int i = 0; i < numParameters; i++) {
+        UnlinkedParam unlinkedParam = unlinkedParameters[i];
+        _parameters[i] = new ParameterElementForLink(this, unlinkedParam,
+            innermostExecutable, innermostExecutable.enclosingUnit, i);
+      }
+    }
+    return _parameters;
+  }
+
+  /**
+   * Get the list of unlinked parameters of this element.
+   */
+  List<UnlinkedParam> get unlinkedParameters;
+}
+
+/**
  * Element representing a getter or setter resynthesized from a summary during
  * linking.
  */
@@ -3197,10 +3471,11 @@
   SyntheticVariableElementForLink variable;
 
   PropertyAccessorElementForLink_Executable(
-      ClassElementForLink_Class enclosingElement,
+      ClassElementForLink_Class enclosingClass,
       UnlinkedExecutable unlinkedExecutable,
       this.variable)
-      : super(enclosingElement, unlinkedExecutable);
+      : super(enclosingClass.enclosingElement, enclosingClass,
+            unlinkedExecutable);
 
   @override
   PropertyAccessorElementForLink_Executable get correspondingGetter =>
@@ -3220,6 +3495,9 @@
 
   @override
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+
+  @override
+  String toString() => '$enclosingElement.$name';
 }
 
 /**
@@ -3231,19 +3509,20 @@
   @override
   final bool isSetter;
 
-  final VariableElementForLink _variable;
+  final VariableElementForLink variable;
   FunctionTypeImpl _type;
+  List<ParameterElement> _parameters;
 
-  PropertyAccessorElementForLink_Variable(this._variable, this.isSetter);
+  PropertyAccessorElementForLink_Variable(this.variable, this.isSetter);
 
   @override
-  Element get enclosingElement => _variable.enclosingElement;
+  Element get enclosingElement => variable.enclosingElement;
 
   @override
   bool get isGetter => !isSetter;
 
   @override
-  bool get isStatic => _variable.isStatic;
+  bool get isStatic => variable.isStatic;
 
   @override
   bool get isSynthetic => true;
@@ -3252,22 +3531,29 @@
   ElementKind get kind => isSetter ? ElementKind.SETTER : ElementKind.GETTER;
 
   @override
-  String get name => isSetter ? '${_variable.name}=' : _variable.name;
+  LibraryElementForLink get library =>
+      variable.compilationUnit.enclosingElement;
+
+  @override
+  String get name => isSetter ? '${variable.name}=' : variable.name;
+
+  @override
+  List<ParameterElement> get parameters {
+    if (_parameters == null) {
+      _parameters = <ParameterElementForLink_VariableSetter>[];
+      if (isSetter) {
+        _parameters.add(new ParameterElementForLink_VariableSetter(this));
+      }
+    }
+    return _parameters;
+  }
 
   @override
   DartType get returnType {
     if (isSetter) {
       return VoidTypeImpl.instance;
-    } else if (_variable.hasImplicitType &&
-        !isStatic &&
-        !_variable.compilationUnit.isTypeInferenceComplete) {
-      // This is an instance field and we are currently inferring types in the
-      // library cycle containing it.  So we shouldn't use the inferred type
-      // (even if we have already computed it), since that would lead to
-      // non-deterministic type inference results.
-      return DynamicTypeImpl.instance;
     } else {
-      return _variable.type;
+      return computeVariableType();
     }
   }
 
@@ -3280,6 +3566,24 @@
     return const [];
   }
 
+  /**
+   * Compute the type of the corresponding variable, which may depend on the
+   * progress of type inference.
+   */
+  DartType computeVariableType() {
+    if (variable.hasImplicitType &&
+        !isStatic &&
+        !variable.compilationUnit.isTypeInferenceComplete) {
+      // This is an instance field and we are currently inferring types in the
+      // library cycle containing it.  So we shouldn't use the inferred type
+      // (even if we have already computed it), since that would lead to
+      // non-deterministic type inference results.
+      return DynamicTypeImpl.instance;
+    } else {
+      return variable.type;
+    }
+  }
+
   @override
   bool isAccessibleIn(LibraryElement library) =>
       !Identifier.isPrivateName(name) || identical(this.library, library);
@@ -3289,6 +3593,9 @@
 
   @override
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+
+  @override
+  String toString() => '$enclosingElement.$name';
 }
 
 /**
@@ -3386,6 +3693,9 @@
   PropertyAccessorElementForLink_Executable get getter => _getter;
 
   @override
+  bool get isSynthetic => true;
+
+  @override
   PropertyAccessorElementForLink_Executable get setter => _setter;
 
   @override
@@ -3396,6 +3706,47 @@
 }
 
 /**
+ * Element representing a top-level function.
+ */
+class TopLevelFunctionElementForLink extends ExecutableElementForLink
+    implements FunctionElementImpl, ReferenceableElementForLink {
+  DartType _returnType;
+
+  TopLevelFunctionElementForLink(
+      CompilationUnitElementForLink enclosingUnit, UnlinkedExecutable _buf)
+      : super(enclosingUnit, null, _buf);
+
+  @override
+  ConstructorElementForLink get asConstructor => null;
+
+  @override
+  ConstVariableNode get asConstVariable => null;
+
+  @override
+  DartType get asStaticType => type;
+
+  @override
+  TypeInferenceNode get asTypeInferenceNode => null;
+
+  @override
+  ElementKind get kind => ElementKind.FUNCTION;
+
+  @override
+  DartType buildType(DartType getTypeArgument(int i),
+          List<int> implicitFunctionTypeIndices) =>
+      DynamicTypeImpl.instance;
+
+  @override
+  ReferenceableElementForLink getContainedName(String name) {
+    // TODO(paulberry): handle references to `call`.
+    return UndefinedElementForLink.instance;
+  }
+
+  @override
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+/**
  * Element representing a top level variable resynthesized from a
  * summary during linking.
  */
@@ -3419,8 +3770,8 @@
     if (hasImplicitType) {
       TypeInferenceNode typeInferenceNode = this.asTypeInferenceNode;
       if (typeInferenceNode != null) {
-        compilationUnit._storeLinkedType(unlinkedVariable.inferredTypeSlot,
-            typeInferenceNode.inferredType, null);
+        compilationUnit._storeLinkedType(
+            unlinkedVariable.inferredTypeSlot, inferredType, null);
       }
     }
   }
@@ -3456,27 +3807,10 @@
    */
   final VariableElementForLink variableElement;
 
-  /**
-   * If a type has been inferred for this node, the inferred type (may be
-   * `dynamic`).  Otherwise `null`.
-   */
-  DartType _inferredType;
-
   TypeInferenceNode(this.variableElement);
 
-  /**
-   * Infer a type for this node if necessary, and return it.
-   */
-  DartType get inferredType {
-    if (_inferredType == null) {
-      new TypeInferenceDependencyWalker().walk(this);
-      assert(_inferredType != null);
-    }
-    return _inferredType;
-  }
-
   @override
-  bool get isEvaluated => _inferredType != null;
+  bool get isEvaluated => variableElement._inferredType != null;
 
   /**
    * Collect the type inference dependencies in [unlinkedConst] (which should be
@@ -3544,9 +3878,10 @@
 
   void evaluate(bool inCycle) {
     if (inCycle) {
-      _inferredType = DynamicTypeImpl.instance;
+      variableElement._inferredType = DynamicTypeImpl.instance;
     } else {
-      _inferredType = new ExprTypeComputer(variableElement).compute();
+      variableElement._inferredType =
+          new ExprTypeComputer(variableElement).compute();
     }
   }
 }
@@ -3555,7 +3890,7 @@
  * Element representing a type parameter resynthesized from a summary during
  * linking.
  */
-class TypeParameterElementForLink implements TypeParameterElement {
+class TypeParameterElementForLink implements TypeParameterElementImpl {
   /**
    * The unlinked representation of the type parameter in the summary.
    */
@@ -3567,9 +3902,14 @@
    */
   final int nestingLevel;
 
-  TypeParameterTypeImpl _type;
+  @override
+  final TypeParameterizedElementForLink enclosingElement;
 
-  TypeParameterElementForLink(this._unlinkedTypeParam, this.nestingLevel);
+  TypeParameterTypeImpl _type;
+  ElementLocation _location;
+
+  TypeParameterElementForLink(
+      this.enclosingElement, this._unlinkedTypeParam, this.nestingLevel);
 
   @override
   DartType get bound {
@@ -3581,9 +3921,16 @@
   }
 
   @override
+  String get identifier => name;
+
+  @override
   ElementKind get kind => ElementKind.TYPE_PARAMETER;
 
   @override
+  ElementLocation get location =>
+      _location ??= new ElementLocationImpl.con1(this);
+
+  @override
   String get name => _unlinkedTypeParam.name;
 
   @override
@@ -3623,7 +3970,7 @@
           new List<TypeParameterElementForLink>(numTypeParameters);
       for (int i = 0; i < numTypeParameters; i++) {
         _typeParameters[i] = new TypeParameterElementForLink(
-            _unlinkedTypeParams[i], enclosingNestingLevel + i);
+            this, _unlinkedTypeParams[i], enclosingNestingLevel + i);
       }
     }
     return _typeParameters;
@@ -3847,7 +4194,10 @@
  * summary during linking.
  */
 class VariableElementForLink
-    implements VariableElementImpl, ReferenceableElementForLink {
+    implements
+        VariableElementImpl,
+        PropertyInducingElement,
+        ReferenceableElementForLink {
   /**
    * The unlinked representation of the variable in the summary.
    */
@@ -3868,7 +4218,8 @@
   TypeInferenceNode _typeInferenceNode;
 
   FunctionElementForLink_Initializer _initializer;
-  DartType _staticType;
+  DartType _inferredType;
+  DartType _declaredType;
 
   /**
    * The compilation unit in which this variable appears.
@@ -3891,32 +4242,55 @@
   ConstVariableNode get asConstVariable => _constNode;
 
   @override
-  DartType get asStaticType {
-    if (_staticType == null) {
-      if (_typeInferenceNode != null) {
-        assert(_typeInferenceNode.isEvaluated);
-        _staticType = _typeInferenceNode.inferredType;
-      } else if (hasImplicitType) {
-        if (!compilationUnit.isInBuildUnit) {
-          _staticType = compilationUnit.getLinkedType(
-              unlinkedVariable.inferredTypeSlot, _typeParameterContext);
-        } else {
-          _staticType = DynamicTypeImpl.instance;
-        }
-      } else {
-        _staticType = compilationUnit._resolveTypeRef(
-            unlinkedVariable.type, _typeParameterContext);
-      }
-    }
-    return _staticType;
-  }
+  DartType get asStaticType => type;
 
   @override
   TypeInferenceNode get asTypeInferenceNode => _typeInferenceNode;
 
+  /**
+   * If the variable has an explicitly declared return type, return it.
+   * Otherwise return `null`.
+   */
+  DartType get declaredType {
+    if (unlinkedVariable.type == null) {
+      return null;
+    } else {
+      return _declaredType ??= compilationUnit._resolveTypeRef(
+          unlinkedVariable.type, _typeParameterContext);
+    }
+  }
+
   @override
   bool get hasImplicitType => unlinkedVariable.type == null;
 
+  /**
+   * Return the inferred type of the variable element.  Should only be called if
+   * no type was explicitly declared.
+   */
+  DartType get inferredType {
+    // We should only try to infer a type when none is explicitly declared.
+    assert(unlinkedVariable.type == null);
+    if (_inferredType == null) {
+      if (_typeInferenceNode != null) {
+        assert(Linker._initializerTypeInferenceCycle == null);
+        Linker._initializerTypeInferenceCycle =
+            compilationUnit.library.libraryCycleForLink;
+        try {
+          new TypeInferenceDependencyWalker().walk(_typeInferenceNode);
+          assert(_inferredType != null);
+        } finally {
+          Linker._initializerTypeInferenceCycle = null;
+        }
+      } else if (compilationUnit.isInBuildUnit) {
+        _inferredType = DynamicTypeImpl.instance;
+      } else {
+        _inferredType = compilationUnit.getLinkedType(
+            unlinkedVariable.inferredTypeSlot, _typeParameterContext);
+      }
+    }
+    return _inferredType;
+  }
+
   @override
   FunctionElementForLink_Initializer get initializer {
     if (unlinkedVariable.constExpr == null) {
@@ -3942,6 +4316,15 @@
   String get name => unlinkedVariable.name;
 
   @override
+  DartType get propagatedType {
+    // TODO(paulberry): implement propagated types in the linker.
+    return DynamicTypeImpl.instance;
+  }
+
+  @override
+  DartType get type => declaredType ?? inferredType;
+
+  @override
   void set type(DartType newType) {
     // TODO(paulberry): store inferred type.
   }
@@ -3958,9 +4341,29 @@
       DynamicTypeImpl.instance;
 
   ReferenceableElementForLink getContainedName(String name) {
-    return new NonstaticMemberElementForLink(_constNode);
+    Element element = _getContainedElement(name);
+    return new NonstaticMemberElementForLink(element, _constNode);
   }
 
   @override
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+
+  /**
+   * Return the contained element with the given [name], or `null` if the lookup
+   * fails.  Currently only static types are supported in the linker, so lookup
+   * is performed only in the strong mode.
+   */
+  Element _getContainedElement(String name) {
+    Linker linker = compilationUnit.library._linker;
+    if (linker.strongMode) {
+      DartType type = asStaticType;
+      if (type is InterfaceType) {
+        Element result = type.lookUpGetter(name, compilationUnit.library);
+        result ??= type.lookUpMethod(name, compilationUnit.library);
+        return result;
+      }
+    }
+    // TODO(scheglov): implement for propagated types
+    return null;
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 63a7f0f..23fecd5 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -1054,18 +1054,25 @@
   /**
    * Resynthesize an [ImportElement].
    */
-  ImportElement buildImport(_UnitResynthesizer definingUnitResynthesizer,
-      UnlinkedImport serializedImport, int dependency) {
+  ImportElement buildImport(
+      _UnitResynthesizer definingUnitResynthesizer,
+      UnlinkedImport serializedImport,
+      int dependency,
+      LibraryElement libraryBeingResynthesized) {
     bool isSynthetic = serializedImport.isImplicit;
     ImportElementImpl importElement =
         new ImportElementImpl(isSynthetic ? -1 : serializedImport.offset);
-    String absoluteUri = summaryResynthesizer.sourceFactory
-        .resolveUri(librarySource, linkedLibrary.dependencies[dependency].uri)
-        .uri
-        .toString();
-    importElement.importedLibrary = new LibraryElementHandle(
-        summaryResynthesizer,
-        new ElementLocationImpl.con3(<String>[absoluteUri]));
+    if (dependency == 0) {
+      importElement.importedLibrary = libraryBeingResynthesized;
+    } else {
+      String absoluteUri = summaryResynthesizer.sourceFactory
+          .resolveUri(librarySource, linkedLibrary.dependencies[dependency].uri)
+          .uri
+          .toString();
+      importElement.importedLibrary = new LibraryElementHandle(
+          summaryResynthesizer,
+          new ElementLocationImpl.con3(<String>[absoluteUri]));
+    }
     if (isSynthetic) {
       importElement.synthetic = true;
     } else {
@@ -1130,7 +1137,8 @@
       imports.add(buildImport(
           definingUnitResynthesizer,
           unlinkedDefiningUnit.imports[i],
-          linkedLibrary.importDependencies[i]));
+          linkedLibrary.importDependencies[i],
+          library));
     }
     library.imports = imports;
     // Create exports.
diff --git a/pkg/analyzer/lib/src/summary/summarize_elements.dart b/pkg/analyzer/lib/src/summary/summarize_elements.dart
index bb2a42e..353de09 100644
--- a/pkg/analyzer/lib/src/summary/summarize_elements.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_elements.dart
@@ -19,6 +19,7 @@
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/name_filter.dart';
 import 'package:analyzer/src/summary/summarize_const_expr.dart';
+import 'package:convert/convert.dart';
 import 'package:crypto/crypto.dart';
 import 'package:path/path.dart' as path;
 
@@ -136,7 +137,16 @@
   final List<LinkedLibraryBuilder> _linkedLibraries = <LinkedLibraryBuilder>[];
   final List<String> _unlinkedUnitUris = <String>[];
   final List<UnlinkedUnitBuilder> _unlinkedUnits = <UnlinkedUnitBuilder>[];
-  final List<String> _unlinkedUnitHashes = <String>[];
+  final List<String> _unlinkedUnitHashes;
+  final bool _excludeHashes;
+
+  /**
+   * Create a [PackageBundleAssembler].  If [excludeHashes] is `true`, hash
+   * computation will be skipped.
+   */
+  PackageBundleAssembler({bool excludeHashes: false})
+      : _excludeHashes = excludeHashes,
+        _unlinkedUnitHashes = excludeHashes ? null : <String>[];
 
   /**
    * Add a fallback library to the package bundle, corresponding to the library
@@ -167,13 +177,15 @@
   }
 
   void addUnlinkedUnit(Source source, UnlinkedUnitBuilder unit) {
-    addUnlinkedUnitWithHash(source.uri.toString(), unit, _hash(source.contents.data));
+    addUnlinkedUnitWithHash(source.uri.toString(), unit,
+        _excludeHashes ? null : _hash(source.contents.data));
   }
 
-  void addUnlinkedUnitWithHash(String uri, UnlinkedUnitBuilder unit, String hash) {
+  void addUnlinkedUnitWithHash(
+      String uri, UnlinkedUnitBuilder unit, String hash) {
     _unlinkedUnitUris.add(uri);
     _unlinkedUnits.add(unit);
-    _unlinkedUnitHashes.add(hash);
+    _unlinkedUnitHashes?.add(hash);
   }
 
   /**
@@ -204,7 +216,7 @@
     _unlinkedUnitUris.addAll(libraryResult.unitUris);
     _unlinkedUnits.addAll(libraryResult.unlinkedUnits);
     for (Source source in libraryResult.unitSources) {
-      _unlinkedUnitHashes.add(_hash(source.contents.data));
+      _unlinkedUnitHashes?.add(_hash(source.contents.data));
     }
   }
 
@@ -212,9 +224,7 @@
    * Compute a hash of the given file contents.
    */
   String _hash(String contents) {
-    MD5 md5 = new MD5();
-    md5.add(UTF8.encode(contents));
-    return CryptoUtils.bytesToHex(md5.close());
+    return hex.encode(md5.convert(UTF8.encode(contents)).bytes);
   }
 }
 
@@ -328,7 +338,7 @@
       new UnlinkedReferenceBuilder()
     ];
     linkedReferences = <LinkedReferenceBuilder>[
-      new LinkedReferenceBuilder(kind: ReferenceKind.classOrEnum)
+      new LinkedReferenceBuilder(kind: ReferenceKind.unresolved)
     ];
     List<UnlinkedPublicNameBuilder> names = <UnlinkedPublicNameBuilder>[];
     for (PropertyAccessorElement accessor in compilationUnit.accessors) {
@@ -1328,6 +1338,15 @@
         constructor = serializeConstructorName(
             new TypeName(annotation.name, null)..type = nameElement.type,
             annotation.constructorName);
+      } else if (nameElement == null) {
+        // Unresolved annotation.
+        if (name is PrefixedIdentifier && annotation.constructorName == null) {
+          constructor = serializeConstructorName(
+              new TypeName(name.prefix, null), name.identifier);
+        } else {
+          constructor = serializeConstructorName(
+              new TypeName(annotation.name, null), annotation.constructorName);
+        }
       } else {
         throw new StateError('Unexpected annotation nameElement type:'
             ' ${nameElement.runtimeType}');
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart
index 3faab08..f38ede3 100644
--- a/pkg/analyzer/lib/src/summary/summary_sdk.dart
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -14,7 +14,7 @@
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart'
-    show DartUriResolver, Source, SourceFactory, SourceKind;
+    show Source, SourceFactory, SourceKind;
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/resynthesize.dart';
 import 'package:analyzer/src/task/dart.dart';
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 3f80560..283bca3 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -16,6 +16,7 @@
 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/resolver/inheritance_manager.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/constant.dart';
@@ -616,6 +617,17 @@
     new ResultDescriptor<ReferencedNames>('REFERENCED_NAMES', null);
 
 /**
+ * The sources of the Dart files that a library references.
+ *
+ * The list is the union of [IMPORTED_LIBRARIES], [EXPORTED_LIBRARIES] and
+ * [UNITS] of the defining unit and [INCLUDED_PARTS]. Never empty or `null`.
+ *
+ * The result is only available for [Source]s representing a library.
+ */
+final ListResultDescriptor<Source> REFERENCED_SOURCES =
+    new ListResultDescriptor<Source>('REFERENCED_SOURCES', Source.EMPTY_LIST);
+
+/**
  * The errors produced while resolving type names.
  *
  * The list will be empty if there were no errors, but will not be `null`.
@@ -995,6 +1007,12 @@
   static const String UNIT_INPUT_NAME = 'UNIT_INPUT_NAME';
 
   /**
+   * The input with a map from referenced sources to their modification times.
+   */
+  static const String SOURCES_MODIFICATION_TIME_INPUT_NAME =
+      'SOURCES_MODIFICATION_TIME_INPUT_NAME';
+
+  /**
    * The input with a list of [LIBRARY_ELEMENT3]s of imported libraries.
    */
   static const String IMPORTS_LIBRARY_ELEMENT_INPUT_NAME =
@@ -1041,6 +1059,8 @@
     //
     LibraryElementImpl libraryElement = getRequiredInput(LIBRARY_INPUT);
     CompilationUnit libraryUnit = getRequiredInput(UNIT_INPUT_NAME);
+    Map<Source, int> sourceModificationTimeMap =
+        getRequiredInput(SOURCES_MODIFICATION_TIME_INPUT_NAME);
     Map<Source, LibraryElement> importLibraryMap =
         getRequiredInput(IMPORTS_LIBRARY_ELEMENT_INPUT_NAME);
     Map<Source, LibraryElement> exportLibraryMap =
@@ -1072,6 +1092,7 @@
       DirectiveElementBuilder builder = new DirectiveElementBuilder(
           context,
           libraryElement,
+          sourceModificationTimeMap,
           importLibraryMap,
           importSourceKindMap,
           exportLibraryMap,
@@ -1103,6 +1124,8 @@
       LIBRARY_INPUT: LIBRARY_ELEMENT1.of(source),
       UNIT_INPUT_NAME:
           RESOLVED_UNIT1.of(new LibrarySpecificUnit(source, source)),
+      SOURCES_MODIFICATION_TIME_INPUT_NAME:
+          REFERENCED_SOURCES.of(source).toMapOf(MODIFICATION_TIME),
       IMPORTS_LIBRARY_ELEMENT_INPUT_NAME:
           IMPORTED_LIBRARIES.of(source).toMapOf(LIBRARY_ELEMENT1),
       EXPORTS_LIBRARY_ELEMENT_INPUT_NAME:
@@ -1359,16 +1382,15 @@
         libraryNameNode = directive.name;
         directivesToResolve.add(directive);
       } else if (directive is PartDirective) {
-        PartDirective partDirective = directive;
-        StringLiteral partUri = partDirective.uri;
-        Source partSource = partDirective.source;
+        StringLiteral partUri = directive.uri;
+        Source partSource = directive.source;
         hasPartDirective = true;
         CompilationUnit partUnit = partUnitMap[partSource];
         if (partUnit != null) {
           CompilationUnitElementImpl partElement = partUnit.element;
           partElement.uriOffset = partUri.offset;
           partElement.uriEnd = partUri.end;
-          partElement.uri = partDirective.uriContent;
+          partElement.uri = directive.uriContent;
           //
           // Validate that the part contains a part-of directive with the same
           // name as the library.
@@ -2342,6 +2364,8 @@
  * of errors.
  */
 class DartErrorsTask extends SourceBasedAnalysisTask {
+  static final RegExp spacesRegExp = new RegExp(r'\s+');
+
   /**
    * The task descriptor describing this kind of task.
    */
@@ -2398,13 +2422,19 @@
     outputs[DART_ERRORS] = errors;
   }
 
+  Token _advanceToLine(Token token, LineInfo lineInfo, int line) {
+    int offset = lineInfo.getOffsetOfLine(line - 1); // 0-based
+    while (token.offset < offset) {
+      token = token.next;
+    }
+    return token;
+  }
+
   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);
 
@@ -2412,58 +2442,50 @@
     Token token = cu.beginToken;
     LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT);
 
-    int errorIndex = 0;
+    bool isIgnored(AnalysisError error) {
+      int errorLine = lineInfo.getLocation(error.offset).lineNumber;
+      token = _advanceToLine(token, lineInfo, errorLine);
 
-    // Step through tokens looking for comments.
-    while (errorIndex < errors.length && token.type != TokenType.EOF) {
-      // Find leading comment.
+      //Check for leading comment.
       Token comments = token.precedingComments;
       while (comments?.next != null) {
         comments = comments.next;
       }
+      if (_isIgnoredBy(error, comments)) {
+        return true;
+      }
 
-      // 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;
+      //Check for trailing comment.
+      int lineNumber = errorLine + 1;
+      if (lineNumber <= lineInfo.lineCount) {
+        Token nextLine = _advanceToLine(token, lineInfo, lineNumber);
+        comments = nextLine.precedingComments;
+        if (comments != null && nextLine.previous.type != TokenType.EOF) {
+          int commentLine = lineInfo.getLocation(comments.offset).lineNumber;
+          if (commentLine == errorLine) {
+            return _isIgnoredBy(error, comments);
           }
         }
       }
 
-      token = token.next;
+      return false;
     }
 
-    // Add remaining errors.
-    if (errorIndex < errors.length) {
-      filtered.addAll(errors.sublist(errorIndex));
-    }
-
-    return filtered;
+    return errors.where((AnalysisError e) => !isIgnored(e)).toList();
   }
 
-  bool _isIgnoredBy(AnalysisError error, String comment) => comment
-      .substring(_normalizedIgnorePrefix.length)
-      .split(',')
-      .contains(error.errorCode.name.toLowerCase());
+  bool _isIgnoredBy(AnalysisError error, Token comment) {
+    //Normalize first.
+    String contents =
+        comment?.lexeme?.toLowerCase()?.replaceAll(spacesRegExp, '');
+    if (contents == null || !contents.startsWith(_normalizedIgnorePrefix)) {
+      return false;
+    }
+    return contents
+        .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
@@ -3474,7 +3496,8 @@
     PARSE_ERRORS,
     PARSED_UNIT,
     SOURCE_KIND,
-    UNITS
+    UNITS,
+    REFERENCED_SOURCES
   ]);
 
   /**
@@ -3500,7 +3523,6 @@
     parser.parseAsync = options.enableAsync;
     parser.parseFunctionBodies = options.analyzeFunctionBodiesPredicate(source);
     parser.parseGenericMethods = options.enableGenericMethods;
-    parser.parseConditionalDirectives = options.enableConditionalDirectives;
     parser.parseGenericMethodComments = options.strongMode;
     CompilationUnit unit = parser.parseCompilationUnit(tokenStream);
     unit.lineInfo = lineInfo;
@@ -3569,6 +3591,11 @@
     List<Source> includedSources = includedSourceSet.toList();
     List<AnalysisError> parseErrors = getUniqueErrors(errorListener.errors);
     List<Source> unitSources = <Source>[source]..addAll(includedSourceSet);
+    List<Source> referencedSources = (new Set<Source>()
+          ..addAll(importedSources)
+          ..addAll(exportedSources)
+          ..addAll(unitSources))
+        .toList();
     List<LibrarySpecificUnit> librarySpecificUnits =
         unitSources.map((s) => new LibrarySpecificUnit(source, s)).toList();
     outputs[EXPLICITLY_IMPORTED_LIBRARIES] = explicitlyImportedSources;
@@ -3580,6 +3607,7 @@
     outputs[PARSED_UNIT] = unit;
     outputs[SOURCE_KIND] = sourceKind;
     outputs[UNITS] = unitSources;
+    outputs[REFERENCED_SOURCES] = referencedSources;
   }
 
   /**
@@ -4489,20 +4517,12 @@
       //
       // Resolve references.
       //
-      // TODO(leafp): This code only needs to re-resolve the right hand sides of
-      // instance fields.  We could do incremental resolution on each field
-      // only using the incremental resolver.  However, this caused a massive
-      // performance degredation on the large_class_declaration_test.dart test.
-      // I would hypothesize that incremental resolution of field is linear in
-      // the size of the enclosing class, and hence incrementally resolving each
-      // field was quadratic.  We may wish to revisit this if we can resolve
-      // this performance issue.
-      PartialResolverVisitor visitor = new PartialResolverVisitor(
+      InstanceFieldResolverVisitor visitor = new InstanceFieldResolverVisitor(
           libraryElement,
           unitElement.source,
           typeProvider,
           AnalysisErrorListener.NULL_LISTENER);
-      unit.accept(visitor);
+      visitor.resolveCompilationUnit(unit);
     }
     //
     // Record outputs.
@@ -5062,6 +5082,11 @@
   static const String CONTENT_INPUT_NAME = 'CONTENT_INPUT_NAME';
 
   /**
+   * The name of the input whose value is the modification time of the file.
+   */
+  static const String MODIFICATION_TIME_INPUT = 'MODIFICATION_TIME_INPUT';
+
+  /**
    * The task descriptor describing this kind of task.
    */
   static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
@@ -5084,9 +5109,10 @@
   @override
   void internalPerform() {
     Source source = getRequiredSource();
-
     RecordingErrorListener errorListener = new RecordingErrorListener();
-    if (context.getModificationStamp(target.source) < 0) {
+
+    int modificationTime = getRequiredInput(MODIFICATION_TIME_INPUT);
+    if (modificationTime < 0) {
       String message = 'Content could not be read';
       if (context is InternalAnalysisContext) {
         CacheEntry entry =
@@ -5143,16 +5169,23 @@
   /**
    * 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
-   * [source].
+   * [target].
    */
   static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
     if (target is Source) {
-      return <String, TaskInput>{CONTENT_INPUT_NAME: CONTENT.of(target)};
+      return <String, TaskInput>{
+        CONTENT_INPUT_NAME: CONTENT.of(target),
+        MODIFICATION_TIME_INPUT: MODIFICATION_TIME.of(target)
+      };
     } else if (target is DartScript) {
       // This task does not use the following input; it is included only to add
       // a dependency between this value and the containing source so that when
       // the containing source is modified these results will be invalidated.
-      return <String, TaskInput>{'-': DART_SCRIPTS.of(target.source)};
+      Source source = target.source;
+      return <String, TaskInput>{
+        '-': DART_SCRIPTS.of(source),
+        MODIFICATION_TIME_INPUT: MODIFICATION_TIME.of(source)
+      };
     }
     throw new AnalysisException(
         'Cannot build inputs for a ${target.runtimeType}');
@@ -5269,6 +5302,13 @@
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
   /**
+   * The name of the input of a mapping from [REFERENCED_SOURCES] to their
+   * [MODIFICATION_TIME]s.
+   */
+  static const String REFERENCED_SOURCE_MODIFICATION_TIME_MAP_INPUT =
+      'REFERENCED_SOURCE_MODIFICATION_TIME_MAP_INPUT';
+
+  /**
    * The name of the [TYPE_PROVIDER] input.
    */
   static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
@@ -5284,6 +5324,12 @@
    */
   ErrorReporter errorReporter;
 
+  /**
+   * The mapping from the current library referenced sources to their
+   * modification times.
+   */
+  Map<Source, int> sourceTimeMap;
+
   VerifyUnitTask(InternalAnalysisContext context, AnalysisTarget target)
       : super(context, target);
 
@@ -5300,6 +5346,8 @@
     //
     TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
     CompilationUnit unit = getRequiredInput(UNIT_INPUT);
+    sourceTimeMap =
+        getRequiredInput(REFERENCED_SOURCE_MODIFICATION_TIME_MAP_INPUT);
     CompilationUnitElement unitElement = unit.element;
     LibraryElement libraryElement = unitElement.library;
     if (libraryElement == null) {
@@ -5354,7 +5402,8 @@
   void validateReferencedSource(UriBasedDirective directive) {
     Source source = directive.source;
     if (source != null) {
-      if (context.exists(source)) {
+      int modificationTime = sourceTimeMap[source] ?? -1;
+      if (modificationTime >= 0) {
         return;
       }
     } else {
@@ -5378,6 +5427,8 @@
     return <String, TaskInput>{
       'thisLibraryClosureIsReady': READY_RESOLVED_UNIT.of(unit.library),
       UNIT_INPUT: RESOLVED_UNIT.of(unit),
+      REFERENCED_SOURCE_MODIFICATION_TIME_MAP_INPUT:
+          REFERENCED_SOURCES.of(unit.library).toMapOf(MODIFICATION_TIME),
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
     };
   }
diff --git a/pkg/analyzer/lib/src/task/dart_work_manager.dart b/pkg/analyzer/lib/src/task/dart_work_manager.dart
index 4a81c18..0eb6613 100644
--- a/pkg/analyzer/lib/src/task/dart_work_manager.dart
+++ b/pkg/analyzer/lib/src/task/dart_work_manager.dart
@@ -8,13 +8,7 @@
 
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/generated/engine.dart'
-    show
-        AnalysisEngine,
-        AnalysisErrorInfo,
-        AnalysisErrorInfoImpl,
-        AnalysisOptions,
-        CacheState,
-        InternalAnalysisContext;
+    show AnalysisEngine, AnalysisErrorInfo, CacheState, InternalAnalysisContext;
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_collection.dart';
diff --git a/pkg/analyzer/lib/src/task/driver.dart b/pkg/analyzer/lib/src/task/driver.dart
index c41c41a..b0cabae 100644
--- a/pkg/analyzer/lib/src/task/driver.dart
+++ b/pkg/analyzer/lib/src/task/driver.dart
@@ -608,7 +608,7 @@
   /**
    * The inputs to the task that have been computed.
    */
-  Map<String, dynamic> inputs;
+  Map<String, dynamic> inputs = const <String, dynamic>{};
 
   /**
    * The exception that was found while trying to populate the inputs. If this
@@ -643,7 +643,6 @@
     if (!builder.moveNext()) {
       builder = null;
     }
-    inputs = new HashMap<String, dynamic>();
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/task/html.dart b/pkg/analyzer/lib/src/task/html.dart
index 2575677..93e00ed 100644
--- a/pkg/analyzer/lib/src/task/html.dart
+++ b/pkg/analyzer/lib/src/task/html.dart
@@ -269,6 +269,11 @@
   static const String CONTENT_INPUT_NAME = 'CONTENT_INPUT_NAME';
 
   /**
+   * The name of the input whose value is the modification time of the file.
+   */
+  static const String MODIFICATION_TIME_INPUT = 'MODIFICATION_TIME_INPUT';
+
+  /**
    * The task descriptor describing this kind of task.
    */
   static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
@@ -292,7 +297,8 @@
   void internalPerform() {
     String content = getRequiredInput(CONTENT_INPUT_NAME);
 
-    if (context.getModificationStamp(target.source) < 0) {
+    int modificationTime = getRequiredInput(MODIFICATION_TIME_INPUT);
+    if (modificationTime < 0) {
       String message = 'Content could not be read';
       if (context is InternalAnalysisContext) {
         CacheEntry entry =
@@ -343,7 +349,10 @@
    * [source].
    */
   static Map<String, TaskInput> buildInputs(AnalysisTarget source) {
-    return <String, TaskInput>{CONTENT_INPUT_NAME: CONTENT.of(source)};
+    return <String, TaskInput>{
+      CONTENT_INPUT_NAME: CONTENT.of(source),
+      MODIFICATION_TIME_INPUT: MODIFICATION_TIME.of(source)
+    };
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/task/html_work_manager.dart b/pkg/analyzer/lib/src/task/html_work_manager.dart
index b0e52bb..07dfb29 100644
--- a/pkg/analyzer/lib/src/task/html_work_manager.dart
+++ b/pkg/analyzer/lib/src/task/html_work_manager.dart
@@ -8,13 +8,7 @@
 
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/generated/engine.dart'
-    show
-        AnalysisEngine,
-        AnalysisErrorInfo,
-        AnalysisErrorInfoImpl,
-        AnalysisOptions,
-        CacheState,
-        InternalAnalysisContext;
+    show AnalysisEngine, AnalysisErrorInfo, CacheState, InternalAnalysisContext;
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_collection.dart';
diff --git a/pkg/analyzer/lib/src/task/incremental_element_builder.dart b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
index b3b3512..d7156e4 100644
--- a/pkg/analyzer/lib/src/task/incremental_element_builder.dart
+++ b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
@@ -303,7 +303,7 @@
   static Token getBeginTokenNotComment(AstNode node) {
     Token oldBeginToken = node.beginToken;
     if (oldBeginToken is CommentToken) {
-      oldBeginToken = (oldBeginToken as CommentToken).parent;
+      return oldBeginToken.parent;
     }
     return oldBeginToken;
   }
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index d3cc82f..47acf37 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -48,6 +48,8 @@
   static const String enableGenericMethods = 'enableGenericMethods';
   static const String enableStrictCallChecks = 'enableStrictCallChecks';
   static const String enableSuperMixins = 'enableSuperMixins';
+
+  /// This option is deprecated.
   static const String enableConditionalDirectives =
       "enableConditionalDirectives";
   static const String errors = 'errors';
@@ -496,14 +498,6 @@
         context.analysisOptions = options;
       }
     }
-    if (feature == AnalyzerOptions.enableConditionalDirectives) {
-      if (isTrue(value)) {
-        AnalysisOptionsImpl options =
-            new AnalysisOptionsImpl.from(context.analysisOptions);
-        options.enableConditionalDirectives = true;
-        context.analysisOptions = options;
-      }
-    }
   }
 
   void setLanguageOptions(AnalysisContext context, Object configs) {
diff --git a/pkg/analyzer/lib/src/task/options_work_manager.dart b/pkg/analyzer/lib/src/task/options_work_manager.dart
index bade2fc..2074eb0 100644
--- a/pkg/analyzer/lib/src/task/options_work_manager.dart
+++ b/pkg/analyzer/lib/src/task/options_work_manager.dart
@@ -8,13 +8,7 @@
 
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/generated/engine.dart'
-    show
-        AnalysisEngine,
-        AnalysisErrorInfo,
-        AnalysisErrorInfoImpl,
-        AnalysisOptions,
-        CacheState,
-        InternalAnalysisContext;
+    show AnalysisEngine, AnalysisErrorInfo, CacheState, InternalAnalysisContext;
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/options.dart';
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index eaa8599..08d414b 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -8,11 +8,10 @@
 
 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/token.dart' show 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/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
 import 'package:analyzer/src/generated/type_system.dart';
@@ -118,10 +117,8 @@
   void checkArgument(Expression arg, DartType expectedType) {
     // Preserve named argument structure, so their immediate parent is the
     // method invocation.
-    if (arg is NamedExpression) {
-      arg = (arg as NamedExpression).expression;
-    }
-    checkAssignment(arg, expectedType);
+    Expression baseExpression = arg is NamedExpression ? arg.expression : arg;
+    checkAssignment(baseExpression, expectedType);
   }
 
   void checkArgumentList(ArgumentList node, FunctionType type) {
@@ -428,16 +425,22 @@
 
   @override
   void visitListLiteral(ListLiteral node) {
-    var type = DynamicTypeImpl.instance;
+    DartType type = DynamicTypeImpl.instance;
     if (node.typeArguments != null) {
-      var targs = node.typeArguments.arguments;
-      if (targs.length > 0) type = targs[0].type;
-    } else if (node.staticType is InterfaceType) {
-      InterfaceType listT = node.staticType;
-      var targs = listT.typeArguments;
-      if (targs != null && targs.length > 0) type = targs[0];
+      NodeList<TypeName> targs = node.typeArguments.arguments;
+      if (targs.length > 0) {
+        type = targs[0].type;
+      }
+    } else {
+      DartType staticType = node.staticType;
+      if (staticType is InterfaceType) {
+        List<DartType> targs = staticType.typeArguments;
+        if (targs != null && targs.length > 0) {
+          type = targs[0];
+        }
+      }
     }
-    var elements = node.elements;
+    NodeList<Expression> elements = node.elements;
     for (int i = 0; i < elements.length; i++) {
       checkArgument(elements[i], type);
     }
@@ -446,23 +449,33 @@
 
   @override
   void visitMapLiteral(MapLiteral node) {
-    var ktype = DynamicTypeImpl.instance;
-    var vtype = DynamicTypeImpl.instance;
+    DartType ktype = DynamicTypeImpl.instance;
+    DartType vtype = DynamicTypeImpl.instance;
     if (node.typeArguments != null) {
-      var targs = node.typeArguments.arguments;
-      if (targs.length > 0) ktype = targs[0].type;
-      if (targs.length > 1) vtype = targs[1].type;
-    } else if (node.staticType is InterfaceType) {
-      InterfaceType mapT = node.staticType;
-      var targs = mapT.typeArguments;
-      if (targs != null) {
-        if (targs.length > 0) ktype = targs[0];
-        if (targs.length > 1) vtype = targs[1];
+      NodeList<TypeName> targs = node.typeArguments.arguments;
+      if (targs.length > 0) {
+        ktype = targs[0].type;
+      }
+      if (targs.length > 1) {
+        vtype = targs[1].type;
+      }
+    } else {
+      DartType staticType = node.staticType;
+      if (staticType is InterfaceType) {
+        List<DartType> targs = staticType.typeArguments;
+        if (targs != null) {
+          if (targs.length > 0) {
+            ktype = targs[0];
+          }
+          if (targs.length > 1) {
+            vtype = targs[1];
+          }
+        }
       }
     }
-    var entries = node.entries;
+    NodeList<MapLiteralEntry> entries = node.entries;
     for (int i = 0; i < entries.length; i++) {
-      var entry = entries[i];
+      MapLiteralEntry entry = entries[i];
       checkArgument(entry.key, ktype);
       checkArgument(entry.value, vtype);
     }
@@ -800,7 +813,7 @@
 
     // Remove fuzzy arrow if possible.
     if (t is FunctionType && StaticInfo.isKnownFunction(expr)) {
-      t = _removeFuzz(t);
+      t = rules.functionTypeToConcreteType(typeProvider, t);
     }
 
     return t;
@@ -821,7 +834,9 @@
     if (t is InterfaceType) {
       return rules.getCallMethodType(t);
     }
-    if (t is FunctionType) return t;
+    if (t is FunctionType) {
+      return t;
+    }
     return null;
   }
 
@@ -908,55 +923,6 @@
     }
   }
 
-  /// Remove "fuzzy arrow" in this function type.
-  ///
-  /// Normally we treat dynamically typed parameters as bottom for function
-  /// types. This allows type tests such as `if (f is SingleArgFunction)`.
-  /// It also requires a dynamic check on the parameter type to call these
-  /// functions.
-  ///
-  /// When we convert to a strict arrow, dynamically typed parameters become
-  /// top. This is safe to do for known functions, like top-level or local
-  /// functions and static methods. Those functions must already be essentially
-  /// treating dynamic as top.
-  ///
-  /// Only the outer-most arrow can be strict. Any others must be fuzzy, because
-  /// we don't know what function value will be passed there.
-  // TODO(jmesserly): should we use a real "fuzzyArrow" bit on the function
-  // type? That would allow us to implement this in the subtype relation.
-  // TODO(jmesserly): we'll need to factor this differently if we want to
-  // move CodeChecker's functionality into existing analyzer. Likely we can
-  // let the Expression have a strict arrow, then in places were we do
-  // inference, convert back to a fuzzy arrow.
-  FunctionType _removeFuzz(FunctionType t) {
-    bool foundFuzz = false;
-    List<ParameterElement> parameters = <ParameterElement>[];
-    for (ParameterElement p in t.parameters) {
-      ParameterElement newP = _removeParameterFuzz(p);
-      parameters.add(newP);
-      if (p != newP) foundFuzz = true;
-    }
-    if (!foundFuzz) {
-      return t;
-    }
-
-    FunctionElementImpl function = new FunctionElementImpl("", -1);
-    function.synthetic = true;
-    function.returnType = t.returnType;
-    function.shareTypeParameters(t.typeFormals);
-    function.shareParameters(parameters);
-    return function.type = new FunctionTypeImpl(function);
-  }
-
-  /// Removes fuzzy arrow, see [_removeFuzz].
-  ParameterElement _removeParameterFuzz(ParameterElement p) {
-    if (p.type.isDynamic) {
-      return new ParameterElementImpl.synthetic(
-          p.name, typeProvider.objectType, p.parameterKind);
-    }
-    return p;
-  }
-
   DartType _specializedBinaryReturnType(
       TokenType op, DartType t1, DartType t2, DartType normalReturnType) {
     // This special cases binary return types as per 16.26 and 16.27 of the
@@ -1061,11 +1027,15 @@
       InterfaceType baseType, Set<String> seen, bool isSubclass) {
     for (var member in node.members) {
       if (member is FieldDeclaration) {
-        if (member.isStatic) continue;
+        if (member.isStatic) {
+          continue;
+        }
         for (var variable in member.fields.variables) {
           var element = variable.element as PropertyInducingElement;
           var name = element.name;
-          if (seen.contains(name)) continue;
+          if (seen.contains(name)) {
+            continue;
+          }
           var getter = element.getter;
           var setter = element.setter;
           bool found = _checkSingleOverride(
@@ -1076,12 +1046,18 @@
                   setter, baseType, variable.name, member, isSubclass)) {
             found = true;
           }
-          if (found) seen.add(name);
+          if (found) {
+            seen.add(name);
+          }
         }
       } else if (member is MethodDeclaration) {
-        if (member.isStatic) continue;
+        if (member.isStatic) {
+          continue;
+        }
         var method = member.element;
-        if (seen.contains(method.name)) continue;
+        if (seen.contains(method.name)) {
+          continue;
+        }
         if (_checkSingleOverride(
             method, baseType, member.name, member, isSubclass)) {
           seen.add(method.name);
diff --git a/pkg/analyzer/lib/src/task/strong_mode.dart b/pkg/analyzer/lib/src/task/strong_mode.dart
index 233e5c4..70d31aa 100644
--- a/pkg/analyzer/lib/src/task/strong_mode.dart
+++ b/pkg/analyzer/lib/src/task/strong_mode.dart
@@ -12,6 +12,7 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/inheritance_manager.dart';
 import 'package:analyzer/src/generated/resolver.dart'
     show TypeProvider, InheritanceManager;
 import 'package:analyzer/src/generated/type_system.dart';
@@ -468,10 +469,13 @@
   @override
   void visitSimpleIdentifier(SimpleIdentifier node) {
     if (!node.inDeclarationContext()) {
-      Element element = node.staticElement;
-      if (element is PropertyAccessorElement && element.isSynthetic) {
-        element = (element as PropertyAccessorElement).variable;
+      Element nonAccessor(Element element) {
+        if (element is PropertyAccessorElement && element.isSynthetic) {
+          return element.variable;
+        }
+        return element;
       }
+      Element element = nonAccessor(node.staticElement);
       if (element is VariableElement && (filter == null || filter(element))) {
         results.add(element);
       }
diff --git a/pkg/analyzer/lib/src/task/yaml.dart b/pkg/analyzer/lib/src/task/yaml.dart
index e83fa8c..2d94165 100644
--- a/pkg/analyzer/lib/src/task/yaml.dart
+++ b/pkg/analyzer/lib/src/task/yaml.dart
@@ -6,7 +6,7 @@
 
 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/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
diff --git a/pkg/analyzer/lib/task/model.dart b/pkg/analyzer/lib/task/model.dart
index be60b78..557a763 100644
--- a/pkg/analyzer/lib/task/model.dart
+++ b/pkg/analyzer/lib/task/model.dart
@@ -7,7 +7,7 @@
 import 'dart:collection';
 import 'dart:developer';
 
-import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask;
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart' show AnalysisError;
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -185,11 +185,11 @@
    * Return the value of the input with the given [name]. Throw an exception if
    * the input value is not defined.
    */
-  Object getRequiredInput(String name) {
+  Object/*=E*/ getRequiredInput/*<E>*/(String name) {
     if (inputs == null || !inputs.containsKey(name)) {
       throw new AnalysisException("Could not $description: missing $name");
     }
-    return inputs[name];
+    return inputs[name] as Object/*=E*/;
   }
 
   /**
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 4b0b2ad..6c8b8cc 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.27.3-alpha.7
+version: 0.27.3
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
@@ -7,7 +7,7 @@
   sdk: '>=1.12.0 <2.0.0'
 dependencies:
   args: '>=0.12.1 <0.14.0'
-  crypto: ^0.9.0
+  crypto: '>=0.9.2 <2.0.0'
   glob: ^1.0.3
   html: ^0.12.0
   package_config: ^0.1.1
diff --git a/pkg/analyzer/test/generated/error_suppression_test.dart b/pkg/analyzer/test/generated/error_suppression_test.dart
index c77bb3d..275e94c 100644
--- a/pkg/analyzer/test/generated/error_suppression_test.dart
+++ b/pkg/analyzer/test/generated/error_suppression_test.dart
@@ -42,6 +42,25 @@
         [CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE]);
   }
 
+  void test_ignore_first_trailing() {
+    Source source = addSource('''
+int x = ''; // ignore: invalid_assignment
+// ... 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_only_trailing() {
+    Source source = addSource('''
+int x = ''; // ignore: invalid_assignment
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, []);
+  }
+
   void test_ignore_second() {
     Source source = addSource('''
 //INVALID_ASSIGNMENT
@@ -53,6 +72,16 @@
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
   }
 
+  void test_ignore_second_trailing() {
+    Source source = addSource('''
+//INVALID_ASSIGNMENT
+int x = '';
+const y = x; // ignore: 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
@@ -108,6 +137,15 @@
     assertErrors(source, []);
   }
 
+  void test_multiple_ignores_traling() {
+    Source source = addSource('''
+int x = 3;
+const String y = x; // ignore: 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;
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 168c471..79cb436 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -1605,7 +1605,7 @@
 }
 ''');
     computeLibrarySourceErrors(source);
-    assertErrors(source, [HintCode.MISSING_REQUIRED_PARAM]);
+    assertErrors(source, [HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS]);
     verify([source]);
   }
 
@@ -1671,7 +1671,7 @@
 }
 ''');
     computeLibrarySourceErrors(source);
-    assertErrors(source, [HintCode.MISSING_REQUIRED_PARAM]);
+    assertErrors(source, [HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS]);
     verify([source]);
   }
 
@@ -1686,7 +1686,7 @@
 }
 ''');
     computeLibrarySourceErrors(source);
-    assertErrors(source, [HintCode.MISSING_REQUIRED_PARAM]);
+    assertErrors(source, [HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS]);
     verify([source]);
   }
 
@@ -1710,6 +1710,50 @@
     verify([source]);
   }
 
+  void test_undefinedIdentifier_importHide() {
+    Source source = addSource(r'''
+library L;
+import 'lib1.dart' hide a;''');
+    addNamedSource("/lib1.dart", "library lib1;");
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source,
+        [HintCode.UNUSED_IMPORT, HintCode.UNDEFINED_HIDDEN_NAME]);
+    verify([source]);
+  }
+
+  void test_undefinedIdentifier_importShow() {
+    Source source = addSource(r'''
+library L;
+import 'lib1.dart' show a;''');
+    addNamedSource("/lib1.dart", "library lib1;");
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source,
+        [HintCode.UNUSED_IMPORT, HintCode.UNDEFINED_SHOWN_NAME]);
+    verify([source]);
+  }
+
+  void test_undefinedIdentifier_exportHide() {
+    Source source = addSource(r'''
+library L;
+export 'lib1.dart' hide a;''');
+    addNamedSource("/lib1.dart", "library lib1;");
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [HintCode.UNDEFINED_HIDDEN_NAME]);
+    verify([source]);
+  }
+
+  void test_undefinedIdentifier_exportShow() {
+    Source source = addSource(r'''
+library L;
+export 'lib1.dart' show a;''');
+    addNamedSource("/lib1.dart", "library lib1;");
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [HintCode.UNDEFINED_SHOWN_NAME]);
+    verify([source]);
+  }
+
   void test_undefinedGetter() {
     Source source = addSource(r'''
 class A {}
@@ -2909,7 +2953,8 @@
 import 'lib1.dart' show A, B;
 A a;''');
     Source source2 = addNamedSource(
-        "/lib1.dart", r'''
+        "/lib1.dart",
+        r'''
 library lib1;
 class A {}
 class B {}''');
@@ -2947,7 +2992,8 @@
 import 'lib1.dart' as p show A, B;
 p.A a;''');
     Source source2 = addNamedSource(
-        "/lib1.dart", r'''
+        "/lib1.dart",
+        r'''
 library lib1;
 class A {}
 class B {}''');
@@ -2965,16 +3011,16 @@
 A a;
 C c;''');
     Source source2 = addNamedSource(
-        "/lib1.dart", r'''
+        "/lib1.dart",
+        r'''
 library lib1;
 class A {}
 class B {}
 class C {}
 class D {}''');
     computeLibrarySourceErrors(source);
-    assertErrors(source, [
-        HintCode.UNUSED_SHOWN_NAME,
-        HintCode.UNUSED_SHOWN_NAME]);
+    assertErrors(
+        source, [HintCode.UNUSED_SHOWN_NAME, HintCode.UNUSED_SHOWN_NAME]);
     assertNoErrors(source2);
     verify([source, source2]);
   }
diff --git a/pkg/analyzer/test/generated/inheritance_manager_test.dart b/pkg/analyzer/test/generated/inheritance_manager_test.dart
index e41df2f..e4f8395 100644
--- a/pkg/analyzer/test/generated/inheritance_manager_test.dart
+++ b/pkg/analyzer/test/generated/inheritance_manager_test.dart
@@ -9,6 +9,7 @@
 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/resolver/inheritance_manager.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_engine_io.dart';
@@ -69,13 +70,13 @@
         ElementFactory.getterElement(getterName, false, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[getterG];
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    MemberMap mapB =
-        _inheritanceManager.getMapOfMembersInheritedFromClasses(classB);
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromClasses(classA);
-    expect(mapA.size, _numOfMembersInObject);
-    expect(mapB.size, _numOfMembersInObject + 1);
-    expect(mapB.get(getterName), same(getterG));
+    Map<String, ExecutableElement> mapB =
+        _inheritanceManager.getMembersInheritedFromClasses(classB);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromClasses(classA);
+    expect(mapA.length, _numOfMembersInObject);
+    expect(mapB.length, _numOfMembersInObject + 1);
+    expect(mapB[getterName], same(getterG));
     _assertNoErrors(classA);
     _assertNoErrors(classB);
   }
@@ -90,13 +91,13 @@
     classA.accessors = <PropertyAccessorElement>[getterG];
     ClassElementImpl classB = ElementFactory.classElement2("B");
     classB.interfaces = <InterfaceType>[classA.type];
-    MemberMap mapB =
-        _inheritanceManager.getMapOfMembersInheritedFromClasses(classB);
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromClasses(classA);
-    expect(mapA.size, _numOfMembersInObject);
-    expect(mapB.size, _numOfMembersInObject);
-    expect(mapB.get(getterName), isNull);
+    Map<String, ExecutableElement> mapB =
+        _inheritanceManager.getMembersInheritedFromClasses(classB);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromClasses(classA);
+    expect(mapA.length, _numOfMembersInObject);
+    expect(mapB.length, _numOfMembersInObject);
+    expect(mapB[getterName], isNull);
     _assertNoErrors(classA);
     _assertNoErrors(classB);
   }
@@ -111,13 +112,13 @@
     classA.accessors = <PropertyAccessorElement>[getterG];
     ClassElementImpl classB = ElementFactory.classElement2("B");
     classB.mixins = <InterfaceType>[classA.type];
-    MemberMap mapB =
-        _inheritanceManager.getMapOfMembersInheritedFromClasses(classB);
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromClasses(classA);
-    expect(mapA.size, _numOfMembersInObject);
-    expect(mapB.size, _numOfMembersInObject + 1);
-    expect(mapB.get(getterName), same(getterG));
+    Map<String, ExecutableElement> mapB =
+        _inheritanceManager.getMembersInheritedFromClasses(classB);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromClasses(classA);
+    expect(mapA.length, _numOfMembersInObject);
+    expect(mapB.length, _numOfMembersInObject + 1);
+    expect(mapB[getterName], same(getterG));
     _assertNoErrors(classA);
     _assertNoErrors(classB);
   }
@@ -125,9 +126,9 @@
   void test_getMapOfMembersInheritedFromClasses_implicitExtends() {
     // class A {}
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromClasses(classA);
-    expect(mapA.size, _numOfMembersInObject);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromClasses(classA);
+    expect(mapA.length, _numOfMembersInObject);
     _assertNoErrors(classA);
   }
 
@@ -141,13 +142,13 @@
     classA.methods = <MethodElement>[methodM];
     ClassElementImpl classB = ElementFactory.classElement2("B");
     classB.supertype = classA.type;
-    MemberMap mapB =
-        _inheritanceManager.getMapOfMembersInheritedFromClasses(classB);
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromClasses(classA);
-    expect(mapA.size, _numOfMembersInObject);
-    expect(mapB.size, _numOfMembersInObject + 1);
-    expect(mapB.get(methodName), same(methodM));
+    Map<String, ExecutableElement> mapB =
+        _inheritanceManager.getMembersInheritedFromClasses(classB);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromClasses(classA);
+    expect(mapA.length, _numOfMembersInObject);
+    expect(mapB.length, _numOfMembersInObject + 1);
+    expect(mapB[methodName], same(methodM));
     _assertNoErrors(classA);
     _assertNoErrors(classB);
   }
@@ -162,13 +163,13 @@
     classA.methods = <MethodElement>[methodM];
     ClassElementImpl classB = ElementFactory.classElement2("B");
     classB.interfaces = <InterfaceType>[classA.type];
-    MemberMap mapB =
-        _inheritanceManager.getMapOfMembersInheritedFromClasses(classB);
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromClasses(classA);
-    expect(mapA.size, _numOfMembersInObject);
-    expect(mapB.size, _numOfMembersInObject);
-    expect(mapB.get(methodName), isNull);
+    Map<String, ExecutableElement> mapB =
+        _inheritanceManager.getMembersInheritedFromClasses(classB);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromClasses(classA);
+    expect(mapA.length, _numOfMembersInObject);
+    expect(mapB.length, _numOfMembersInObject);
+    expect(mapB[methodName], isNull);
     _assertNoErrors(classA);
     _assertNoErrors(classB);
   }
@@ -183,13 +184,13 @@
     classA.methods = <MethodElement>[methodM];
     ClassElementImpl classB = ElementFactory.classElement2("B");
     classB.mixins = <InterfaceType>[classA.type];
-    MemberMap mapB =
-        _inheritanceManager.getMapOfMembersInheritedFromClasses(classB);
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromClasses(classA);
-    expect(mapA.size, _numOfMembersInObject);
-    expect(mapB.size, _numOfMembersInObject + 1);
-    expect(mapB.get(methodName), same(methodM));
+    Map<String, ExecutableElement> mapB =
+        _inheritanceManager.getMembersInheritedFromClasses(classB);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromClasses(classA);
+    expect(mapA.length, _numOfMembersInObject);
+    expect(mapB.length, _numOfMembersInObject + 1);
+    expect(mapB[methodName], same(methodM));
     _assertNoErrors(classA);
     _assertNoErrors(classB);
   }
@@ -209,9 +210,9 @@
     classA2.methods = <MethodElement>[methodA2M];
     ClassElementImpl classB = ElementFactory.classElement2("B");
     classB.mixins = <InterfaceType>[classA1.type, classA2.type];
-    MemberMap mapB =
-        _inheritanceManager.getMapOfMembersInheritedFromClasses(classB);
-    expect(mapB.get(methodName), same(methodA2M));
+    Map<String, ExecutableElement> mapB =
+        _inheritanceManager.getMembersInheritedFromClasses(classB);
+    expect(mapB[methodName], same(methodA2M));
     _assertNoErrors(classA1);
     _assertNoErrors(classA2);
     _assertNoErrors(classB);
@@ -226,13 +227,13 @@
         ElementFactory.getterElement(getterName, false, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[getterG];
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    MemberMap mapB =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB);
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject);
-    expect(mapB.size, _numOfMembersInObject + 1);
-    expect(mapB.get(getterName), same(getterG));
+    Map<String, ExecutableElement> mapB =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classB);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject);
+    expect(mapB.length, _numOfMembersInObject + 1);
+    expect(mapB[getterName], same(getterG));
     _assertNoErrors(classA);
     _assertNoErrors(classB);
   }
@@ -247,13 +248,13 @@
     classA.accessors = <PropertyAccessorElement>[getterG];
     ClassElementImpl classB = ElementFactory.classElement2("B");
     classB.interfaces = <InterfaceType>[classA.type];
-    MemberMap mapB =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB);
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject);
-    expect(mapB.size, _numOfMembersInObject + 1);
-    expect(mapB.get(getterName), same(getterG));
+    Map<String, ExecutableElement> mapB =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classB);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject);
+    expect(mapB.length, _numOfMembersInObject + 1);
+    expect(mapB[getterName], same(getterG));
     _assertNoErrors(classA);
     _assertNoErrors(classB);
   }
@@ -268,13 +269,13 @@
     classA.accessors = <PropertyAccessorElement>[getterG];
     ClassElementImpl classB = ElementFactory.classElement2("B");
     classB.mixins = <InterfaceType>[classA.type];
-    MemberMap mapB =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB);
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject);
-    expect(mapB.size, _numOfMembersInObject + 1);
-    expect(mapB.get(getterName), same(getterG));
+    Map<String, ExecutableElement> mapB =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classB);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject);
+    expect(mapB.length, _numOfMembersInObject + 1);
+    expect(mapB[getterName], same(getterG));
     _assertNoErrors(classA);
     _assertNoErrors(classB);
   }
@@ -282,9 +283,9 @@
   void test_getMapOfMembersInheritedFromInterfaces_implicitExtends() {
     // class A {}
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject);
     _assertNoErrors(classA);
   }
 
@@ -304,10 +305,10 @@
     classI2.accessors = <PropertyAccessorElement>[getter];
     ClassElementImpl classA = ElementFactory.classElement2("A");
     classA.interfaces = <InterfaceType>[classI2.type, classI1.type];
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject);
-    expect(mapA.get(methodName), isNull);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject);
+    expect(mapA[methodName], isNull);
     _assertErrors(classA,
         [StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD]);
   }
@@ -328,10 +329,10 @@
     classI2.methods = <MethodElement>[methodM2];
     ClassElementImpl classA = ElementFactory.classElement2("A");
     classA.interfaces = <InterfaceType>[classI1.type, classI2.type];
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject);
-    expect(mapA.get(methodName), isNull);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject);
+    expect(mapA[methodName], isNull);
     _assertErrors(
         classA, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]);
   }
@@ -352,10 +353,10 @@
     classI2.accessors = <PropertyAccessorElement>[getter];
     ClassElementImpl classA = ElementFactory.classElement2("A");
     classA.interfaces = <InterfaceType>[classI1.type, classI2.type];
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject);
-    expect(mapA.get(methodName), isNull);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject);
+    expect(mapA[methodName], isNull);
     _assertErrors(classA,
         [StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD]);
   }
@@ -402,10 +403,10 @@
     classI2.methods = <MethodElement>[methodM2];
     ClassElementImpl classA = ElementFactory.classElement2("A");
     classA.interfaces = <InterfaceType>[classI1.type, classI2.type];
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject);
-    expect(mapA.get(methodName), isNull);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject);
+    expect(mapA[methodName], isNull);
     _assertErrors(
         classA, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]);
   }
@@ -426,10 +427,10 @@
     classI2.methods = <MethodElement>[methodM2];
     ClassElementImpl classA = ElementFactory.classElement2("A");
     classA.interfaces = <InterfaceType>[classI2.type, classI1.type];
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject);
-    expect(mapA.get(methodName), isNull);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject);
+    expect(mapA[methodName], isNull);
     _assertErrors(
         classA, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]);
   }
@@ -443,13 +444,13 @@
         ElementFactory.methodElement(methodName, _typeProvider.intType);
     classA.methods = <MethodElement>[methodM];
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    MemberMap mapB =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB);
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject);
-    expect(mapB.size, _numOfMembersInObject + 1);
-    expect(mapB.get(methodName), same(methodM));
+    Map<String, ExecutableElement> mapB =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classB);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject);
+    expect(mapB.length, _numOfMembersInObject + 1);
+    expect(mapB[methodName], same(methodM));
     _assertNoErrors(classA);
     _assertNoErrors(classB);
   }
@@ -464,13 +465,13 @@
     classA.methods = <MethodElement>[methodM];
     ClassElementImpl classB = ElementFactory.classElement2("B");
     classB.interfaces = <InterfaceType>[classA.type];
-    MemberMap mapB =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB);
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject);
-    expect(mapB.size, _numOfMembersInObject + 1);
-    expect(mapB.get(methodName), same(methodM));
+    Map<String, ExecutableElement> mapB =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classB);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject);
+    expect(mapB.length, _numOfMembersInObject + 1);
+    expect(mapB[methodName], same(methodM));
     _assertNoErrors(classA);
     _assertNoErrors(classB);
   }
@@ -485,13 +486,13 @@
     classA.methods = <MethodElement>[methodM];
     ClassElementImpl classB = ElementFactory.classElement2("B");
     classB.mixins = <InterfaceType>[classA.type];
-    MemberMap mapB =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB);
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject);
-    expect(mapB.size, _numOfMembersInObject + 1);
-    expect(mapB.get(methodName), same(methodM));
+    Map<String, ExecutableElement> mapB =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classB);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject);
+    expect(mapB.length, _numOfMembersInObject + 1);
+    expect(mapB[methodName], same(methodM));
     _assertNoErrors(classA);
     _assertNoErrors(classB);
   }
@@ -512,11 +513,11 @@
     classI2.methods = <MethodElement>[methodM2];
     ClassElementImpl classA = ElementFactory.classElement2("A");
     classA.interfaces = <InterfaceType>[classI1.type, classI2.type];
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject + 2);
-    expect(mapA.get(methodName1), same(methodM1));
-    expect(mapA.get(methodName2), same(methodM2));
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject + 2);
+    expect(mapA[methodName1], same(methodM1));
+    expect(mapA[methodName2], same(methodM2));
     _assertNoErrors(classA);
   }
 
@@ -536,12 +537,12 @@
     classI2.accessors = <PropertyAccessorElement>[getter2];
     ClassElementImpl classA = ElementFactory.classElement2("A");
     classA.interfaces = <InterfaceType>[classI1.type, classI2.type];
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject + 1);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject + 1);
     PropertyAccessorElement syntheticAccessor = ElementFactory.getterElement(
         accessorName, false, _typeProvider.dynamicType);
-    expect(mapA.get(accessorName).type, syntheticAccessor.type);
+    expect(mapA[accessorName].type, syntheticAccessor.type);
     _assertNoErrors(classA);
   }
 
@@ -571,12 +572,12 @@
     classI2.methods = <MethodElement>[methodM2];
     ClassElementImpl classA = ElementFactory.classElement2("A");
     classA.interfaces = <InterfaceType>[classI1.type, classI2.type];
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject + 1);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject + 1);
     MethodElement syntheticMethod = ElementFactory.methodElement(
         methodName, _typeProvider.dynamicType, [_typeProvider.dynamicType]);
-    expect(mapA.get(methodName).type, syntheticMethod.type);
+    expect(mapA[methodName].type, syntheticMethod.type);
     _assertNoErrors(classA);
   }
 
@@ -596,13 +597,13 @@
     classI2.accessors = <PropertyAccessorElement>[setter2];
     ClassElementImpl classA = ElementFactory.classElement2("A");
     classA.interfaces = <InterfaceType>[classI1.type, classI2.type];
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject + 1);
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject + 1);
     PropertyAccessorElementImpl syntheticAccessor = ElementFactory
         .setterElement(accessorName, false, _typeProvider.dynamicType);
     syntheticAccessor.returnType = _typeProvider.dynamicType;
-    expect(mapA.get("$accessorName=").type, syntheticAccessor.type);
+    expect(mapA["$accessorName="].type, syntheticAccessor.type);
     _assertNoErrors(classA);
   }
 
@@ -637,12 +638,12 @@
       classI2.type,
       classI3.type
     ];
-    MemberMap mapD =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classD);
-    expect(mapD.size, _numOfMembersInObject + 1);
+    Map<String, ExecutableElement> mapD =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classD);
+    expect(mapD.length, _numOfMembersInObject + 1);
     PropertyAccessorElement syntheticAccessor = ElementFactory.getterElement(
         accessorName, false, _typeProvider.dynamicType);
-    expect(mapD.get(accessorName).type, syntheticAccessor.type);
+    expect(mapD[accessorName].type, syntheticAccessor.type);
     _assertNoErrors(classD);
   }
 
@@ -692,12 +693,12 @@
       classI2.type,
       classI3.type
     ];
-    MemberMap mapD =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classD);
-    expect(mapD.size, _numOfMembersInObject + 1);
+    Map<String, ExecutableElement> mapD =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classD);
+    expect(mapD.length, _numOfMembersInObject + 1);
     MethodElement syntheticMethod = ElementFactory.methodElement(
         methodName, _typeProvider.dynamicType, [_typeProvider.dynamicType]);
-    expect(mapD.get(methodName).type, syntheticMethod.type);
+    expect(mapD[methodName].type, syntheticMethod.type);
     _assertNoErrors(classD);
   }
 
@@ -732,13 +733,13 @@
       classI2.type,
       classI3.type
     ];
-    MemberMap mapD =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classD);
-    expect(mapD.size, _numOfMembersInObject + 1);
+    Map<String, ExecutableElement> mapD =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classD);
+    expect(mapD.length, _numOfMembersInObject + 1);
     PropertyAccessorElementImpl syntheticAccessor = ElementFactory
         .setterElement(accessorName, false, _typeProvider.dynamicType);
     syntheticAccessor.returnType = _typeProvider.dynamicType;
-    expect(mapD.get("$accessorName=").type, syntheticAccessor.type);
+    expect(mapD["$accessorName="].type, syntheticAccessor.type);
     _assertNoErrors(classD);
   }
 
@@ -763,10 +764,10 @@
     classI2.methods = <MethodElement>[methodM2];
     ClassElementImpl classA = ElementFactory.classElement2("A");
     classA.interfaces = <InterfaceType>[classI1.type, classI2.type];
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject + 1);
-    expect(mapA.get(methodName), same(methodM2));
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject + 1);
+    expect(mapA[methodName], same(methodM2));
     _assertNoErrors(classA);
   }
 
@@ -809,10 +810,10 @@
       classI2.type,
       classI3.type
     ];
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject + 1);
-    expect(mapA.get(methodName), same(methodM3));
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject + 1);
+    expect(mapA[methodName], same(methodM3));
     _assertNoErrors(classA);
   }
 
@@ -861,10 +862,10 @@
       classI3.type,
       classI4.type
     ];
-    MemberMap mapA =
-        _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA);
-    expect(mapA.size, _numOfMembersInObject + 1);
-    expect(mapA.get(methodName), same(methodM4));
+    Map<String, ExecutableElement> mapA =
+        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
+    expect(mapA.length, _numOfMembersInObject + 1);
+    expect(mapA[methodName], same(methodM4));
     _assertNoErrors(classA);
   }
 
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 8b4cd5e..28f721e 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -5581,26 +5581,6 @@
     verify([source]);
   }
 
-  void test_undefinedIdentifier_hide() {
-    Source source = addSource(r'''
-library L;
-export 'lib1.dart' hide a;''');
-    addNamedSource("/lib1.dart", "library lib1;");
-    computeLibrarySourceErrors(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  void test_undefinedIdentifier_show() {
-    Source source = addSource(r'''
-library L;
-export 'lib1.dart' show a;''');
-    addNamedSource("/lib1.dart", "library lib1;");
-    computeLibrarySourceErrors(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
   void test_undefinedIdentifier_synthetic_whenExpression() {
     Source source = addSource(r'''
 print(x) {}
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index c366b84..47be73f 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -2766,12 +2766,6 @@
   bool parseAsync = true;
 
   /**
-   * A flag indicating whether conditional directives support should be enabled
-   * for a specific test.
-   */
-  bool enableConditionalDirectives = false;
-
-  /**
    * A flag indicating whether generic method support should be enabled for a
    * specific test.
    */
@@ -2833,7 +2827,6 @@
     //
     Parser parser = createParser(listener);
     parser.parseAsync = parseAsync;
-    parser.parseConditionalDirectives = enableConditionalDirectives;
     parser.parseGenericMethods = enableGenericMethods;
     parser.parseGenericMethodComments = enableGenericMethodComments;
     parser.parseFunctionBodies = parseFunctionBodies;
@@ -2964,7 +2957,6 @@
     Parser parser = createParser(listener);
     parser.parseAsync = parseAsync;
     parser.parseFunctionBodies = parseFunctionBodies;
-    parser.parseConditionalDirectives = enableConditionalDirectives;
     parser.parseGenericMethods = enableGenericMethods;
     parser.parseGenericMethodComments = enableGenericMethodComments;
     CompilationUnit unit = parser.parseCompilationUnit(token);
@@ -3707,7 +3699,7 @@
         (obj) => obj is FieldDeclaration, FieldDeclaration, classMember);
     VariableDeclarationList fieldList =
         (classMember as FieldDeclaration).fields;
-    expect((fieldList.keyword as KeywordToken).keyword, Keyword.CONST);
+    expect(fieldList.keyword.keyword, Keyword.CONST);
     NodeList<VariableDeclaration> fields = fieldList.variables;
     expect(fields, hasLength(1));
     VariableDeclaration field = fields[0];
@@ -3733,7 +3725,7 @@
         (obj) => obj is FieldDeclaration, FieldDeclaration, classMember);
     VariableDeclarationList fieldList =
         (classMember as FieldDeclaration).fields;
-    expect((fieldList.keyword as KeywordToken).keyword, Keyword.FINAL);
+    expect(fieldList.keyword.keyword, Keyword.FINAL);
     NodeList<VariableDeclaration> fields = fieldList.variables;
     expect(fields, hasLength(1));
     VariableDeclaration field = fields[0];
@@ -3759,7 +3751,7 @@
         (obj) => obj is FieldDeclaration, FieldDeclaration, classMember);
     VariableDeclarationList fieldList =
         (classMember as FieldDeclaration).fields;
-    expect((fieldList.keyword as KeywordToken).keyword, Keyword.VAR);
+    expect(fieldList.keyword.keyword, Keyword.VAR);
     NodeList<VariableDeclaration> fields = fieldList.variables;
     expect(fields, hasLength(1));
     VariableDeclaration field = fields[0];
@@ -7262,7 +7254,6 @@
   }
 
   void test_parseExportDirective_configuration_multiple() {
-    enableConditionalDirectives = true;
     ExportDirective directive = parse(
         "parseExportDirective",
         <Object>[emptyCommentAndMetadata()],
@@ -7277,7 +7268,6 @@
   }
 
   void test_parseExportDirective_configuration_single() {
-    enableConditionalDirectives = true;
     ExportDirective directive = parse(
         "parseExportDirective",
         <Object>[emptyCommentAndMetadata()],
@@ -7515,7 +7505,7 @@
     Token keyword = result.keyword;
     expect(keyword, isNotNull);
     expect(keyword.type, TokenType.KEYWORD);
-    expect((keyword as KeywordToken).keyword, Keyword.CONST);
+    expect(keyword.keyword, Keyword.CONST);
     expect(result.type, isNull);
   }
 
@@ -7525,7 +7515,7 @@
     Token keyword = result.keyword;
     expect(keyword, isNotNull);
     expect(keyword.type, TokenType.KEYWORD);
-    expect((keyword as KeywordToken).keyword, Keyword.CONST);
+    expect(keyword.keyword, Keyword.CONST);
     expect(result.type, isNotNull);
   }
 
@@ -7535,7 +7525,7 @@
     Token keyword = result.keyword;
     expect(keyword, isNotNull);
     expect(keyword.type, TokenType.KEYWORD);
-    expect((keyword as KeywordToken).keyword, Keyword.FINAL);
+    expect(keyword.keyword, Keyword.FINAL);
     expect(result.type, isNull);
   }
 
@@ -7545,7 +7535,7 @@
     Token keyword = result.keyword;
     expect(keyword, isNotNull);
     expect(keyword.type, TokenType.KEYWORD);
-    expect((keyword as KeywordToken).keyword, Keyword.FINAL);
+    expect(keyword.keyword, Keyword.FINAL);
     expect(result.type, isNotNull);
   }
 
@@ -7555,7 +7545,7 @@
     Token keyword = result.keyword;
     expect(keyword, isNotNull);
     expect(keyword.type, TokenType.KEYWORD);
-    expect((keyword as KeywordToken).keyword, Keyword.FINAL);
+    expect(keyword.keyword, Keyword.FINAL);
     expect(result.type, isNotNull);
   }
 
@@ -7600,7 +7590,7 @@
     Token keyword = result.keyword;
     expect(keyword, isNotNull);
     expect(keyword.type, TokenType.KEYWORD);
-    expect((keyword as KeywordToken).keyword, Keyword.VAR);
+    expect(keyword.keyword, Keyword.VAR);
     expect(result.type, isNull);
   }
 
@@ -8472,7 +8462,6 @@
   }
 
   void test_parseImportDirective_configuration_multiple() {
-    enableConditionalDirectives = true;
     ImportDirective directive = parse(
         "parseImportDirective",
         <Object>[emptyCommentAndMetadata()],
@@ -8490,7 +8479,6 @@
   }
 
   void test_parseImportDirective_configuration_single() {
-    enableConditionalDirectives = true;
     ImportDirective directive = parse(
         "parseImportDirective",
         <Object>[emptyCommentAndMetadata()],
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 4fe6516..fd39ad5 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -42,7 +42,6 @@
   runReflectiveTests(ErrorResolverTest);
   runReflectiveTests(LibraryImportScopeTest);
   runReflectiveTests(LibraryScopeTest);
-  runReflectiveTests(MemberMapTest);
   runReflectiveTests(ScopeTest);
   runReflectiveTests(StrictModeTest);
   runReflectiveTests(SubtypeManagerTest);
@@ -536,52 +535,6 @@
   }
 }
 
-@reflectiveTest
-class MemberMapTest {
-  /**
-   * The null type.
-   */
-  InterfaceType _nullType;
-
-  void setUp() {
-    _nullType = new TestTypeProvider().nullType;
-  }
-
-  void test_MemberMap_copyConstructor() {
-    MethodElement m1 = ElementFactory.methodElement("m1", _nullType);
-    MethodElement m2 = ElementFactory.methodElement("m2", _nullType);
-    MethodElement m3 = ElementFactory.methodElement("m3", _nullType);
-    MemberMap map = new MemberMap();
-    map.put(m1.name, m1);
-    map.put(m2.name, m2);
-    map.put(m3.name, m3);
-    MemberMap copy = new MemberMap.from(map);
-    expect(copy.size, map.size);
-    expect(copy.get(m1.name), m1);
-    expect(copy.get(m2.name), m2);
-    expect(copy.get(m3.name), m3);
-  }
-
-  void test_MemberMap_override() {
-    MethodElement m1 = ElementFactory.methodElement("m", _nullType);
-    MethodElement m2 = ElementFactory.methodElement("m", _nullType);
-    MemberMap map = new MemberMap();
-    map.put(m1.name, m1);
-    map.put(m2.name, m2);
-    expect(map.size, 1);
-    expect(map.get("m"), m2);
-  }
-
-  void test_MemberMap_put() {
-    MethodElement m1 = ElementFactory.methodElement("m1", _nullType);
-    MemberMap map = new MemberMap();
-    expect(map.size, 0);
-    map.put(m1.name, m1);
-    expect(map.size, 1);
-    expect(map.get("m1"), m1);
-  }
-}
-
 class Scope_EnclosedScopeTest_test_define_duplicate extends Scope {
   GatheringErrorListener listener;
 
diff --git a/pkg/analyzer/test/generated/resolver_test_case.dart b/pkg/analyzer/test/generated/resolver_test_case.dart
index 264d393..c63cc85 100644
--- a/pkg/analyzer/test/generated/resolver_test_case.dart
+++ b/pkg/analyzer/test/generated/resolver_test_case.dart
@@ -756,12 +756,20 @@
       String typeParams: '[]',
       String typeArgs: '[]',
       String typeFormals: '[]'}) {
+    typeParameters(Element element) {
+      if (element is ExecutableElement) {
+        return element.typeParameters;
+      } else if (element is ParameterElement) {
+        return element.typeParameters;
+      }
+      fail('Wrong element type: ${element.runtimeType}');
+    }
     SimpleIdentifier identifier = findIdentifier(name);
     // Element is either ExecutableElement or ParameterElement.
-    var element = identifier.staticElement;
+    Element element = identifier.staticElement;
     FunctionTypeImpl functionType = identifier.staticType;
     expect(functionType.toString(), type);
-    expect(element.typeParameters.toString(), elementTypeParams);
+    expect(typeParameters(element).toString(), elementTypeParams);
     expect(functionType.typeParameters.toString(), typeParams);
     expect(functionType.typeArguments.toString(), typeArgs);
     expect(functionType.typeFormals.toString(), typeFormals);
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 64bebe3..4568fe9 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -470,7 +470,49 @@
 ''');
   }
 
-  void test_illegal_return_type_async_function() {
+  void test_illegalAsyncGeneratorReturnType_function_nonStream() {
+    assertErrorsInCode(
+        '''
+int f() async* {}
+''',
+        [StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE]);
+  }
+
+  void test_illegalAsyncGeneratorReturnType_function_subtypeOfStream() {
+    resetWithOptions(new AnalysisOptionsImpl()..strongMode = true);
+    assertErrorsInCode(
+        '''
+import 'dart:async';
+abstract class SubStream<T> implements Stream<T> {}
+SubStream<int> f() async* {}
+''',
+        [StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE]);
+  }
+
+  void test_illegalAsyncGeneratorReturnType_method_nonStream() {
+    assertErrorsInCode(
+        '''
+class C {
+  int f() async* {}
+}
+''',
+        [StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE]);
+  }
+
+  void test_illegalAsyncGeneratorReturnType_method_subtypeOfStream() {
+    resetWithOptions(new AnalysisOptionsImpl()..strongMode = true);
+    assertErrorsInCode(
+        '''
+import 'dart:async';
+abstract class SubStream<T> implements Stream<T> {}
+class C {
+  SubStream<int> f() async* {}
+}
+''',
+        [StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE]);
+  }
+
+  void test_illegalAsyncReturnType_function_nonFuture() {
     assertErrorsInCode(
         '''
 int f() async {}
@@ -481,29 +523,24 @@
         ]);
   }
 
-  void test_illegal_return_type_async_generator_function() {
+  void test_illegalAsyncReturnType_function_subtypeOfFuture() {
+    resetWithOptions(new AnalysisOptionsImpl()..strongMode = true);
     assertErrorsInCode(
         '''
-int f() async* {}
-''',
-        [StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE]);
-  }
-
-  void test_illegal_return_type_async_generator_method() {
-    assertErrorsInCode(
-        '''
-class C {
-  int f() async* {}
+import 'dart:async';
+abstract class SubFuture<T> implements Future<T> {}
+SubFuture<int> f() async {
+  return 0;
 }
 ''',
-        [StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE]);
+        [StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE]);
   }
 
-  void test_illegal_return_type_async_method() {
+  void test_illegalAsyncReturnType_method_nonFuture() {
     assertErrorsInCode(
         '''
 class C {
-  int f() async {}
+  int m() async {}
 }
 ''',
         [
@@ -512,7 +549,22 @@
         ]);
   }
 
-  void test_illegal_return_type_sync_generator_function() {
+  void test_illegalAsyncReturnType_method_subtypeOfFuture() {
+    resetWithOptions(new AnalysisOptionsImpl()..strongMode = true);
+    assertErrorsInCode(
+        '''
+import 'dart:async';
+abstract class SubFuture<T> implements Future<T> {}
+class C {
+  SubFuture<int> m() async {
+    return 0;
+  }
+}
+''',
+        [StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE]);
+  }
+
+  void test_illegalSyncGeneratorReturnType_function_nonIterator() {
     assertErrorsInCode(
         '''
 int f() sync* {}
@@ -520,7 +572,17 @@
         [StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE]);
   }
 
-  void test_illegal_return_type_sync_generator_method() {
+  void test_illegalSyncGeneratorReturnType_function_subclassOfIterator() {
+    resetWithOptions(new AnalysisOptionsImpl()..strongMode = true);
+    assertErrorsInCode(
+        '''
+abstract class SubIterator<T> implements Iterator<T> {}
+SubIterator<int> f() sync* {}
+''',
+        [StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE]);
+  }
+
+  void test_illegalSyncGeneratorReturnType_method_nonIterator() {
     assertErrorsInCode(
         '''
 class C {
@@ -530,6 +592,18 @@
         [StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE]);
   }
 
+  void test_illegalSyncGeneratorReturnType_method_subclassOfIterator() {
+    resetWithOptions(new AnalysisOptionsImpl()..strongMode = true);
+    assertErrorsInCode(
+        '''
+abstract class SubIterator<T> implements Iterator<T> {}
+class C {
+  SubIterator<int> f() sync* {}
+}
+''',
+        [StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE]);
+  }
+
   void test_inconsistentMethodInheritance_paramCount() {
     assertErrorsInCode(
         r'''
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index 8a55212..7bc5ed1 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -681,6 +681,41 @@
     verify([source]);
   }
 
+  void test_inferredFieldDeclaration_propagation() {
+    // Regression test for https://github.com/dart-lang/sdk/issues/25546
+    String code = r'''
+      abstract class A {
+        Map<int, List<int>> get map;
+      }
+      class B extends A {
+        var map = { 42: [] };
+      }
+      class C extends A {
+        get map => { 43: [] };
+      }
+   ''';
+    CompilationUnit unit = resolveSource(code);
+
+    Asserter<InterfaceType> assertListOfInt = _isListOf(_isInt);
+    Asserter<InterfaceType> assertMapOfIntToListOfInt =
+        _isMapOf(_isInt, assertListOfInt);
+
+    VariableDeclaration mapB = AstFinder.getFieldInClass(unit, "B", "map");
+    MethodDeclaration mapC = AstFinder.getMethodInClass(unit, "C", "map");
+    assertMapOfIntToListOfInt(mapB.element.type);
+    assertMapOfIntToListOfInt(mapC.element.returnType);
+
+    MapLiteral mapLiteralB = mapB.initializer;
+    MapLiteral mapLiteralC = (mapC.body as ExpressionFunctionBody).expression;
+    assertMapOfIntToListOfInt(mapLiteralB.staticType);
+    assertMapOfIntToListOfInt(mapLiteralC.staticType);
+
+    ListLiteral listLiteralB = mapLiteralB.entries[0].value;
+    ListLiteral listLiteralC = mapLiteralC.entries[0].value;
+    assertListOfInt(listLiteralB.staticType);
+    assertListOfInt(listLiteralC.staticType);
+  }
+
   void test_instanceCreation() {
     String code = r'''
       class A<S, T> {
diff --git a/pkg/analyzer/test/src/context/mock_sdk.dart b/pkg/analyzer/test/src/context/mock_sdk.dart
index 62d0beb..e7021f0 100644
--- a/pkg/analyzer/test/src/context/mock_sdk.dart
+++ b/pkg/analyzer/test/src/context/mock_sdk.dart
@@ -8,8 +8,7 @@
 import 'package:analyzer/file_system/memory_file_system.dart' as resource;
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/generated/engine.dart'
-    show AnalysisEngine, ChangeSet;
+import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 
diff --git a/pkg/analyzer/test/src/summary/index_unit_test.dart b/pkg/analyzer/test/src/summary/index_unit_test.dart
index cb18d02..9a269b0 100644
--- a/pkg/analyzer/test/src/summary/index_unit_test.dart
+++ b/pkg/analyzer/test/src/summary/index_unit_test.dart
@@ -819,6 +819,26 @@
       ..isInvokedAt('foo());', false);
   }
 
+  void test_isReferencedBy_FunctionElement_with_LibraryElement() {
+    addSource(
+        '/foo.dart',
+        r'''
+bar() {}
+''');
+    _indexTestUnit('''
+import "foo.dart";
+main() {
+  bar();
+}
+''');
+    LibraryElement fooLibrary = testLibraryElement.imports[0].importedLibrary;
+    assertThat(fooLibrary)..isReferencedAt('"foo.dart";', true, length: 10);
+    {
+      FunctionElement bar = fooLibrary.definingCompilationUnit.functions[0];
+      assertThat(bar)..isInvokedAt('bar();', false);
+    }
+  }
+
   void test_isReferencedBy_FunctionTypeAliasElement() {
     _indexTestUnit('''
 typedef A();
diff --git a/pkg/analyzer/test/src/summary/linker_test.dart b/pkg/analyzer/test/src/summary/linker_test.dart
index 81499ae..e5f0dfa 100644
--- a/pkg/analyzer/test/src/summary/linker_test.dart
+++ b/pkg/analyzer/test/src/summary/linker_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/link.dart';
 import 'package:unittest/unittest.dart';
@@ -38,6 +39,117 @@
     return linker.getLibrary(Uri.parse(uri));
   }
 
+  void test_baseClass_genericWithAccessor() {
+    createLinker('''
+class B<T> {
+  int get i => null;
+}
+class C<U> extends B<U> {
+  var j;
+}
+    ''');
+    LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri);
+    library.libraryCycleForLink.ensureLinked();
+    // No assertions--just make sure it doesn't crash.
+  }
+
+  void test_baseClass_genericWithField() {
+    createLinker('''
+class B<T> {
+  int i = 0;
+}
+class C<T> extends B<T> {
+  void f() {}
+}
+''');
+    LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri);
+    library.libraryCycleForLink.ensureLinked();
+    // No assertions--just make sure it doesn't crash.
+  }
+
+  void test_baseClass_genericWithFunctionTypedParameter() {
+    createLinker('''
+class B<T> {
+  void f(void g(T t));
+}
+class C<U> extends B<U> {
+  void f(g) {}
+}
+''');
+    LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri);
+    library.libraryCycleForLink.ensureLinked();
+    // No assertions--just make sure it doesn't crash.
+  }
+
+  void test_baseClass_genericWithGenericMethod() {
+    createLinker('''
+class B<T> {
+  List<U> f<U>(U u) => null;
+}
+class C<V> extends B<V> {
+  var j;
+}
+''');
+    LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri);
+    library.libraryCycleForLink.ensureLinked();
+    // No assertions--just make sure it doesn't crash.
+  }
+
+  void test_baseClass_genericWithGenericMethod_returnsGenericFuture() {
+    createLinker('''
+import 'dart:async';
+class B<T> {
+  Future<T> f() => null;
+}
+class C<T> extends B<T> {
+  Future<T> f() => null;
+}
+''');
+    LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri);
+    library.libraryCycleForLink.ensureLinked();
+    // No assertions--just make sure it doesn't crash.
+  }
+
+  void test_baseClass_genericWithStaticFinal() {
+    createLinker('''
+class B<T> {
+  static final int i = 0;
+}
+class C<T> extends B<T> {
+  void f() {}
+}
+''');
+    LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri);
+    library.libraryCycleForLink.ensureLinked();
+  }
+
+  void test_baseClass_withPrivateField() {
+    createLinker('''
+class B {
+  var _b;
+}
+class C extends B {
+  var c;
+}
+''');
+    LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri);
+    library.libraryCycleForLink.ensureLinked();
+    // No assertions--just make sure it doesn't crash.
+  }
+
+  void test_constCycle_viaLength() {
+    createLinker('''
+class C {
+  final y;
+  const C() : y = x.length;
+}
+const x = [const C()];
+''');
+    testLibrary.libraryCycleForLink.ensureLinked();
+    ClassElementForLink classC = testLibrary.getContainedName('C');
+    expect(classC.unnamedConstructor.isCycleFree, false);
+  }
+
   void test_inferredType_instanceField_dynamic() {
     createLinker('''
 var x;
@@ -87,6 +199,22 @@
     expect(cls.methods[0].returnType.toString(), 'dynamic');
   }
 
+  void test_inferredType_methodReturnType_void() {
+    createLinker('''
+class B {
+  void f() {}
+}
+class C extends B {
+  f() {}
+}
+''');
+    LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri);
+    library.libraryCycleForLink.ensureLinked();
+    ClassElementForLink_Class cls = library.getContainedName('C');
+    expect(cls.methods, hasLength(1));
+    expect(cls.methods[0].returnType.toString(), 'void');
+  }
+
   void test_inferredType_staticField_dynamic() {
     createLinker('''
 dynamic x = null;
@@ -100,6 +228,7 @@
             .getContainedName('C')
             .getContainedName('y')
             .asTypeInferenceNode
+            .variableElement
             .inferredType
             .toString(),
         'dynamic');
@@ -115,6 +244,7 @@
             .getLibrary(linkerInputs.testDartUri)
             .getContainedName('y')
             .asTypeInferenceNode
+            .variableElement
             .inferredType
             .toString(),
         'dynamic');
@@ -137,6 +267,7 @@
         library
             .getContainedName('z')
             .asTypeInferenceNode
+            .variableElement
             .inferredType
             .toString(),
         'dynamic');
@@ -160,11 +291,32 @@
         library
             .getContainedName('x')
             .asTypeInferenceNode
+            .variableElement
             .inferredType
             .toString(),
         'int');
   }
 
+  void test_inferredTypeFromOutsideBuildUnit_instanceField_toInstanceField() {
+    var bundle = createPackageBundle(
+        '''
+class C {
+  var f = 0; // Inferred type: int
+}
+''',
+        path: '/a.dart');
+    addBundle(bundle);
+    createLinker('''
+import 'a.dart';
+class D {
+  var g = new C().f; // Inferred type: int
+}
+''');
+    LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri);
+    ClassElementForLink_Class classD = library.getContainedName('D');
+    expect(classD.fields[0].inferredType.toString(), 'int');
+  }
+
   void test_inferredTypeFromOutsideBuildUnit_methodParamType_viaGeneric() {
     var bundle = createPackageBundle(
         '''
@@ -186,27 +338,12 @@
         library
             .getContainedName('x')
             .asTypeInferenceNode
+            .variableElement
             .inferredType
             .toString(),
         'int');
   }
 
-  void test_inferredType_methodReturnType_void() {
-    createLinker('''
-class B {
-  void f() {}
-}
-class C extends B {
-  f() {}
-}
-''');
-    LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri);
-    library.libraryCycleForLink.ensureLinked();
-    ClassElementForLink_Class cls = library.getContainedName('C');
-    expect(cls.methods, hasLength(1));
-    expect(cls.methods[0].returnType.toString(), 'void');
-  }
-
   void test_inferredTypeFromOutsideBuildUnit_methodParamType_viaInheritance() {
     var bundle = createPackageBundle(
         '''
@@ -255,6 +392,7 @@
         library
             .getContainedName('x')
             .asTypeInferenceNode
+            .variableElement
             .inferredType
             .toString(),
         'int');
@@ -295,6 +433,7 @@
             .getLibrary(linkerInputs.testDartUri)
             .getContainedName('x')
             .asTypeInferenceNode
+            .variableElement
             .inferredType
             .toString(),
         'int');
@@ -309,6 +448,7 @@
             .getLibrary(linkerInputs.testDartUri)
             .getContainedName('b')
             .asTypeInferenceNode
+            .variableElement
             .inferredType
             .toString(),
         'int');
@@ -397,4 +537,50 @@
         unorderedEquals([libA.libraryCycleForLink, libB.libraryCycleForLink]));
     expect(libraryCycle.libraries, [testLibrary]);
   }
+
+  void test_multiplyInheritedExecutable_differentSignatures() {
+    createLinker('''
+class B {
+  void f() {}
+}
+abstract class I {
+   f();
+}
+class C extends B with I {}
+class D extends C {
+  void f() {}
+}
+''');
+    LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri);
+    library.libraryCycleForLink.ensureLinked();
+    // No assertions--just make sure it doesn't crash.
+  }
+
+  void test_parameterParentElementForLink_implicitFunctionTypeIndices() {
+    createLinker('void f(a, void g(b, c, d, void h())) {}');
+    TopLevelFunctionElementForLink f = testLibrary.getContainedName('f');
+    expect(f.implicitFunctionTypeIndices, []);
+    ParameterElementForLink g = f.parameters[1];
+    FunctionType gType = g.type;
+    FunctionElementForLink_FunctionTypedParam gTypeElement = gType.element;
+    expect(gTypeElement.implicitFunctionTypeIndices, [1]);
+    ParameterElementForLink h = gTypeElement.parameters[3];
+    FunctionType hType = h.type;
+    FunctionElementForLink_FunctionTypedParam hTypeElement = hType.element;
+    expect(hTypeElement.implicitFunctionTypeIndices, [1, 3]);
+  }
+
+  void test_parameterParentElementForLink_innermostExecutable() {
+    createLinker('void f(void g(void h())) {}');
+    TopLevelFunctionElementForLink f = testLibrary.getContainedName('f');
+    expect(f.innermostExecutable, same(f));
+    ParameterElementForLink g = f.parameters[0];
+    FunctionType gType = g.type;
+    FunctionElementForLink_FunctionTypedParam gTypeElement = gType.element;
+    expect(gTypeElement.innermostExecutable, same(f));
+    ParameterElementForLink h = gTypeElement.parameters[0];
+    FunctionType hType = h.type;
+    FunctionElementForLink_FunctionTypedParam hTypeElement = hType.element;
+    expect(hTypeElement.innermostExecutable, same(f));
+  }
 }
diff --git a/pkg/analyzer/test/src/summary/prelinker_test.dart b/pkg/analyzer/test/src/summary/prelinker_test.dart
index f2f1a82..b4a2172 100644
--- a/pkg/analyzer/test/src/summary/prelinker_test.dart
+++ b/pkg/analyzer/test/src/summary/prelinker_test.dart
@@ -59,6 +59,8 @@
   @override
   void serializeLibraryElement(LibraryElement library) {
     super.serializeLibraryElement(library);
+    uriToPublicNamespace[library.source.uri.toString()] =
+        unlinkedUnits[0].publicNamespace;
     Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{};
     expect(unlinkedUnits.length, unitUris.length);
     for (int i = 1; i < unlinkedUnits.length; i++) {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
index 5e2bcd6..9d7a10d 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
@@ -245,10 +245,87 @@
   ''');
   }
 
+  void test_infer_extractProperty_getter_sequence() {
+    var unit = checkFile(r'''
+class A {
+  B b = new B();
+}
+class B {
+  C c = new C();
+}
+class C {
+  int d;
+}
+var a = new A();
+var v = a.b.c.d;
+  ''');
+    expect(unit.topLevelVariables[1].type.toString(), 'int');
+  }
+
+  void test_infer_extractProperty_getter_sequence_generic() {
+    var unit = checkFile(r'''
+class A<T> {
+  B<T> b = new B<T>();
+}
+class B<K> {
+  C<List<K>, int> c = new C<List<K>, int>();
+}
+class C<K, V> {
+  Map<K, V> d;
+}
+var a = new A<double>();
+var v = a.b.c.d;
+  ''');
+    expect(unit.topLevelVariables[1].type.toString(), 'Map<List<double>, int>');
+  }
+
+  void test_infer_extractProperty_getter_sequence_withUnresolved() {
+    var unit = checkFile(r'''
+class A {
+  B b = new B();
+}
+class B {
+  int c;
+}
+var a = new A();
+var v = a.b.foo.c;
+  ''');
+    expect(unit.topLevelVariables[1].type.toString(), 'dynamic');
+  }
+
   void test_infer_extractProperty_method() {
-    checkFile(r'''
+    var unit = checkFile(r'''
+class A {
+  int m(double p1, String p2) => 42;
+}
+var a = new A();
+var v = a.m;
+  ''');
+    expect(unit.topLevelVariables[1].type.toString(), '(double, String) → int');
+  }
+
+  void test_infer_extractProperty_method2() {
+    var unit = checkFile(r'''
 var a = 1.round;
   ''');
+    expect(unit.topLevelVariables[0].type.toString(), '() → int');
+  }
+
+  void test_infer_extractProperty_method_sequence() {
+    var unit = checkFile(r'''
+class A {
+  B b = new B();
+}
+class B {
+  C c = new C();
+}
+class C {
+  int m(double p1, String p2) => 42;
+}
+var a = new A();
+var v = a.b.c.m;
+  ''');
+    expect(unit.topLevelVariables[1].type.toString(), '(double, String) → int');
   }
 
   void test_infer_invokeConstructor_factoryRedirected() {
@@ -319,6 +396,160 @@
   ''');
   }
 
+  void test_infer_invokeMethodRef_function() {
+    var unit = checkFile(r'''
+int m() => 0;
+var a = m();
+  ''');
+    expect(unit.topLevelVariables[0].type.toString(), 'int');
+  }
+
+  void test_infer_invokeMethodRef_function_generic() {
+    var unit = checkFile(r'''
+/*=Map<int, V>*/ m/*<V>*/(/*=V*/ a) => null;
+var a = m(2.3);
+  ''');
+    expect(unit.topLevelVariables[0].type.toString(), 'Map<int, double>');
+  }
+
+  void test_infer_invokeMethodRef_function_importedWithPrefix() {
+    addFile(
+        r'''
+int m() => 0;
+''',
+        name: '/a.dart');
+    var unit = checkFile(r'''
+import 'a.dart' as p;
+var a = p.m();
+  ''');
+    expect(unit.topLevelVariables[0].type.toString(), 'int');
+  }
+
+  void test_infer_invokeMethodRef_method() {
+    var unit = checkFile(r'''
+class A {
+  int m() => 0;
+}
+var a = new A();
+var b = a.m();
+  ''');
+    expect(unit.topLevelVariables[1].type.toString(), 'int');
+  }
+
+  void test_infer_invokeMethodRef_method_g() {
+    var unit = checkFile(r'''
+class A {
+  /*=T*/ m/*<T>*/(/*=T*/ a) => null;
+}
+var a = new A();
+var b = a.m(1.0);
+  ''');
+    expect(unit.topLevelVariables[1].type.toString(), 'double');
+  }
+
+  void test_infer_invokeMethodRef_method_genericSequence() {
+    var unit = checkFile(r'''
+class A<T> {
+  B<T> b = new B<T>();
+}
+class B<K> {
+  C<List<K>, int> c = new C<List<K>, int>();
+}
+class C<K, V> {
+  Map<K, V> m() => null;
+}
+var a = new A<double>();
+var v = a.b.c.m();
+  ''');
+    expect(unit.topLevelVariables[1].type.toString(), 'Map<List<double>, int>');
+  }
+
+  void test_infer_invokeMethodRef_method_gg() {
+    var unit = checkFile(r'''
+class A<K> {
+  /*=Map<K, V>*/ m/*<V>*/(/*=V*/ a) => null;
+}
+var a = new A<int>();
+var b = a.m(1.0);
+  ''');
+    expect(unit.topLevelVariables[1].type.toString(), 'Map<int, double>');
+  }
+
+  void test_infer_invokeMethodRef_method_importedWithPrefix() {
+    addFile(
+        r'''
+class A {
+  int m() => 0;
+}
+var a = new A();
+''',
+        name: '/a.dart');
+    var unit = checkFile(r'''
+import 'a.dart' as p;
+var b = p.a.m();
+  ''');
+    expect(unit.topLevelVariables[0].type.toString(), 'int');
+  }
+
+  void test_infer_invokeMethodRef_method_importedWithPrefix2() {
+    addFile(
+        r'''
+class A {
+  B b = new B();
+}
+class B {
+  int m() => 0;
+}
+var a = new A();
+''',
+        name: '/a.dart');
+    var unit = checkFile(r'''
+import 'a.dart' as p;
+var b = p.a.b.m();
+  ''');
+    expect(unit.topLevelVariables[0].type.toString(), 'int');
+  }
+
+  void test_infer_invokeMethodRef_method_withInferredTypeInLibraryCycle() {
+    var unit = checkFile('''
+class Base {
+  int m() => 0;
+}
+class A extends Base {
+  m() => 0; // Inferred return type: int
+}
+var a = new A();
+var b = a.m();
+    ''');
+    // Type inference operates on static and top level variables prior to
+    // instance members.  So at the time `b` is inferred, `A.m` still has return
+    // type `dynamic`.
+    expect(unit.topLevelVariables[1].type.toString(), 'dynamic');
+  }
+
+  void test_infer_invokeMethodRef_method_withInferredTypeOutsideLibraryCycle() {
+    addFile(
+        '''
+class Base {
+  int m() => 0;
+}
+class A extends Base {
+  m() => 0; // Inferred return type: int
+}
+''',
+        name: '/a.dart');
+    var unit = checkFile('''
+import 'a.dart';
+var a = new A();
+var b = a.m();
+''');
+    // Since a.dart is in a separate library file from the compilation unit
+    // containing `a` and `b`, its types are inferred first; then `a` and `b`'s
+    // types are inferred.  So the inferred return type of `int` should be
+    // propagated to `b`.
+    expect(unit.topLevelVariables[1].type.toString(), 'int');
+  }
+
   @override
   @failingTest
   void test_inferCorrectlyOnMultipleVariablesDeclaredTogether() {
@@ -331,30 +562,6 @@
     super.test_inferenceInCyclesIsDeterministic();
   }
 
-  @override
-  @failingTest
-  void test_inferFromRhsOnlyIfItWontConflictWithOverriddenFields() {
-    super.test_inferFromRhsOnlyIfItWontConflictWithOverriddenFields();
-  }
-
-  @override
-  @failingTest
-  void test_inferTypesOnGenericInstantiations_4() {
-    super.test_inferTypesOnGenericInstantiations_4();
-  }
-
-  @override
-  @failingTest
-  void test_inferTypesOnGenericInstantiations_5() {
-    super.test_inferTypesOnGenericInstantiations_5();
-  }
-
-  @override
-  @failingTest
-  void test_inferTypesOnGenericInstantiationsInLibraryCycle() {
-    super.test_inferTypesOnGenericInstantiationsInLibraryCycle();
-  }
-
   void test_invokeMethod_notGeneric_genericClass() {
     var unit = checkFile(r'''
 class C<T> {
@@ -410,12 +617,13 @@
   bool get checkPropagatedTypes => false;
 
   @override
-  void checkLibrary(String text,
+  LibraryElementImpl checkLibrary(String text,
       {bool allowErrors: false, bool dumpSummaries: false}) {
     Source source = addTestSource(text);
     LibraryElementImpl resynthesized = _encodeDecodeLibraryElement(source);
     LibraryElementImpl original = context.computeLibraryElement(source);
     checkLibraryElements(original, resynthesized);
+    return resynthesized;
   }
 
   @override
diff --git a/pkg/analyzer/test/src/summary/resynthesize_test.dart b/pkg/analyzer/test/src/summary/resynthesize_test.dart
index 5b4f8ed..b4e87cd 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_test.dart
@@ -17,8 +17,7 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/resolver.dart'
-    show Namespace, TypeProvider;
+import 'package:analyzer/src/generated/resolver.dart' show Namespace;
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/testing/ast_factory.dart';
@@ -1212,7 +1211,7 @@
 @reflectiveTest
 class ResynthesizeElementTest extends ResynthesizeTest {
   @override
-  void checkLibrary(String text,
+  LibraryElementImpl checkLibrary(String text,
       {bool allowErrors: false, bool dumpSummaries: false}) {
     Source source = addTestSource(text);
     LibraryElementImpl original = context.computeLibraryElement(source);
@@ -1222,6 +1221,7 @@
         source.uri.toString(),
         original);
     checkLibraryElements(original, resynthesized);
+    return resynthesized;
   }
 
   @override
@@ -1317,7 +1317,7 @@
 
 @reflectiveTest
 abstract class ResynthesizeTest extends AbstractResynthesizeTest {
-  void checkLibrary(String text,
+  LibraryElementImpl checkLibrary(String text,
       {bool allowErrors: false, bool dumpSummaries: false});
 
   /**
@@ -3165,6 +3165,18 @@
     checkLibrary('import "a.dart" as a; a.C c;');
   }
 
+  test_import_self() {
+    LibraryElementImpl resynthesized = checkLibrary('''
+import 'test.dart' as p;
+class C {}
+class D extends p.C {} // Prevent "unused import" warning
+''');
+    expect(resynthesized.imports, hasLength(2));
+    expect(resynthesized.imports[0].importedLibrary.location,
+        resynthesized.location);
+    expect(resynthesized.imports[1].importedLibrary.isDartCore, true);
+  }
+
   test_import_show() {
     addLibrary('dart:async');
     checkLibrary('''
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index cfde5e9..c50e33b 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -7272,6 +7272,27 @@
         expectedPrefix: 'p');
   }
 
+  test_import_self() {
+    if (!checkAstDerivedData) {
+      // TODO(paulberry): this test fails when building the summary from the
+      // element model because the element model can't tell the difference
+      // between self references via a local name and self references via a
+      // self-import.
+      return;
+    }
+    serializeLibraryText('''
+import 'test.dart' as p;
+class C {}
+class D extends p.C {} // Prevent "unused import" warning
+''');
+    expect(unlinkedUnits[0].imports[0].uri, 'test.dart');
+    checkDependency(
+        linked.importDependencies[0], absUri('/test.dart'), 'test.dart');
+    checkTypeRef(unlinkedUnits[0].classes[1].supertype, absUri('/test.dart'),
+        'test.dart', 'C',
+        expectedPrefix: 'p');
+  }
+
   test_import_show_order() {
     String libraryText =
         'import "dart:async" show Future, Stream; Future x; Stream y;';
@@ -7298,6 +7319,21 @@
     expect(unlinkedUnits[0].imports[0].uri, 'dart:async');
   }
 
+  test_inferred_type_keeps_leading_dynamic() {
+    if (!strongMode || skipFullyLinkedData) {
+      return;
+    }
+    UnlinkedClass cls =
+        serializeClassText('class C { final x = <dynamic, int>{}; }');
+    EntityRef type = getTypeRefForSlot(cls.fields[0].inferredTypeSlot);
+    // Check that x has inferred type `Map<dynamic, int>`.
+    checkLinkedTypeRef(type, 'dart:core', 'dart:core', 'Map',
+        allowTypeArguments: true, numTypeParameters: 2);
+    expect(type.typeArguments, hasLength(2));
+    checkLinkedTypeRef(type.typeArguments[0], null, null, 'dynamic');
+    checkLinkedTypeRef(type.typeArguments[1], 'dart:core', 'dart:core', 'int');
+  }
+
   test_inferred_type_refers_to_bound_type_param() {
     if (!strongMode || skipFullyLinkedData) {
       return;
@@ -7435,6 +7471,32 @@
     checkReferenceIndex(linkedReference.containingReference, null, null, 'D');
   }
 
+  test_inferred_type_skips_trailing_dynamic() {
+    if (!strongMode || skipFullyLinkedData) {
+      return;
+    }
+    UnlinkedClass cls =
+        serializeClassText('class C { final x = <int, dynamic>{}; }');
+    EntityRef type = getTypeRefForSlot(cls.fields[0].inferredTypeSlot);
+    // Check that x has inferred type `Map<int>`.  The trailing type argument
+    // `dynamic` is omitted.
+    checkLinkedTypeRef(type, 'dart:core', 'dart:core', 'Map',
+        allowTypeArguments: true, numTypeParameters: 2);
+    expect(type.typeArguments, hasLength(1));
+    checkLinkedTypeRef(type.typeArguments[0], 'dart:core', 'dart:core', 'int');
+  }
+
+  test_inferred_type_skips_unnecessary_dynamic() {
+    if (!strongMode || skipFullyLinkedData) {
+      return;
+    }
+    UnlinkedClass cls = serializeClassText('class C { final x = []; }');
+    EntityRef type = getTypeRefForSlot(cls.fields[0].inferredTypeSlot);
+    // Check that x has inferred type `List`, not `List<dynamic>`.
+    checkLinkedTypeRef(type, 'dart:core', 'dart:core', 'List',
+        numTypeParameters: 1);
+  }
+
   test_initializer_executable_with_bottom_return_type() {
     // The synthetic executable for `v` has type `() => Bottom`.
     UnlinkedVariable variable = serializeVariableText('int v = null;');
@@ -7744,6 +7806,89 @@
     ]);
   }
 
+  test_metadata_constructor_call_named_prefixed_unresolved_class() {
+    addNamedSource('/foo.dart', '');
+    UnlinkedClass cls = serializeClassText(
+        'import "foo.dart" as foo; @foo.A.named() class C {}',
+        allowErrors: true);
+    expect(cls.annotations, hasLength(1));
+    _assertUnlinkedConst(cls.annotations[0], operators: [
+      UnlinkedConstOperation.invokeConstructor,
+    ], ints: [
+      0,
+      0
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'named',
+          expectedKind: ReferenceKind.unresolved,
+          prefixExpectations: [
+            new _PrefixExpectation(ReferenceKind.unresolved, 'A'),
+            new _PrefixExpectation(ReferenceKind.prefix, 'foo')
+          ],
+          checkAstDerivedDataOverride: true)
+    ]);
+  }
+
+  test_metadata_constructor_call_named_prefixed_unresolved_constructor() {
+    addNamedSource('/foo.dart', 'class A {}');
+    UnlinkedClass cls = serializeClassText(
+        'import "foo.dart" as foo; @foo.A.named() class C {}',
+        allowErrors: true);
+    expect(cls.annotations, hasLength(1));
+    _assertUnlinkedConst(cls.annotations[0], operators: [
+      UnlinkedConstOperation.invokeConstructor,
+    ], ints: [
+      0,
+      0
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'named',
+          expectedKind: ReferenceKind.unresolved,
+          prefixExpectations: [
+            new _PrefixExpectation(ReferenceKind.classOrEnum, 'A',
+                absoluteUri: absUri('/foo.dart'), relativeUri: 'foo.dart'),
+            new _PrefixExpectation(ReferenceKind.prefix, 'foo')
+          ],
+          checkAstDerivedDataOverride: true)
+    ]);
+  }
+
+  test_metadata_constructor_call_named_unresolved_class() {
+    UnlinkedClass cls =
+        serializeClassText('@A.named() class C {}', allowErrors: true);
+    expect(cls.annotations, hasLength(1));
+    _assertUnlinkedConst(cls.annotations[0], operators: [
+      UnlinkedConstOperation.invokeConstructor,
+    ], ints: [
+      0,
+      0
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'named',
+          expectedKind: ReferenceKind.unresolved,
+          prefixExpectations: [
+            new _PrefixExpectation(ReferenceKind.unresolved, 'A')
+          ],
+          checkAstDerivedDataOverride: true)
+    ]);
+  }
+
+  test_metadata_constructor_call_named_unresolved_constructor() {
+    UnlinkedClass cls = serializeClassText('class A {} @A.named() class C {}',
+        allowErrors: true);
+    expect(cls.annotations, hasLength(1));
+    _assertUnlinkedConst(cls.annotations[0], operators: [
+      UnlinkedConstOperation.invokeConstructor,
+    ], ints: [
+      0,
+      0
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'named',
+          expectedKind: ReferenceKind.unresolved,
+          prefixExpectations: [
+            new _PrefixExpectation(ReferenceKind.classOrEnum, 'A')
+          ],
+          checkAstDerivedDataOverride: true)
+    ]);
+  }
+
   test_metadata_constructor_call_unnamed() {
     UnlinkedClass cls =
         serializeClassText('class A { const A(); } @A() class C {}');
@@ -7775,6 +7920,41 @@
     ]);
   }
 
+  test_metadata_constructor_call_unnamed_prefixed_unresolved() {
+    addNamedSource('/foo.dart', '');
+    UnlinkedClass cls = serializeClassText(
+        'import "foo.dart" as foo; @foo.A() class C {}',
+        allowErrors: true);
+    expect(cls.annotations, hasLength(1));
+    _assertUnlinkedConst(cls.annotations[0], operators: [
+      UnlinkedConstOperation.invokeConstructor,
+    ], ints: [
+      0,
+      0
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'A',
+          expectedKind: ReferenceKind.unresolved,
+          expectedPrefix: 'foo',
+          checkAstDerivedDataOverride: true)
+    ]);
+  }
+
+  test_metadata_constructor_call_unnamed_unresolved() {
+    UnlinkedClass cls =
+        serializeClassText('@A() class C {}', allowErrors: true);
+    expect(cls.annotations, hasLength(1));
+    _assertUnlinkedConst(cls.annotations[0], operators: [
+      UnlinkedConstOperation.invokeConstructor,
+    ], ints: [
+      0,
+      0
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'A',
+          expectedKind: ReferenceKind.unresolved,
+          checkAstDerivedDataOverride: true)
+    ]);
+  }
+
   test_metadata_constructor_call_with_args() {
     UnlinkedClass cls =
         serializeClassText('class A { const A(x); } @A(null) class C {}');
@@ -7943,6 +8123,22 @@
     ]);
   }
 
+  test_metadata_prefixed_variable_unresolved() {
+    addNamedSource('/a.dart', '');
+    UnlinkedClass cls = serializeClassText(
+        'import "a.dart" as a; @a.b class C {}',
+        allowErrors: true);
+    expect(cls.annotations, hasLength(1));
+    _assertUnlinkedConst(cls.annotations[0], operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'b',
+          expectedKind: ReferenceKind.unresolved,
+          expectedPrefix: 'a',
+          checkAstDerivedDataOverride: true)
+    ]);
+  }
+
   test_metadata_simpleFormalParameter() {
     checkAnnotationA(serializeExecutableText('const a = null; f(@a x) {}')
         .parameters[0]
@@ -7987,6 +8183,18 @@
         .annotations);
   }
 
+  test_metadata_variable_unresolved() {
+    UnlinkedClass cls = serializeClassText('@a class C {}', allowErrors: true);
+    expect(cls.annotations, hasLength(1));
+    _assertUnlinkedConst(cls.annotations[0], operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'a',
+          expectedKind: ReferenceKind.unresolved,
+          checkAstDerivedDataOverride: true)
+    ]);
+  }
+
   test_method_documented() {
     String text = '''
 class C {
@@ -8197,6 +8405,23 @@
     expect(unlinkedUnits[1].publicNamespace.names[0].name, 'C');
   }
 
+  test_reference_zero() {
+    // Element zero of the references table should be populated in a standard
+    // way.
+    serializeLibraryText('');
+    UnlinkedReference unlinkedReference0 = unlinkedUnits[0].references[0];
+    expect(unlinkedReference0.name, '');
+    expect(unlinkedReference0.prefixReference, 0);
+    LinkedReference linkedReference0 = linked.units[0].references[0];
+    expect(linkedReference0.containingReference, 0);
+    expect(linkedReference0.dependency, 0);
+    expect(linkedReference0.kind, ReferenceKind.unresolved);
+    expect(linkedReference0.localIndex, 0);
+    expect(linkedReference0.name, '');
+    expect(linkedReference0.numTypeParameters, 0);
+    expect(linkedReference0.unit, 0);
+  }
+
   test_setter_documented() {
     String text = '''
 // Extra comment so doc comment offset != 0
diff --git a/pkg/analyzer/test/src/summary/test_all.dart b/pkg/analyzer/test/src/summary/test_all.dart
index fa620fe..2f9202b 100644
--- a/pkg/analyzer/test/src/summary/test_all.dart
+++ b/pkg/analyzer/test/src/summary/test_all.dart
@@ -11,6 +11,7 @@
 import 'in_summary_source_test.dart' as in_summary_source_test;
 import 'incremental_cache_test.dart' as incremental_cache_test;
 import 'index_unit_test.dart' as index_unit_test;
+import 'linker_test.dart' as linker_test;
 import 'name_filter_test.dart' as name_filter_test;
 import 'prelinker_test.dart' as prelinker_test;
 import 'resynthesize_ast_test.dart' as resynthesize_ast_test;
@@ -29,6 +30,7 @@
     in_summary_source_test.main();
     incremental_cache_test.main();
     index_unit_test.main();
+    linker_test.main();
     name_filter_test.main();
     prelinker_test.main();
     resynthesize_ast_test.main();
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index 9b058bc..4c3007b 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -3202,7 +3202,7 @@
     _performParseTask(r'''
 part of lib;
 class B {}''');
-    expect(outputs, hasLength(9));
+    expect(outputs, hasLength(10));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(0));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 1);
@@ -3212,6 +3212,7 @@
     expect(outputs[PARSED_UNIT], isNotNull);
     expect(outputs[SOURCE_KIND], SourceKind.PART);
     expect(outputs[UNITS], hasLength(1));
+    expect(outputs[REFERENCED_SOURCES], hasLength(2));
   }
 
   test_perform_computeSourceKind_noDirectives_hasContainingLibrary() {
@@ -3236,7 +3237,7 @@
 
   test_perform_doesNotExist() {
     _performParseTask(null);
-    expect(outputs, hasLength(9));
+    expect(outputs, hasLength(10));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(0));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 1);
@@ -3246,6 +3247,7 @@
     expect(outputs[PARSED_UNIT], isNotNull);
     expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
     expect(outputs[UNITS], hasLength(1));
+    expect(outputs[REFERENCED_SOURCES], hasLength(2));
   }
 
   test_perform_enableAsync_false() {
@@ -3255,7 +3257,7 @@
     _performParseTask(r'''
 import 'dart:async';
 class B {void foo() async {}}''');
-    expect(outputs, hasLength(9));
+    expect(outputs, hasLength(10));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(1));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 2);
@@ -3265,13 +3267,14 @@
     expect(outputs[PARSED_UNIT], isNotNull);
     expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
     expect(outputs[UNITS], hasLength(1));
+    expect(outputs[REFERENCED_SOURCES], hasLength(3));
   }
 
   test_perform_enableAsync_true() {
     _performParseTask(r'''
 import 'dart:async';
 class B {void foo() async {}}''');
-    expect(outputs, hasLength(9));
+    expect(outputs, hasLength(10));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(1));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 2);
@@ -3281,6 +3284,7 @@
     expect(outputs[PARSED_UNIT], isNotNull);
     expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
     expect(outputs[UNITS], hasLength(1));
+    expect(outputs[REFERENCED_SOURCES], hasLength(3));
   }
 
   test_perform_flushTokenStream() {
@@ -3298,7 +3302,7 @@
 export '${a}lib3.dart';
 part 'part.dart';
 class A {}''');
-    expect(outputs, hasLength(9));
+    expect(outputs, hasLength(10));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(1));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 2);
@@ -3308,6 +3312,7 @@
     expect(outputs[PARSED_UNIT], isNotNull);
     expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
     expect(outputs[UNITS], hasLength(2));
+    expect(outputs[REFERENCED_SOURCES], hasLength(4));
   }
 
   test_perform_library() {
@@ -3317,7 +3322,7 @@
 export 'lib3.dart';
 part 'part.dart';
 class A {''');
-    expect(outputs, hasLength(9));
+    expect(outputs, hasLength(10));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(1));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(1));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 2);
@@ -3327,6 +3332,7 @@
     expect(outputs[PARSED_UNIT], isNotNull);
     expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
     expect(outputs[UNITS], hasLength(2));
+    expect(outputs[REFERENCED_SOURCES], hasLength(5));
   }
 
   test_perform_library_selfReferenceAsPart() {
@@ -3341,7 +3347,7 @@
     _performParseTask(r'''
 part of lib;
 class B {}''');
-    expect(outputs, hasLength(9));
+    expect(outputs, hasLength(10));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(0));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 1);
@@ -3351,6 +3357,7 @@
     expect(outputs[PARSED_UNIT], isNotNull);
     expect(outputs[SOURCE_KIND], SourceKind.PART);
     expect(outputs[UNITS], hasLength(1));
+    expect(outputs[REFERENCED_SOURCES], hasLength(2));
   }
 
   void _performParseTask(String content) {
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 c6d3f1d..cb8fb46 100644
--- a/pkg/analyzer/test/src/task/dart_work_manager_test.dart
+++ b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
@@ -9,7 +9,6 @@
 import 'package:analyzer/src/dart/scanner/scanner.dart' show ScannerErrorCode;
 import 'package:analyzer/src/generated/engine.dart'
     show
-        AnalysisErrorInfo,
         AnalysisErrorInfoImpl,
         CacheState,
         ChangeNoticeImpl,
diff --git a/pkg/analyzer/test/src/task/html_test.dart b/pkg/analyzer/test/src/task/html_test.dart
index c8f1f97..a41cc1c 100644
--- a/pkg/analyzer/test/src/task/html_test.dart
+++ b/pkg/analyzer/test/src/task/html_test.dart
@@ -265,7 +265,12 @@
     Source source = newSource('/test.html');
     Map<String, TaskInput> inputs = ParseHtmlTask.buildInputs(source);
     expect(inputs, isNotNull);
-    expect(inputs.keys, unorderedEquals([ParseHtmlTask.CONTENT_INPUT_NAME]));
+    expect(
+        inputs.keys,
+        unorderedEquals([
+          ParseHtmlTask.CONTENT_INPUT_NAME,
+          ParseHtmlTask.MODIFICATION_TIME_INPUT
+        ]));
   }
 
   test_constructor() {
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index 05c5713..880479d 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -67,16 +67,6 @@
     expect(analysisOptions.enableAsync, false);
   }
 
-  test_configure_enableConditionalDirectives() {
-    expect(analysisOptions.enableConditionalDirectives, true);
-    configureContext('''
-analyzer:
-  language:
-    enableConditionalDirectives: true
-''');
-    expect(analysisOptions.enableConditionalDirectives, true);
-  }
-
   test_configure_enableGenericMethods() {
     expect(analysisOptions.enableGenericMethods, false);
     configureContext('''
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index cff8782..9a7b128 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -737,7 +737,47 @@
     test('dynamic functions - closures are not fuzzy', () {
       // Regression test for
       // https://github.com/dart-lang/sdk/issues/26118
+      // https://github.com/dart-lang/sdk/issues/26156
       checkFile('''
+        void takesF(void f(int x)) {}
+
+        typedef void TakesInt(int x);
+
+        void update(_) {}
+        void updateOpt([_]) {}
+        void updateOptNum([num x]) {}
+
+        class A {
+          TakesInt f;
+          A(TakesInt g) {
+            f = update;
+            f = updateOpt;
+            f = updateOptNum;
+          }
+          TakesInt g(bool a, bool b) {
+            if (a) {
+              return update;
+            } else if (b) {
+              return updateOpt;
+            } else {
+              return updateOptNum;
+            }
+          }
+        }
+
+        void test0() {
+          takesF(update);
+          takesF(updateOpt);
+          takesF(updateOptNum);
+          TakesInt f;
+          f = update;
+          f = updateOpt;
+          f = updateOptNum;
+          new A(update);
+          new A(updateOpt);
+          new A(updateOptNum);
+        }
+
         void test1() {
           void takesF(f(int x)) => null;
           takesF((dynamic y) => 3);
@@ -1646,10 +1686,10 @@
                l = <int>[i, /*info:DOWN_CAST_IMPLICIT*/n, /*warning:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/s];
             }
             {
-               List l = [i];
-               l = [s];
-               l = [n];
-               l = [i, n, s];
+               List l = /*info:INFERRED_TYPE_LITERAL*/[i];
+               l = /*info:INFERRED_TYPE_LITERAL*/[s];
+               l = /*info:INFERRED_TYPE_LITERAL*/[n];
+               l = /*info:INFERRED_TYPE_LITERAL*/[i, n, s];
             }
             {
                Map<String, int> m = <String, int>{s: i};
@@ -1662,13 +1702,15 @@
            // TODO(leafp): We can't currently test for key errors since the
            // error marker binds to the entire entry.
             {
-               Map m = {s: i};
-               m = {s: s};
-               m = {s: n};
-               m = {s: i,
+               Map m = /*info:INFERRED_TYPE_LITERAL*/{s: i};
+               m = /*info:INFERRED_TYPE_LITERAL*/{s: s};
+               m = /*info:INFERRED_TYPE_LITERAL*/{s: n};
+               m = /*info:INFERRED_TYPE_LITERAL*/
+                   {s: i,
                     s: n,
                     s: s};
-               m = {i: s,
+               m = /*info:INFERRED_TYPE_LITERAL*/
+                   {i: s,
                     n: s,
                     s: s};
             }
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 3ace67a..84052c4 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -265,7 +265,7 @@
 main() {
   var f = /*info:INFERRED_TYPE_CLOSURE*/() sync* {
     yield 1;
-    yield* [3, 4.0];
+    yield* /*info:INFERRED_TYPE_LITERAL*/[3, 4.0];
   };
   Iterable<num> g = f();
   Iterable<int> h = /*info:ASSIGNMENT_CAST*/f();
@@ -695,14 +695,16 @@
                       /*info:INFERRED_TYPE_LITERAL*/[3]]);
 
   new F3(/*info:INFERRED_TYPE_LITERAL*/[]);
-  new F3(/*info:INFERRED_TYPE_LITERAL*/[[3]]);
-  new F3(/*info:INFERRED_TYPE_LITERAL*/[["hello"]]);
-  new F3(/*info:INFERRED_TYPE_LITERAL*/[["hello"], [3]]);
+  new F3(/*info:INFERRED_TYPE_LITERAL*/[/*info:INFERRED_TYPE_LITERAL*/[3]]);
+  new F3(/*info:INFERRED_TYPE_LITERAL*/[/*info:INFERRED_TYPE_LITERAL*/["hello"]]);
+  new F3(/*info:INFERRED_TYPE_LITERAL*/[/*info:INFERRED_TYPE_LITERAL*/["hello"],
+                                        /*info:INFERRED_TYPE_LITERAL*/[3]]);
 
   new F4(a: /*info:INFERRED_TYPE_LITERAL*/[]);
-  new F4(a: /*info:INFERRED_TYPE_LITERAL*/[[3]]);
-  new F4(a: /*info:INFERRED_TYPE_LITERAL*/[["hello"]]);
-  new F4(a: /*info:INFERRED_TYPE_LITERAL*/[["hello"], [3]]);
+  new F4(a: /*info:INFERRED_TYPE_LITERAL*/[/*info:INFERRED_TYPE_LITERAL*/[3]]);
+  new F4(a: /*info:INFERRED_TYPE_LITERAL*/[/*info:INFERRED_TYPE_LITERAL*/["hello"]]);
+  new F4(a: /*info:INFERRED_TYPE_LITERAL*/[/*info:INFERRED_TYPE_LITERAL*/["hello"],
+                                           /*info:INFERRED_TYPE_LITERAL*/[3]]);
 }
 ''');
   }
@@ -884,9 +886,9 @@
   }
   {
     List<dynamic> l0 = [];
-    List<dynamic> l1 = [3];
-    List<dynamic> l2 = ["hello"];
-    List<dynamic> l3 = ["hello", 3];
+    List<dynamic> l1 = /*info:INFERRED_TYPE_LITERAL*/[3];
+    List<dynamic> l2 = /*info:INFERRED_TYPE_LITERAL*/["hello"];
+    List<dynamic> l3 = /*info:INFERRED_TYPE_LITERAL*/["hello", 3];
   }
   {
     List<int> l0 = /*severe:STATIC_TYPE_ERROR*/<num>[];
@@ -997,10 +999,10 @@
   }
   {
     Map<dynamic, dynamic> l0 = {};
-    Map<dynamic, dynamic> l1 = {3: "hello"};
-    Map<dynamic, dynamic> l2 = {"hello": "hello"};
-    Map<dynamic, dynamic> l3 = {3: 3};
-    Map<dynamic, dynamic> l4 = {3:"hello", "hello": 3};
+    Map<dynamic, dynamic> l1 = /*info:INFERRED_TYPE_LITERAL*/{3: "hello"};
+    Map<dynamic, dynamic> l2 = /*info:INFERRED_TYPE_LITERAL*/{"hello": "hello"};
+    Map<dynamic, dynamic> l3 = /*info:INFERRED_TYPE_LITERAL*/{3: 3};
+    Map<dynamic, dynamic> l4 = /*info:INFERRED_TYPE_LITERAL*/{3:"hello", "hello": 3};
   }
   {
     Map<dynamic, String> l0 = /*info:INFERRED_TYPE_LITERAL*/{};
@@ -2372,17 +2374,80 @@
 ''');
   }
 
+  void test_instanceField_basedOnInstanceField_betweenCycles() {
+    // Verify that all instance fields in one library cycle are inferred before
+    // an instance fields in a dependent library cycle.
+    addFile(
+        '''
+import 'b.dart';
+class A {
+  var x = new B().y;
+  var y = 0;
+}
+''',
+        name: '/a.dart');
+    addFile(
+        '''
+class B {
+  var x = new B().y;
+  var y = 0;
+}
+''',
+        name: '/b.dart');
+    checkFile('''
+import 'a.dart';
+import 'b.dart';
+main() {
+  new A().x = /*warning:INVALID_ASSIGNMENT*/'foo';
+  new B().x = 'foo';
+}
+''');
+  }
+
+  void test_instanceField_basedOnInstanceField_withinCycle() {
+    // Verify that all instance field inferences that occur within the same
+    // library cycle happen as though they occurred "all at once", so no
+    // instance field in the library cycle can inherit its type from another
+    // instance field in the same library cycle.
+    addFile(
+        '''
+import 'b.dart';
+class A {
+  var x = new B().y;
+  var y = 0;
+}
+''',
+        name: '/a.dart');
+    addFile(
+        '''
+import 'a.dart';
+class B {
+  var x = new A().y;
+  var y = 0;
+}
+''',
+        name: '/b.dart');
+    checkFile('''
+import 'a.dart';
+import 'b.dart';
+main() {
+  new A().x = 'foo';
+  new B().x = 'foo';
+}
+''');
+  }
+
   void test_listLiterals() {
     checkFile(r'''
 test1() {
-  var x = [1, 2, 3];
+  var x = /*info:INFERRED_TYPE_LITERAL*/[1, 2, 3];
   x.add(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/'hi');
   x.add(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/4.0);
   x.add(4);
   List<num> y = x;
 }
 test2() {
-  var x = [1, 2.0, 3];
+  var x = /*info:INFERRED_TYPE_LITERAL*/[1, 2.0, 3];
   x.add(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/'hi');
   x.add(4.0);
   List<int> y = /*info:ASSIGNMENT_CAST*/x;
@@ -2392,14 +2457,14 @@
 
   void test_listLiterals_topLevel() {
     checkFile(r'''
-var x1 = [1, 2, 3];
+var x1 = /*info:INFERRED_TYPE_LITERAL*/[1, 2, 3];
 test1() {
   x1.add(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/'hi');
   x1.add(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/4.0);
   x1.add(4);
   List<num> y = x1;
 }
-var x2 = [1, 2.0, 3];
+var x2 = /*info:INFERRED_TYPE_LITERAL*/[1, 2.0, 3];
 test2() {
   x2.add(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/'hi');
   x2.add(4.0);
@@ -2422,7 +2487,7 @@
   void test_mapLiterals() {
     checkFile(r'''
 test1() {
-  var x = { 1: 'x', 2: 'y' };
+  var x = /*info:INFERRED_TYPE_LITERAL*/{ 1: 'x', 2: 'y' };
   x[3] = 'z';
   x[/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/'hi'] = 'w';
   x[/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/4.0] = 'u';
@@ -2431,7 +2496,7 @@
 }
 
 test2() {
-  var x = { 1: 'x', 2: 'y', 3.0: new RegExp('.') };
+  var x = /*info:INFERRED_TYPE_LITERAL*/{ 1: 'x', 2: 'y', 3.0: new RegExp('.') };
   x[3] = 'z';
   x[/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/'hi'] = 'w';
   x[4.0] = 'u';
@@ -2445,7 +2510,7 @@
 
   void test_mapLiterals_topLevel() {
     checkFile(r'''
-var x1 = { 1: 'x', 2: 'y' };
+var x1 = /*info:INFERRED_TYPE_LITERAL*/{ 1: 'x', 2: 'y' };
 test1() {
   x1[3] = 'z';
   x1[/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/'hi'] = 'w';
@@ -2454,7 +2519,7 @@
   Map<num, String> y = x1;
 }
 
-var x2 = { 1: 'x', 2: 'y', 3.0: new RegExp('.') };
+var x2 = /*info:INFERRED_TYPE_LITERAL*/{ 1: 'x', 2: 'y', 3.0: new RegExp('.') };
 test2() {
   x2[3] = 'z';
   x2[/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/'hi'] = 'w';
diff --git a/pkg/analyzer/test/src/task/strong/test_all.dart b/pkg/analyzer/test/src/task/strong/test_all.dart
index be9a178..698e2ae 100644
--- a/pkg/analyzer/test/src/task/strong/test_all.dart
+++ b/pkg/analyzer/test/src/task/strong/test_all.dart
@@ -13,7 +13,7 @@
 /// Utility for manually running all tests.
 main() {
   initializeTestEnvironment();
-  group('task tests', () {
+  group('strong tests', () {
     checker_test.main();
     inferred_type_test.main();
   });
diff --git a/pkg/analyzer/test/src/task/strong_mode_test.dart b/pkg/analyzer/test/src/task/strong_mode_test.dart
index c4589f7..3f4a5a6 100644
--- a/pkg/analyzer/test/src/task/strong_mode_test.dart
+++ b/pkg/analyzer/test/src/task/strong_mode_test.dart
@@ -7,7 +7,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/dart/resolver/inheritance_manager.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/strong_mode.dart';
 import 'package:unittest/unittest.dart';
diff --git a/pkg/analyzer/tool/summary/dump_inferred_types.dart b/pkg/analyzer/tool/summary/dump_inferred_types.dart
new file mode 100644
index 0000000..0668513
--- /dev/null
+++ b/pkg/analyzer/tool/summary/dump_inferred_types.dart
@@ -0,0 +1,275 @@
+// 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:convert';
+import 'dart:io';
+
+import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/summary/base.dart';
+import 'package:analyzer/src/summary/idl.dart';
+
+/**
+ * Collect the inferred types from all the summary files listed in [args] and
+ * print them in alphabetical order.
+ */
+main(List<String> args) {
+  InferredTypeCollector collector = new InferredTypeCollector();
+  for (String arg in args) {
+    PackageBundle bundle =
+        new PackageBundle.fromBuffer(new File(arg).readAsBytesSync());
+    collector.visitPackageBundle(bundle);
+  }
+  collector.dumpCollectedTypes();
+}
+
+/**
+ * Visitor class that visits the contents of a summary file and collects the
+ * inferred types in it.
+ */
+class InferredTypeCollector {
+  UnlinkedUnit unlinkedUnit;
+  LinkedUnit linkedUnit;
+  final Map<String, String> inferredTypes = <String, String>{};
+  List<String> typeParamsInScope = <String>[];
+
+  /**
+   * If an inferred type exists matching the given [slot], record that it is the
+   * type of the entity reachable via [path].
+   */
+  void collectInferredType(int slot, String path) {
+    for (EntityRef type in linkedUnit.types) {
+      if (type.slot == slot) {
+        inferredTypes[path] = formatType(type);
+        return;
+      }
+    }
+  }
+
+  /**
+   * Collect the inferred type in summary object [obj] (if any), which is
+   * reachable via [path].
+   *
+   * This method may modify [properties] in order to affect how sub-elements
+   * are visited.
+   */
+  void collectInferredTypes(
+      SummaryClass obj, Map<String, Object> properties, String path) {
+    if (obj is UnlinkedVariable) {
+      collectInferredType(obj.inferredTypeSlot, path);
+    } else if (obj is UnlinkedExecutable) {
+      collectInferredType(obj.inferredReturnTypeSlot, path);
+    } else if (obj is UnlinkedParam) {
+      collectInferredType(obj.inferredTypeSlot, path);
+      // As a temporary measure, prevent recursion into the parameter's
+      // initializer, since AST-based type inference doesn't infer its type
+      // correctly yet.  TODO(paulberry): fix.
+      properties.remove('initializer');
+    }
+  }
+
+  /**
+   * Print out all the inferred types collected so far, in alphabetical order.
+   */
+  void dumpCollectedTypes() {
+    List<String> paths = inferredTypes.keys.toList();
+    paths.sort();
+    for (String path in paths) {
+      print('$path -> ${inferredTypes[path]}');
+    }
+  }
+
+  /**
+   * Interpret the given [param] as a parameter in a synthetic typedef, and
+   * format it as a string.
+   */
+  String formatParam(UnlinkedParam param) {
+    if (param.isFunctionTyped) {
+      // TODO(paulberry): fix this case.
+      return 'BAD(${JSON.encode(param)})';
+    }
+    String result;
+    if (param.type != null) {
+      result = '${formatType(param.type)} ${param.name}';
+    } else {
+      result = param.name;
+    }
+    if (param.kind == UnlinkedParamKind.named) {
+      result = '{$result}';
+    } else if (param.kind == UnlinkedParamKind.positional) {
+      result = '[$result]';
+    }
+    return result;
+  }
+
+  /**
+   * Convert the reference with index [index] into a string.  If [typeOf] is
+   * `true`, the reference is being used in the context of naming a type, so
+   * if the entity being referenced is not a type, it will be enclosed in
+   * `typeof()` for clarity.
+   */
+  String formatReference(int index, {bool typeOf: false}) {
+    LinkedReference linkedRef = linkedUnit.references[index];
+    switch (linkedRef.kind) {
+      case ReferenceKind.classOrEnum:
+      case ReferenceKind.function:
+      case ReferenceKind.propertyAccessor:
+      case ReferenceKind.topLevelFunction:
+      case ReferenceKind.method:
+      case ReferenceKind.typedef:
+      case ReferenceKind.prefix:
+      case ReferenceKind.topLevelPropertyAccessor:
+        break;
+      default:
+        // TODO(paulberry): fix this case.
+        return 'BAD(${JSON.encode(linkedRef.toJson())})';
+    }
+    int containingReference;
+    String name;
+    if (index < unlinkedUnit.references.length) {
+      containingReference = unlinkedUnit.references[index].prefixReference;
+      name = unlinkedUnit.references[index].name;
+    } else {
+      containingReference = linkedRef.containingReference;
+      name = linkedRef.name;
+    }
+    String result;
+    if (containingReference != 0) {
+      result = '${formatReference(containingReference)}.$name';
+    } else {
+      result = name;
+    }
+    if (linkedRef.kind == ReferenceKind.function) {
+      assert(name.isEmpty);
+      result += 'localFunction[${linkedRef.localIndex}]';
+    }
+    if (!typeOf ||
+        linkedRef.kind == ReferenceKind.classOrEnum ||
+        linkedRef.kind == ReferenceKind.typedef) {
+      return result;
+    } else {
+      return 'typeof($result)';
+    }
+  }
+
+  /**
+   * Interpret the given [entityRef] as a reference to a type, and format it as
+   * a string.
+   */
+  String formatType(EntityRef entityRef) {
+    List<int> implicitFunctionTypeIndices =
+        entityRef.implicitFunctionTypeIndices;
+    if (entityRef.syntheticReturnType != null) {
+      String params = entityRef.syntheticParams.map(formatParam).join(', ');
+      String retType = formatType(entityRef.syntheticReturnType);
+      return '($params) -> $retType';
+    }
+    if (entityRef.paramReference != 0) {
+      return typeParamsInScope[
+          typeParamsInScope.length - entityRef.paramReference];
+    }
+    String result = formatReference(entityRef.reference, typeOf: true);
+    if (entityRef.typeArguments.isNotEmpty) {
+      result += '<${entityRef.typeArguments.map(formatType).join(', ')}>';
+    }
+    if (implicitFunctionTypeIndices.isNotEmpty) {
+      result =
+          'parameterOf($result, ${implicitFunctionTypeIndices.join(', ')})';
+    }
+    return result;
+  }
+
+  /**
+   * Collect all the inferred types contained in [obj], which is reachable via
+   * [path].  [properties] is the result of calling `obj.toMap()`, and may be
+   * modified before returning.
+   */
+  void visit(SummaryClass obj, Map<String, Object> properties, String path) {
+    List<String> oldTypeParamsInScope = typeParamsInScope;
+    Object newTypeParams = properties['typeParameters'];
+    if (newTypeParams is List && newTypeParams.isNotEmpty) {
+      typeParamsInScope = typeParamsInScope.toList();
+      for (Object typeParam in newTypeParams) {
+        if (typeParam is UnlinkedTypeParam) {
+          typeParamsInScope.add(typeParam.name);
+        } else {
+          throw new StateError(
+              'Unexpected type param type: ${typeParam.runtimeType}');
+        }
+      }
+    }
+    collectInferredTypes(obj, properties, path);
+    properties.forEach((String key, Object value) {
+      if (value is SummaryClass) {
+        visit(value, value.toMap(), '$path.$key');
+      } else if (value is List) {
+        for (int i = 0; i < value.length; i++) {
+          Object item = value[i];
+          if (item is SummaryClass) {
+            Map<String, Object> itemProperties = item.toMap();
+            String indexOrName = itemProperties['name'] ?? i.toString();
+            visit(item, itemProperties, '$path.$key[$indexOrName]');
+          }
+        }
+      }
+    });
+    typeParamsInScope = oldTypeParamsInScope;
+  }
+
+  /**
+   * Collect all the inferred types contained in [bundle].
+   */
+  void visitPackageBundle(PackageBundle bundle) {
+    Map<String, LinkedLibrary> linkedLibraries = <String, LinkedLibrary>{};
+    Map<String, UnlinkedUnit> unlinkedUnits = <String, UnlinkedUnit>{};
+    for (int i = 0; i < bundle.linkedLibraryUris.length; i++) {
+      linkedLibraries[bundle.linkedLibraryUris[i]] = bundle.linkedLibraries[i];
+    }
+    for (int i = 0; i < bundle.unlinkedUnitUris.length; i++) {
+      unlinkedUnits[bundle.unlinkedUnitUris[i]] = bundle.unlinkedUnits[i];
+    }
+    // Figure out which unlinked units are a part of another library so we won't
+    // visit them redundantly.
+    Set<String> partOfUris = new Set<String>();
+    unlinkedUnits.forEach((String unitUriString, UnlinkedUnit unlinkedUnit) {
+      Uri unitUri = Uri.parse(unitUriString);
+      for (String relativePartUriString in unlinkedUnit.publicNamespace.parts) {
+        partOfUris.add(
+            resolveRelativeUri(unitUri, Uri.parse(relativePartUriString))
+                .toString());
+      }
+    });
+    linkedLibraries
+        .forEach((String libraryUriString, LinkedLibrary linkedLibrary) {
+      if (partOfUris.contains(libraryUriString)) {
+        return;
+      }
+      Uri libraryUri = Uri.parse(libraryUriString);
+      UnlinkedUnit definingUnlinkedUnit = unlinkedUnits[libraryUriString];
+      visitUnit(definingUnlinkedUnit, linkedLibrary.units[0], libraryUriString);
+      for (int i = 0;
+          i < definingUnlinkedUnit.publicNamespace.parts.length;
+          i++) {
+        Uri relativePartUri =
+            Uri.parse(definingUnlinkedUnit.publicNamespace.parts[i]);
+        String unitUriString =
+            resolveRelativeUri(libraryUri, relativePartUri).toString();
+        visitUnit(unlinkedUnits[unitUriString], linkedLibrary.units[i + 1],
+            libraryUriString);
+      }
+    });
+  }
+
+  /**
+   * Collect all the inferred types contained in the compilation unit described
+   * by [unlinkedUnit] and [linkedUnit], which has URI [libraryUriString].
+   */
+  void visitUnit(UnlinkedUnit unlinkedUnit, LinkedUnit linkedUnit,
+      String libraryUriString) {
+    this.unlinkedUnit = unlinkedUnit;
+    this.linkedUnit = linkedUnit;
+    visit(unlinkedUnit, unlinkedUnit.toMap(), libraryUriString);
+    this.unlinkedUnit = null;
+    this.linkedUnit = null;
+  }
+}
diff --git a/pkg/analyzer/tool/summary/inspect.dart b/pkg/analyzer/tool/summary/inspect.dart
new file mode 100644
index 0000000..eb0093d
--- /dev/null
+++ b/pkg/analyzer/tool/summary/inspect.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary/inspect.dart';
+import 'package:args/args.dart';
+
+main(List<String> args) {
+  ArgParser argParser = new ArgParser()..addFlag('raw');
+  ArgResults argResults = argParser.parse(args);
+  if (argResults.rest.length != 1) {
+    print(argParser.usage);
+    exitCode = 1;
+    return;
+  }
+  String path = argResults.rest[0];
+  List<int> bytes = new File(path).readAsBytesSync();
+  PackageBundle bundle = new PackageBundle.fromBuffer(bytes);
+  SummaryInspector inspector = new SummaryInspector(argResults['raw']);
+  print(inspector.dumpPackageBundle(bundle).join('\n'));
+}
diff --git a/pkg/analyzer/tool/task_dependency_graph/tasks.dot b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
index 4142a2a..75e8989 100644
--- a/pkg/analyzer/tool/task_dependency_graph/tasks.dot
+++ b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
@@ -172,7 +172,10 @@
   LINTS [shape=box]
   LibraryErrorsReadyTask -> LIBRARY_ERRORS_READY
   LibraryUnitErrorsTask -> LIBRARY_UNIT_ERRORS
+  MODIFICATION_TIME -> BuildDirectiveElementsTask
   MODIFICATION_TIME -> ParseDartTask
+  MODIFICATION_TIME -> ScanDartTask
+  MODIFICATION_TIME -> VerifyUnitTask
   MODIFICATION_TIME [shape=box]
   PARSED_UNIT -> BuildCompilationUnitElementTask
   PARSED_UNIT -> DartErrorsTask
@@ -193,6 +196,7 @@
   ParseDartTask -> LIBRARY_SPECIFIC_UNITS
   ParseDartTask -> PARSED_UNIT
   ParseDartTask -> PARSE_ERRORS
+  ParseDartTask -> REFERENCED_SOURCES
   ParseDartTask -> SOURCE_KIND
   ParseDartTask -> UNITS
   PartiallyResolveUnitReferencesTask -> CREATED_RESOLVED_UNIT6
@@ -217,6 +221,9 @@
   READY_RESOLVED_UNIT -> VerifyUnitTask
   READY_RESOLVED_UNIT [shape=box]
   REFERENCED_NAMES [shape=box]
+  REFERENCED_SOURCES -> BuildDirectiveElementsTask
+  REFERENCED_SOURCES -> VerifyUnitTask
+  REFERENCED_SOURCES [shape=box]
   RESOLVED_UNIT -> GenerateHintsTask
   RESOLVED_UNIT -> GenerateLintsTask
   RESOLVED_UNIT -> ReadyResolvedUnitTask
diff --git a/pkg/analyzer_cli/lib/src/analyzer_impl.dart b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
index 7314a20..b3e9398 100644
--- a/pkg/analyzer_cli/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
@@ -20,6 +20,7 @@
 import 'package:analyzer_cli/src/driver.dart';
 import 'package:analyzer_cli/src/error_formatter.dart';
 import 'package:analyzer_cli/src/options.dart';
+import 'package:path/path.dart' as pathos;
 
 /// The maximum number of sources for which AST structures should be kept in the cache.
 const int _maxCacheSize = 512;
@@ -179,11 +180,15 @@
 
   /// Returns true if we want to report diagnostics for this library.
   bool _isAnalyzedLibrary(LibraryElement library) {
-    switch (library.source.uriKind) {
+    Source source = library.source;
+    switch (source.uriKind) {
       case UriKind.DART_URI:
         return options.showSdkWarnings;
       case UriKind.PACKAGE_URI:
-        return _isAnalyzedPackage(library.source.uri);
+        if (_isPathInPubCache(source.fullName)) {
+          return false;
+        }
+        return _isAnalyzedPackage(source.uri);
       default:
         return true;
     }
@@ -194,7 +199,6 @@
     if (uri.scheme != 'package' || uri.pathSegments.isEmpty) {
       return false;
     }
-
     String packageName = uri.pathSegments.first;
     if (packageName == _selfPackageName) {
       return true;
@@ -328,6 +332,20 @@
 
     return new ProcessedSeverity(severity, isOverridden);
   }
+
+  /// Return `true` if the given [path] is in the Pub cache.
+  static bool _isPathInPubCache(String path) {
+    List<String> parts = pathos.split(path);
+    if (parts.contains('.pub-cache')) {
+      return true;
+    }
+    for (int i = 0; i < parts.length - 2; i++) {
+      if (parts[i] == 'Pub' && parts[i + 1] == 'Cache') {
+        return true;
+      }
+    }
+    return false;
+  }
 }
 
 /// This [Logger] prints out information comments to [outSink] and error messages
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index 511c6c0..e60ec09 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -28,10 +28,93 @@
 import 'package:analyzer_cli/src/driver.dart';
 import 'package:analyzer_cli/src/error_formatter.dart';
 import 'package:analyzer_cli/src/options.dart';
-import 'package:protobuf/protobuf.dart';
+import 'package:bazel_worker/bazel_worker.dart';
 
-import 'message_grouper.dart';
-import 'worker_protocol.pb.dart';
+/**
+ * Persistent Bazel worker.
+ */
+class AnalyzerWorkerLoop extends SyncWorkerLoop {
+  final StringBuffer errorBuffer = new StringBuffer();
+  final StringBuffer outBuffer = new StringBuffer();
+
+  final String dartSdkPath;
+
+  AnalyzerWorkerLoop(SyncWorkerConnection connection, {this.dartSdkPath})
+      : super(connection: connection);
+
+  factory AnalyzerWorkerLoop.std(
+      {io.Stdin stdinStream, io.Stdout stdoutStream, String dartSdkPath}) {
+    SyncWorkerConnection connection = new StdSyncWorkerConnection(
+        stdinStream: stdinStream, stdoutStream: stdoutStream);
+    return new AnalyzerWorkerLoop(connection, dartSdkPath: dartSdkPath);
+  }
+
+  /**
+   * Performs analysis with given [options].
+   */
+  void analyze(CommandLineOptions options) {
+    new BuildMode(options, new AnalysisStats()).analyze();
+    AnalysisEngine.instance.clearCaches();
+  }
+
+  /**
+   * Perform a single loop step.
+   */
+  WorkResponse performRequest(WorkRequest request) {
+    errorBuffer.clear();
+    outBuffer.clear();
+    try {
+      // Add in the dart-sdk argument if `dartSdkPath` is not null, otherwise it
+      // will try to find the currently installed sdk.
+      var arguments = new List.from(request.arguments);
+      if (dartSdkPath != null &&
+          !arguments.any((arg) => arg.startsWith('--dart-sdk'))) {
+        arguments.add('--dart-sdk=$dartSdkPath');
+      }
+      // Prepare options.
+      CommandLineOptions options =
+          CommandLineOptions.parse(arguments, (String msg) {
+        throw new ArgumentError(msg);
+      });
+      // Analyze and respond.
+      analyze(options);
+      String msg = _getErrorOutputBuffersText();
+      return new WorkResponse()
+        ..exitCode = EXIT_CODE_OK
+        ..output = msg;
+    } catch (e, st) {
+      String msg = _getErrorOutputBuffersText();
+      msg += '$e\n$st';
+      return new WorkResponse()
+        ..exitCode = EXIT_CODE_ERROR
+        ..output = msg;
+    }
+  }
+
+  /**
+   * Run the worker loop.
+   */
+  @override
+  void run() {
+    errorSink = errorBuffer;
+    outSink = outBuffer;
+    exitHandler = (int exitCode) {
+      return throw new StateError('Exit called: $exitCode');
+    };
+    super.run();
+  }
+
+  String _getErrorOutputBuffersText() {
+    String msg = '';
+    if (errorBuffer.isNotEmpty) {
+      msg += errorBuffer.toString() + '\n';
+    }
+    if (outBuffer.isNotEmpty) {
+      msg += outBuffer.toString() + '\n';
+    }
+    return msg;
+  }
+}
 
 /**
  * Analyzer used when the "--build-mode" option is supplied.
@@ -46,7 +129,7 @@
   Map<Uri, JavaFile> uriToFileMap;
   final List<Source> explicitSources = <Source>[];
 
-  PackageBundleAssembler assembler = new PackageBundleAssembler();
+  PackageBundleAssembler assembler;
   final Set<Source> processedSources = new Set<Source>();
   final Map<Uri, UnlinkedUnit> uriToUnit = <Uri, UnlinkedUnit>{};
 
@@ -97,6 +180,8 @@
     }
 
     // Write summary.
+    assembler = new PackageBundleAssembler(
+        excludeHashes: options.buildSummaryExcludeInformative);
     if (options.buildSummaryOutput != null) {
       if (options.buildSummaryOnlyAst && !options.buildSummaryFallback) {
         _serializeAstBasedSummary(explicitSources);
@@ -120,7 +205,6 @@
       PackageBundleBuilder sdkBundle = assembler.assemble();
       if (options.buildSummaryExcludeInformative) {
         sdkBundle.flushInformative();
-        sdkBundle.unlinkedUnitHashes = null;
       }
       io.File file = new io.File(options.buildSummaryOutput);
       file.writeAsBytesSync(sdkBundle.toBuffer(), mode: io.FileMode.WRITE_ONLY);
@@ -157,7 +241,7 @@
         new DirectoryBasedDartSdk(new JavaFile(options.dartSdkPath));
     sdk.analysisOptions =
         Driver.createAnalysisOptionsForCommandLineOptions(options);
-    sdk.useSummary = true;
+    sdk.useSummary = !options.buildSummaryOnlyAst;
 
     // Read the summaries.
     summaryDataStore = new SummaryDataStore(options.buildSummaryInputs);
@@ -183,10 +267,12 @@
       }
     });
 
-    // Configure using summaries.
-    context.typeProvider = sdk.context.typeProvider;
-    context.resultProvider =
-        new InputPackagesResultProvider(context, summaryDataStore);
+    if (!options.buildSummaryOnlyAst) {
+      // Configure using summaries.
+      context.typeProvider = sdk.context.typeProvider;
+      context.resultProvider =
+          new InputPackagesResultProvider(context, summaryDataStore);
+    }
   }
 
   /**
@@ -273,142 +359,3 @@
     return uriToFileMap;
   }
 }
-
-/**
- * Default implementation of [WorkerConnection] that works with stdio.
- */
-class StdWorkerConnection implements WorkerConnection {
-  final MessageGrouper _messageGrouper;
-  final io.Stdout _stdoutStream;
-
-  StdWorkerConnection(io.Stdin stdinStream, this._stdoutStream)
-      : _messageGrouper = new MessageGrouper(stdinStream);
-
-  @override
-  WorkRequest readRequest() {
-    var buffer = _messageGrouper.next;
-    if (buffer == null) return null;
-
-    return new WorkRequest.fromBuffer(buffer);
-  }
-
-  @override
-  void writeResponse(WorkResponse response) {
-    var responseBuffer = response.writeToBuffer();
-
-    var writer = new CodedBufferWriter();
-    writer.writeInt32NoTag(responseBuffer.length);
-    writer.writeRawBytes(responseBuffer);
-
-    _stdoutStream.add(writer.toBuffer());
-  }
-}
-
-/**
- * Connection between a worker and input / output.
- */
-abstract class WorkerConnection {
-  /**
-   * Read a new [WorkRequest]. Returns [null] when there are no more requests.
-   */
-  WorkRequest readRequest();
-
-  /**
-   * Write the given [response] as bytes to the output.
-   */
-  void writeResponse(WorkResponse response);
-}
-
-/**
- * Persistent Bazel worker.
- */
-class WorkerLoop {
-  static const int EXIT_CODE_OK = 0;
-  static const int EXIT_CODE_ERROR = 15;
-
-  final WorkerConnection connection;
-
-  final StringBuffer errorBuffer = new StringBuffer();
-  final StringBuffer outBuffer = new StringBuffer();
-
-  final String dartSdkPath;
-
-  WorkerLoop(this.connection, {this.dartSdkPath});
-
-  factory WorkerLoop.std(
-      {io.Stdin stdinStream, io.Stdout stdoutStream, String dartSdkPath}) {
-    stdinStream ??= io.stdin;
-    stdoutStream ??= io.stdout;
-    WorkerConnection connection =
-        new StdWorkerConnection(stdinStream, stdoutStream);
-    return new WorkerLoop(connection, dartSdkPath: dartSdkPath);
-  }
-
-  /**
-   * Performs analysis with given [options].
-   */
-  void analyze(CommandLineOptions options) {
-    options.dartSdkPath ??= dartSdkPath;
-    new BuildMode(options, new AnalysisStats()).analyze();
-  }
-
-  /**
-   * Perform a single loop step.  Return `true` if should exit the loop.
-   */
-  bool performSingle() {
-    try {
-      WorkRequest request = connection.readRequest();
-      if (request == null) {
-        return true;
-      }
-      // Prepare options.
-      CommandLineOptions options =
-          CommandLineOptions.parse(request.arguments, (String msg) {
-        throw new ArgumentError(msg);
-      });
-      // Analyze and respond.
-      analyze(options);
-      String msg = _getErrorOutputBuffersText();
-      connection.writeResponse(new WorkResponse()
-        ..exitCode = EXIT_CODE_OK
-        ..output = msg);
-    } catch (e, st) {
-      String msg = _getErrorOutputBuffersText();
-      msg += '$e \n $st';
-      connection.writeResponse(new WorkResponse()
-        ..exitCode = EXIT_CODE_ERROR
-        ..output = msg);
-    }
-    return false;
-  }
-
-  /**
-   * Run the worker loop.
-   */
-  void run() {
-    errorSink = errorBuffer;
-    outSink = outBuffer;
-    exitHandler = (int exitCode) {
-      return throw new StateError('Exit called: $exitCode');
-    };
-    while (true) {
-      errorBuffer.clear();
-      outBuffer.clear();
-      bool shouldExit = performSingle();
-      if (shouldExit) {
-        break;
-      }
-    }
-  }
-
-  String _getErrorOutputBuffersText() {
-    String msg = '';
-    if (errorBuffer.isNotEmpty) {
-      msg += errorBuffer.toString() + '\n';
-    }
-    if (outBuffer.isNotEmpty) {
-      msg += outBuffer.toString() + '\n';
-    }
-    return msg;
-  }
-}
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index a05f81e..6a67547 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -245,7 +245,7 @@
   ErrorSeverity _buildModeAnalyze(CommandLineOptions options) {
     return _analyzeAllTag.makeCurrentWhile(() {
       if (options.buildModePersistentWorker) {
-        new WorkerLoop.std(dartSdkPath: options.dartSdkPath).run();
+        new AnalyzerWorkerLoop.std(dartSdkPath: options.dartSdkPath).run();
       } else {
         return new BuildMode(options, stats).analyze();
       }
@@ -298,10 +298,6 @@
     if (options.enableSuperMixins != _previousOptions.enableSuperMixins) {
       return false;
     }
-    if (options.enableConditionalDirectives !=
-        _previousOptions.enableConditionalDirectives) {
-      return false;
-    }
     return true;
   }
 
@@ -603,8 +599,6 @@
     contextOptions.hint = !options.disableHints;
     contextOptions.enableStrictCallChecks = options.enableStrictCallChecks;
     contextOptions.enableSuperMixins = options.enableSuperMixins;
-    contextOptions.enableConditionalDirectives =
-        options.enableConditionalDirectives;
     contextOptions.generateImplicitErrors = options.showPackageWarnings;
     contextOptions.generateSdkErrors = options.showSdkWarnings;
     contextOptions.lint = options.lints;
diff --git a/pkg/analyzer_cli/lib/src/message_grouper.dart b/pkg/analyzer_cli/lib/src/message_grouper.dart
deleted file mode 100644
index 8696796..0000000
--- a/pkg/analyzer_cli/lib/src/message_grouper.dart
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:io';
-import 'dart:typed_data';
-
-/// Groups stdin input into messages by interpreting it as
-/// base-128 encoded lengths interleaved with raw data.
-///
-/// The base-128 encoding is in little-endian order, with the high bit set on
-/// all bytes but the last.  This was chosen since it's the same as the
-/// base-128 encoding used by protobufs, so it allows a modest amount of code
-/// reuse at the other end of the protocol.
-///
-/// Possible future improvements to consider (should a debugging need arise):
-/// - Put a magic number at the beginning of the stream.
-/// - Use a guard byte between messages to sanity check that the encoder and
-///   decoder agree on the encoding of lengths.
-class MessageGrouper {
-  final _state = new _MessageGrouperState();
-  final Stdin _stdin;
-
-  MessageGrouper(this._stdin);
-
-  /// Blocks until the next full message is received, and then returns it.
-  ///
-  /// Returns null at end of file.
-  List<int> get next {
-    var message;
-    while (message == null) {
-    var nextByte = _stdin.readByteSync();
-    if (nextByte == -1) return null;
-      message = _state.handleInput(nextByte);
-    }
-    return message;
-  }
-}
-
-/// State held by the [MessageGrouper] while waiting for additional data to
-/// arrive.
-class _MessageGrouperState {
-  /// `true` means we are waiting to receive bytes of base-128 encoded length.
-  /// Some bytes of length may have been received already.
-  ///
-  /// `false` means we are waiting to receive more bytes of message data.  Some
-  /// bytes of message data may have been received already.
-  bool waitingForLength = true;
-
-  /// If [waitingForLength] is `true`, the decoded value of the length bytes
-  /// received so far (if any).  If [waitingForLength] is `false`, the decoded
-  /// length that was most recently received.
-  int length = 0;
-
-  /// If [waitingForLength] is `true`, the amount by which the next received
-  /// length byte must be left-shifted; otherwise undefined.
-  int lengthShift = 0;
-
-  /// If [waitingForLength] is `false`, a [Uint8List] which is ready to receive
-  /// message data.  Otherwise null.
-  Uint8List message;
-
-  /// If [waitingForLength] is `false`, the number of message bytes that have
-  /// been received so far.  Otherwise zero.
-  int numMessageBytesReceived;
-
-  _MessageGrouperState() {
-    reset();
-  }
-
-  /// Handle one byte at a time.
-  ///
-  /// Returns a [List<int>] of message bytes if [byte] was the last byte in a
-  /// message, otherwise returns [null].
-  List<int> handleInput(int byte) {
-    if (waitingForLength) {
-      length |= (byte & 0x7f) << lengthShift;
-      if ((byte & 0x80) == 0) {
-        waitingForLength = false;
-        message = new Uint8List(length);
-        if (length == 0) {
-          // There is no message data to wait for, so just go ahead and deliver the
-          // empty message.
-          var messageToReturn = message;
-          reset();
-          return messageToReturn;
-        }
-      } else {
-        lengthShift += 7;
-      }
-    } else {
-      message[numMessageBytesReceived] = byte;
-      numMessageBytesReceived++;
-      if (numMessageBytesReceived == length) {
-        var messageToReturn = message;
-        reset();
-        return messageToReturn;
-      }
-    }
-    return null;
-  }
-
-  /// Reset the state so that we are ready to receive the next base-128 encoded
-  /// length.
-  void reset() {
-    waitingForLength = true;
-    length = 0;
-    lengthShift = 0;
-    message = null;
-    numMessageBytesReceived = 0;
-  }
-}
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index fc778f4..3f26109 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -80,9 +80,6 @@
   /// Whether to display version information
   final bool displayVersion;
 
-  /// Whether to enable conditional directives (DEP 40).
-  final bool enableConditionalDirectives;
-
   /// Whether to enable null-aware operators (DEP 9).
   final bool enableNullAwareOperators;
 
@@ -166,7 +163,6 @@
         analysisOptionsFile = args['options'],
         disableHints = args['no-hints'],
         displayVersion = args['version'],
-        enableConditionalDirectives = args['enable-conditional-directives'],
         enableNullAwareOperators = args['enable-null-aware-operators'],
         enableStrictCallChecks = args['enable-strict-call-checks'],
         enableSuperMixins = args['supermixin'],
@@ -419,7 +415,8 @@
           negatable: false,
           hide: true)
       ..addFlag('enable-conditional-directives',
-          help: 'Enable support for conditional directives (DEP 40).',
+          help:
+              'deprecated -- Enable support for conditional directives (DEP 40).',
           defaultsTo: false,
           negatable: false,
           hide: true)
@@ -434,7 +431,7 @@
           negatable: false,
           hide: true)
       ..addFlag('enable-new-task-model',
-          help: 'Ennable new task model.',
+          help: 'deprecated -- Ennable new task model.',
           defaultsTo: false,
           negatable: false,
           hide: true)
diff --git a/pkg/analyzer_cli/lib/src/perf_report.dart b/pkg/analyzer_cli/lib/src/perf_report.dart
index f92ae9a..452b2ff 100644
--- a/pkg/analyzer_cli/lib/src/perf_report.dart
+++ b/pkg/analyzer_cli/lib/src/perf_report.dart
@@ -5,7 +5,7 @@
 library analyzer_cli.src.perf_report;
 
 import 'dart:convert' show JsonEncoder;
-import 'dart:io' show File, Platform;
+import 'dart:io' show Platform;
 
 import 'package:analyzer/src/generated/utilities_general.dart'
     show PerformanceTag;
diff --git a/pkg/analyzer_cli/lib/src/worker_protocol.pb.dart b/pkg/analyzer_cli/lib/src/worker_protocol.pb.dart
deleted file mode 100755
index 908dfac..0000000
--- a/pkg/analyzer_cli/lib/src/worker_protocol.pb.dart
+++ /dev/null
@@ -1,133 +0,0 @@
-///
-//  Generated code. Do not modify.
-///
-library blaze.worker_worker_protocol;
-
-import 'package:protobuf/protobuf.dart';
-
-class Input extends GeneratedMessage {
-  static final BuilderInfo _i = new BuilderInfo('Input')
-    ..a(1, 'path', PbFieldType.OS)
-    ..a(2, 'digest', PbFieldType.OY)
-    ..hasRequiredFields = false
-  ;
-
-  Input() : super();
-  Input.fromBuffer(List<int> i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r);
-  Input.fromJson(String i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) : super.fromJson(i, r);
-  Input clone() => new Input()..mergeFromMessage(this);
-  BuilderInfo get info_ => _i;
-  static Input create() => new Input();
-  static PbList<Input> createRepeated() => new PbList<Input>();
-  static Input getDefault() {
-    if (_defaultInstance == null) _defaultInstance = new _ReadonlyInput();
-    return _defaultInstance;
-  }
-  static Input _defaultInstance;
-  static void $checkItem(Input v) {
-    if (v is !Input) checkItemFailed(v, 'Input');
-  }
-
-  String get path => $_get(0, 1, '');
-  void set path(String v) { $_setString(0, 1, v); }
-  bool hasPath() => $_has(0, 1);
-  void clearPath() => clearField(1);
-
-  List<int> get digest => $_get(1, 2, null);
-  void set digest(List<int> v) { $_setBytes(1, 2, v); }
-  bool hasDigest() => $_has(1, 2);
-  void clearDigest() => clearField(2);
-}
-
-class _ReadonlyInput extends Input with ReadonlyMessageMixin {}
-
-class WorkRequest extends GeneratedMessage {
-  static final BuilderInfo _i = new BuilderInfo('WorkRequest')
-    ..p(1, 'arguments', PbFieldType.PS)
-    ..pp(2, 'inputs', PbFieldType.PM, Input.$checkItem, Input.create)
-    ..hasRequiredFields = false
-  ;
-
-  WorkRequest() : super();
-  WorkRequest.fromBuffer(List<int> i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r);
-  WorkRequest.fromJson(String i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) : super.fromJson(i, r);
-  WorkRequest clone() => new WorkRequest()..mergeFromMessage(this);
-  BuilderInfo get info_ => _i;
-  static WorkRequest create() => new WorkRequest();
-  static PbList<WorkRequest> createRepeated() => new PbList<WorkRequest>();
-  static WorkRequest getDefault() {
-    if (_defaultInstance == null) _defaultInstance = new _ReadonlyWorkRequest();
-    return _defaultInstance;
-  }
-  static WorkRequest _defaultInstance;
-  static void $checkItem(WorkRequest v) {
-    if (v is !WorkRequest) checkItemFailed(v, 'WorkRequest');
-  }
-
-  List<String> get arguments => $_get(0, 1, null);
-
-  List<Input> get inputs => $_get(1, 2, null);
-}
-
-class _ReadonlyWorkRequest extends WorkRequest with ReadonlyMessageMixin {}
-
-class WorkResponse extends GeneratedMessage {
-  static final BuilderInfo _i = new BuilderInfo('WorkResponse')
-    ..a(1, 'exitCode', PbFieldType.O3)
-    ..a(2, 'output', PbFieldType.OS)
-    ..hasRequiredFields = false
-  ;
-
-  WorkResponse() : super();
-  WorkResponse.fromBuffer(List<int> i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r);
-  WorkResponse.fromJson(String i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) : super.fromJson(i, r);
-  WorkResponse clone() => new WorkResponse()..mergeFromMessage(this);
-  BuilderInfo get info_ => _i;
-  static WorkResponse create() => new WorkResponse();
-  static PbList<WorkResponse> createRepeated() => new PbList<WorkResponse>();
-  static WorkResponse getDefault() {
-    if (_defaultInstance == null) _defaultInstance = new _ReadonlyWorkResponse();
-    return _defaultInstance;
-  }
-  static WorkResponse _defaultInstance;
-  static void $checkItem(WorkResponse v) {
-    if (v is !WorkResponse) checkItemFailed(v, 'WorkResponse');
-  }
-
-  int get exitCode => $_get(0, 1, 0);
-  void set exitCode(int v) { $_setUnsignedInt32(0, 1, v); }
-  bool hasExitCode() => $_has(0, 1);
-  void clearExitCode() => clearField(1);
-
-  String get output => $_get(1, 2, '');
-  void set output(String v) { $_setString(1, 2, v); }
-  bool hasOutput() => $_has(1, 2);
-  void clearOutput() => clearField(2);
-}
-
-class _ReadonlyWorkResponse extends WorkResponse with ReadonlyMessageMixin {}
-
-const Input$json = const {
-  '1': 'Input',
-  '2': const [
-    const {'1': 'path', '3': 1, '4': 1, '5': 9},
-    const {'1': 'digest', '3': 2, '4': 1, '5': 12},
-  ],
-};
-
-const WorkRequest$json = const {
-  '1': 'WorkRequest',
-  '2': const [
-    const {'1': 'arguments', '3': 1, '4': 3, '5': 9},
-    const {'1': 'inputs', '3': 2, '4': 3, '5': 11, '6': '.blaze.worker.Input'},
-  ],
-};
-
-const WorkResponse$json = const {
-  '1': 'WorkResponse',
-  '2': const [
-    const {'1': 'exit_code', '3': 1, '4': 1, '5': 5},
-    const {'1': 'output', '3': 2, '4': 1, '5': 9},
-  ],
-};
-
diff --git a/pkg/analyzer_cli/pubspec.yaml b/pkg/analyzer_cli/pubspec.yaml
index a1b2fe8..dbccd97 100644
--- a/pkg/analyzer_cli/pubspec.yaml
+++ b/pkg/analyzer_cli/pubspec.yaml
@@ -8,6 +8,7 @@
 dependencies:
   analyzer: ^0.27.0
   args: ^0.13.0
+  bazel_worker: ^0.1.0
   cli_util: ^0.0.1
   linter: ^0.1.10
   package_config: ^0.1.1
diff --git a/pkg/analyzer_cli/test/all.dart b/pkg/analyzer_cli/test/all.dart
index 05d8a98..13f72d1 100644
--- a/pkg/analyzer_cli/test/all.dart
+++ b/pkg/analyzer_cli/test/all.dart
@@ -6,7 +6,6 @@
 import 'build_mode_test.dart' as build_mode_test;
 import 'driver_test.dart' as driver;
 import 'error_test.dart' as error;
-import 'message_grouper_test.dart' as message_grouper;
 import 'options_test.dart' as options;
 import 'package_prefix_test.dart' as package_prefix;
 import 'perf_report_test.dart' as perf;
@@ -25,7 +24,6 @@
   //sdk_ext.main();
   //strong_mode.main();
   error.main();
-  message_grouper.main();
   options.main();
   perf.main();
   plugin_manager.main();
diff --git a/pkg/analyzer_cli/test/build_mode_test.dart b/pkg/analyzer_cli/test/build_mode_test.dart
index dcc2423..9c88a0f 100644
--- a/pkg/analyzer_cli/test/build_mode_test.dart
+++ b/pkg/analyzer_cli/test/build_mode_test.dart
@@ -4,35 +4,28 @@
 
 library analyzer_cli.test.built_mode;
 
-import 'dart:collection';
-import 'dart:convert';
-import 'dart:io';
-
 import 'package:analyzer_cli/src/build_mode.dart';
 import 'package:analyzer_cli/src/driver.dart';
 import 'package:analyzer_cli/src/options.dart';
-import 'package:analyzer_cli/src/worker_protocol.pb.dart';
+import 'package:bazel_worker/bazel_worker.dart';
+import 'package:bazel_worker/testing.dart';
 import 'package:protobuf/protobuf.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'package:typed_mock/typed_mock.dart';
 import 'package:unittest/unittest.dart';
 
-import 'utils.dart';
-
 main() {
   defineReflectiveTests(WorkerLoopTest);
 }
 
-typedef void _TestWorkerLoopAnalyze(CommandLineOptions options);
-
 @reflectiveTest
 class WorkerLoopTest {
-  final TestStdinStream stdinStream = new TestStdinStream();
+  final TestStdinSync stdinStream = new TestStdinSync();
   final TestStdoutStream stdoutStream = new TestStdoutStream();
-  _TestWorkerConnection connection;
+  TestSyncWorkerConnection connection;
 
   WorkerLoopTest() {
-    connection = new _TestWorkerConnection(this.stdinStream, this.stdoutStream);
+    connection =
+        new TestSyncWorkerConnection(this.stdinStream, this.stdoutStream);
   }
 
   void setUp() {}
@@ -56,8 +49,9 @@
       'package:foo/bar.dart|/inputs/foo/lib/bar.dart',
     ]);
     stdinStream.addInputBytes(_serializeProto(request));
+    stdinStream.close();
 
-    new _TestWorkerLoop(connection, (CommandLineOptions options) {
+    new TestAnalyzerWorkerLoop(connection, (CommandLineOptions options) {
       expect(options.buildSummaryInputs,
           unorderedEquals(['/tmp/1.sum', '/tmp/2.sum']));
       expect(
@@ -71,10 +65,10 @@
       outSink.writeln('outSink b');
       errorSink.writeln('errorSink b');
     }).run();
-    expect(connection.outputList, hasLength(1));
+    expect(connection.responses, hasLength(1));
 
-    var response = connection.outputList[0];
-    expect(response.exitCode, WorkerLoop.EXIT_CODE_OK);
+    var response = connection.responses[0];
+    expect(response.exitCode, EXIT_CODE_OK, reason: response.output);
     expect(
         response.output,
         allOf(contains('errorSink a'), contains('errorSink a'),
@@ -89,64 +83,53 @@
     var request = new WorkRequest();
     request.arguments.addAll(['--unknown-option', '/foo.dart', '/bar.dart']);
     stdinStream.addInputBytes(_serializeProto(request));
-    new _TestWorkerLoop(connection).run();
-    expect(connection.outputList, hasLength(1));
+    stdinStream.close();
+    new TestAnalyzerWorkerLoop(connection).run();
+    expect(connection.responses, hasLength(1));
 
-    var response = connection.outputList[0];
-    expect(response.exitCode, WorkerLoop.EXIT_CODE_ERROR);
+    var response = connection.responses[0];
+    expect(response.exitCode, EXIT_CODE_ERROR);
     expect(response.output, anything);
   }
 
   test_run_invalidRequest_noArgumentsInputs() {
     stdinStream.addInputBytes(_serializeProto(new WorkRequest()));
+    stdinStream.close();
 
-    new _TestWorkerLoop(connection).run();
-    expect(connection.outputList, hasLength(1));
+    new TestAnalyzerWorkerLoop(connection).run();
+    expect(connection.responses, hasLength(1));
 
-    var response = connection.outputList[0];
-    expect(response.exitCode, WorkerLoop.EXIT_CODE_ERROR);
+    var response = connection.responses[0];
+    expect(response.exitCode, EXIT_CODE_ERROR);
     expect(response.output, anything);
   }
 
   test_run_invalidRequest_randomBytes() {
     stdinStream.addInputBytes([1, 2, 3]);
-    new _TestWorkerLoop(connection).run();
-    expect(connection.outputList, hasLength(1));
+    stdinStream.close();
+    new TestAnalyzerWorkerLoop(connection).run();
+    expect(connection.responses, hasLength(1));
 
-    var response = connection.outputList[0];
-    expect(response.exitCode, WorkerLoop.EXIT_CODE_ERROR);
+    var response = connection.responses[0];
+    expect(response.exitCode, EXIT_CODE_ERROR);
     expect(response.output, anything);
   }
 
   test_run_stopAtEOF() {
-    stdinStream.addInputBytes([-1]);
-    new _TestWorkerLoop(connection).run();
+    stdinStream.close();
+    new TestAnalyzerWorkerLoop(connection).run();
   }
 }
 
-/**
- * A [StdWorkerConnection] which records its responses.
- */
-class _TestWorkerConnection extends StdWorkerConnection {
-  final outputList = <WorkResponse>[];
-
-  _TestWorkerConnection(Stdin stdinStream, Stdout stdoutStream)
-      : super(stdinStream, stdoutStream);
-
-  @override
-  void writeResponse(WorkResponse response) {
-    super.writeResponse(response);
-    outputList.add(response);
-  }
-}
+typedef void _TestWorkerLoopAnalyze(CommandLineOptions options);
 
 /**
- * [WorkerLoop] for testing.
+ * [AnalyzerWorkerLoop] for testing.
  */
-class _TestWorkerLoop extends WorkerLoop {
+class TestAnalyzerWorkerLoop extends AnalyzerWorkerLoop {
   final _TestWorkerLoopAnalyze _analyze;
 
-  _TestWorkerLoop(WorkerConnection connection, [this._analyze])
+  TestAnalyzerWorkerLoop(SyncWorkerConnection connection, [this._analyze])
       : super(connection);
 
   @override
diff --git a/pkg/analyzer_cli/test/message_grouper_test.dart b/pkg/analyzer_cli/test/message_grouper_test.dart
deleted file mode 100644
index 6388f9b..0000000
--- a/pkg/analyzer_cli/test/message_grouper_test.dart
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer_cli/src/message_grouper.dart';
-import 'package:unittest/unittest.dart';
-
-import 'utils.dart';
-
-main() {
-  MessageGrouper messageGrouper;
-  TestStdinStream stdinStream;
-
-  setUp(() {
-    stdinStream = new TestStdinStream();
-    messageGrouper = new MessageGrouper(stdinStream);
-  });
-
-  group('message_grouper', () {
-    /// Check that if the message grouper produces the [expectedOutput] in
-    /// response to the corresponding [input].
-    void check(List<int> input, List<List<int>> expectedOutput) {
-      stdinStream.addInputBytes(input);
-      for (var chunk in expectedOutput) {
-        expect(messageGrouper.next, equals(chunk));
-      }
-    }
-
-    /// Make a simple message having the given [length]
-    List<int> makeMessage(int length) {
-      var result = <int>[];
-      for (int i = 0; i < length; i++) {
-        result.add(i & 0xff);
-      }
-      return result;
-    }
-
-    test('Empty message', () {
-      check([0], [[]]);
-    });
-
-    test('Short message', () {
-      check([
-        5,
-        10,
-        20,
-        30,
-        40,
-        50
-      ], [
-        [10, 20, 30, 40, 50]
-      ]);
-    });
-
-    test('Message with 2-byte length', () {
-      var len = 0x155;
-      var msg = makeMessage(len);
-      var encodedLen = [0xd5, 0x02];
-      check([]..addAll(encodedLen)..addAll(msg), [msg]);
-    });
-
-    test('Message with 3-byte length', () {
-      var len = 0x4103;
-      var msg = makeMessage(len);
-      var encodedLen = [0x83, 0x82, 0x01];
-      check([]..addAll(encodedLen)..addAll(msg), [msg]);
-    });
-
-    test('Multiple messages', () {
-      check([
-        2,
-        10,
-        20,
-        2,
-        30,
-        40
-      ], [
-        [10, 20],
-        [30, 40]
-      ]);
-    });
-
-    test('Empty message at start', () {
-      check([
-        0,
-        2,
-        10,
-        20
-      ], [
-        [],
-        [10, 20]
-      ]);
-    });
-
-    test('Empty message at end', () {
-      check([
-        2,
-        10,
-        20,
-        0
-      ], [
-        [10, 20],
-        []
-      ]);
-    });
-
-    test('Empty message in the middle', () {
-      check([
-        2,
-        10,
-        20,
-        0,
-        2,
-        30,
-        40
-      ], [
-        [10, 20],
-        [],
-        [30, 40]
-      ]);
-    });
-  });
-}
diff --git a/pkg/analyzer_cli/test/options_test.dart b/pkg/analyzer_cli/test/options_test.dart
index 6b546a6..620c047 100644
--- a/pkg/analyzer_cli/test/options_test.dart
+++ b/pkg/analyzer_cli/test/options_test.dart
@@ -32,7 +32,6 @@
         expect(options.displayVersion, isFalse);
         expect(options.enableStrictCallChecks, isFalse);
         expect(options.enableSuperMixins, isFalse);
-        expect(options.enableConditionalDirectives, isFalse);
         expect(options.enableTypeChecks, isFalse);
         expect(options.hintsAreFatal, isFalse);
         expect(options.ignoreUnrecognizedFlags, isFalse);
diff --git a/pkg/analyzer_cli/test/utils.dart b/pkg/analyzer_cli/test/utils.dart
index ce71009b..07dbe4b 100644
--- a/pkg/analyzer_cli/test/utils.dart
+++ b/pkg/analyzer_cli/test/utils.dart
@@ -4,7 +4,6 @@
 
 library analyzer_cli.test.utils;
 
-import 'dart:collection';
 import 'dart:io';
 import 'dart:mirrors';
 
@@ -12,7 +11,6 @@
 import 'package:analyzer/src/generated/java_io.dart';
 import 'package:path/path.dart' as pathos;
 import 'package:path/path.dart' as path;
-import 'package:typed_mock/typed_mock.dart';
 import 'package:unittest/unittest.dart';
 
 /// Gets the test directory in a way that works with
@@ -65,37 +63,3 @@
 }
 
 class _TestUtils {}
-
-/**
- * A [Stdin] mock.
- */
-class TestStdinStream extends TypedMock implements Stdin {
-  final pendingBytes = new Queue<int>();
-
-  // Adds all the input bytes to this stream.
-  void addInputBytes(List<int> bytes) {
-    pendingBytes.addAll(bytes);
-  }
-
-  @override
-  int readByteSync() {
-    if (pendingBytes.isEmpty) {
-      return -1;
-    } else {
-      return pendingBytes.removeFirst();
-    }
-  }
-}
-
-/**
- * A [Stdout] mock.
- */
-class TestStdoutStream extends TypedMock implements Stdout {
-  final writes = <List<int>>[];
-
-  @override
-  void add(List<int> bytes) {
-    super.add(bytes);
-    writes.add(bytes);
-  }
-}
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index bfadc5b..d360c18 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -14,8 +14,10 @@
 import 'package:package_config/src/util.dart' show checkValidPackageUri;
 
 import '../compiler_new.dart' as api;
+import 'common/tasks.dart' show GenericTask, Measurer;
 import 'common.dart';
-import 'common/tasks.dart' show GenericTask;
+import 'common/backend_api.dart' show
+    Backend;
 import 'compiler.dart';
 import 'diagnostics/messages.dart' show Message;
 import 'elements/elements.dart' as elements;
@@ -23,6 +25,7 @@
 import 'io/source_file.dart';
 import 'options.dart' show CompilerOptions;
 import 'platform_configuration.dart' as platform_configuration;
+import 'resolved_uri_translator.dart';
 import 'script.dart';
 
 /// Implements the [Compiler] using a [api.CompilerInput] for supplying the
@@ -31,12 +34,12 @@
   api.CompilerInput provider;
   api.CompilerDiagnostics handler;
   Packages packages;
-  bool mockableLibraryUsed = false;
 
-  /// A mapping of the dart: library-names to their location.
-  ///
-  /// Initialized in [setupSdk].
-  Map<String, Uri> sdkLibraries;
+  bool get mockableLibraryUsed => resolvedUriTranslator.isSet
+      ? resolvedUriTranslator.mockableLibraryUsed
+      : false;
+
+  ForwardingResolvedUriTranslator resolvedUriTranslator;
 
   GenericTask userHandlerTask;
   GenericTask userProviderTask;
@@ -45,11 +48,14 @@
   Uri get libraryRoot => options.platformConfigUri.resolve(".");
 
   CompilerImpl(this.provider, api.CompilerOutput outputProvider, this.handler,
-      CompilerOptions options)
-      : super(
+      CompilerOptions options,
+      {MakeBackendFuncion makeBackend, MakeReporterFunction makeReporter})
+      : resolvedUriTranslator = new ForwardingResolvedUriTranslator(),
+        super(
             options: options,
             outputProvider: outputProvider,
-            environment: new _Environment(options.environment)) {
+            environment: new _Environment(options.environment),
+            makeBackend: makeBackend, makeReporter: makeReporter) {
     _Environment env = environment;
     env.compiler = this;
     tasks.addAll([
@@ -64,15 +70,6 @@
         null, null, null, null, message, api.Diagnostic.VERBOSE_INFO);
   }
 
-  /// See [Compiler.translateResolvedUri].
-  Uri translateResolvedUri(elements.LibraryElement importingLibrary,
-      Uri resolvedUri, Spannable spannable) {
-    if (resolvedUri.scheme == 'dart') {
-      return translateDartUri(importingLibrary, resolvedUri, spannable);
-    }
-    return resolvedUri;
-  }
-
   /**
    * Reads the script designated by [readableUri].
    */
@@ -149,63 +146,6 @@
   Uri translateUri(Spannable node, Uri uri) =>
       uri.scheme == 'package' ? translatePackageUri(node, uri) : uri;
 
-  /// Translates "resolvedUri" with scheme "dart" to a [uri] resolved relative
-  /// to `options.platformConfigUri` according to the information in the file at
-  /// `options.platformConfigUri`.
-  ///
-  /// Returns null and emits an error if the library could not be found or
-  /// imported into [importingLibrary].
-  ///
-  /// Internal libraries (whose name starts with '_') can be only resolved if
-  /// [importingLibrary] is a platform or patch library.
-  Uri translateDartUri(elements.LibraryElement importingLibrary,
-      Uri resolvedUri, Spannable spannable) {
-    Uri location = lookupLibraryUri(resolvedUri.path);
-
-    if (location == null) {
-      reporter.reportErrorMessage(spannable, MessageKind.LIBRARY_NOT_FOUND,
-          {'resolvedUri': resolvedUri});
-      return null;
-    }
-
-    if (resolvedUri.path.startsWith('_')) {
-      bool allowInternalLibraryAccess = importingLibrary != null &&
-          (importingLibrary.isPlatformLibrary ||
-              importingLibrary.isPatch ||
-              importingLibrary.canonicalUri.path
-                  .contains('sdk/tests/compiler/dart2js_native'));
-
-      if (!allowInternalLibraryAccess) {
-        if (importingLibrary != null) {
-          reporter.reportErrorMessage(
-              spannable, MessageKind.INTERNAL_LIBRARY_FROM, {
-            'resolvedUri': resolvedUri,
-            'importingUri': importingLibrary.canonicalUri
-          });
-        } else {
-          reporter.reportErrorMessage(spannable, MessageKind.INTERNAL_LIBRARY,
-              {'resolvedUri': resolvedUri});
-          registerDisallowedLibraryUse(resolvedUri);
-        }
-        return null;
-      }
-    }
-
-    if (location.scheme == "unsupported") {
-      reporter.reportErrorMessage(spannable, MessageKind.LIBRARY_NOT_SUPPORTED,
-          {'resolvedUri': resolvedUri});
-      registerDisallowedLibraryUse(resolvedUri);
-      return null;
-    }
-
-    if (resolvedUri.path == 'html' || resolvedUri.path == 'io') {
-      // TODO(ahe): Get rid of mockableLibraryUsed when test.dart
-      // supports this use case better.
-      mockableLibraryUsed = true;
-    }
-    return location;
-  }
-
   Uri translatePackageUri(Spannable node, Uri uri) {
     try {
       checkValidPackageUri(uri);
@@ -223,14 +163,14 @@
 
   Future<elements.LibraryElement> analyzeUri(Uri uri,
       {bool skipLibraryWithPartOfTag: true}) {
-    List<Future> setupFutures = new List<Future>();
-    if (sdkLibraries == null) {
-      setupFutures.add(setupSdk());
+    Future setupFuture = new Future.value();
+    if (resolvedUriTranslator.isNotSet) {
+      setupFuture = setupFuture.then((_) => setupSdk());
     }
     if (packages == null) {
-      setupFutures.add(setupPackages(uri));
+      setupFuture = setupFuture.then((_) => setupPackages(uri));
     }
-    return Future.wait(setupFutures).then((_) {
+    return setupFuture.then((_) {
       return super
           .analyzeUri(uri, skipLibraryWithPartOfTag: skipLibraryWithPartOfTag);
     });
@@ -273,11 +213,12 @@
   }
 
   Future<Null> setupSdk() {
-    if (sdkLibraries == null) {
+    if (resolvedUriTranslator.isNotSet) {
       return platform_configuration
           .load(options.platformConfigUri, provider)
           .then((Map<String, Uri> mapping) {
-        sdkLibraries = mapping;
+        resolvedUriTranslator.resolvedUriTranslator =
+            new ResolvedUriTranslator(mapping, reporter);
       });
     } else {
       // The incremental compiler sets up the sdk before run.
@@ -287,33 +228,59 @@
   }
 
   Future<bool> run(Uri uri) {
-    log('Using platform configuration at ${options.platformConfigUri}');
+    Duration setupDuration = measurer.wallClock.elapsed;
+    return selfTask.measureSubtask("CompilerImpl.run", () {
+      log('Using platform configuration at ${options.platformConfigUri}');
 
-    return Future.wait([setupSdk(), setupPackages(uri)]).then((_) {
-      assert(sdkLibraries != null);
-      assert(packages != null);
+      return setupSdk().then((_) => setupPackages(uri)).then((_) {
+        assert(resolvedUriTranslator.isSet);
+        assert(packages != null);
 
-      return super.run(uri).then((bool success) {
-        int cumulated = 0;
-        for (final task in tasks) {
-          int elapsed = task.timing;
-          if (elapsed != 0) {
-            cumulated += elapsed;
-            log('${task.name} took ${elapsed}msec');
-            for (String subtask in task.subtasks) {
-              int subtime = task.getSubtaskTime(subtask);
-              log('${task.name} > $subtask took ${subtime}msec');
-            }
-          }
+        return super.run(uri);
+      }).then((bool success) {
+        if (options.verbose) {
+          StringBuffer timings = new StringBuffer();
+          computeTimings(setupDuration, timings);
+          log("$timings");
         }
-        int total = totalCompileTime.elapsedMilliseconds;
-        log('Total compile-time ${total}msec;'
-            ' unaccounted ${total - cumulated}msec');
         return success;
       });
     });
   }
 
+  void computeTimings(Duration setupDuration, StringBuffer timings) {
+    timings.writeln("Timings:");
+    Duration totalDuration = measurer.wallClock.elapsed;
+    Duration asyncDuration = measurer.asyncWallClock.elapsed;
+    Duration cumulatedDuration = Duration.ZERO;
+    for (final task in tasks) {
+      String running = task.isRunning ? "*" : "";
+      Duration duration = task.duration;
+      if (duration != Duration.ZERO) {
+        cumulatedDuration += duration;
+        timings.writeln(
+            '    $running${task.name} took'
+            ' ${duration.inMilliseconds}msec');
+        for (String subtask in task.subtasks) {
+          int subtime = task.getSubtaskTime(subtask);
+          String running = task.getSubtaskIsRunning(subtask) ? "*" : "";
+          timings.writeln(
+              '    $running${task.name} > $subtask took ${subtime}msec');
+        }
+      }
+    }
+    Duration unaccountedDuration =
+        totalDuration - cumulatedDuration - setupDuration - asyncDuration;
+    double percent = unaccountedDuration.inMilliseconds * 100
+        / totalDuration.inMilliseconds;
+    timings.write(
+        '    Total compile-time ${totalDuration.inMilliseconds}msec;'
+        ' setup ${setupDuration.inMilliseconds}msec;'
+        ' async ${asyncDuration.inMilliseconds}msec;'
+        ' unaccounted ${unaccountedDuration.inMilliseconds}msec'
+        ' (${percent.toStringAsFixed(2)}%)');
+  }
+
   void reportDiagnostic(DiagnosticMessage message,
       List<DiagnosticMessage> infos, api.Diagnostic kind) {
     _reportDiagnosticMessage(message, kind);
@@ -341,24 +308,33 @@
 
   void callUserHandler(Message message, Uri uri, int begin, int end,
       String text, api.Diagnostic kind) {
-    userHandlerTask.measure(() {
-      handler.report(message, uri, begin, end, text, kind);
-    });
+    try {
+      userHandlerTask.measure(() {
+        handler.report(message, uri, begin, end, text, kind);
+      });
+    } catch (ex, s) {
+      reportCrashInUserCode('Uncaught exception in diagnostic handler', ex, s);
+      rethrow;
+    }
   }
 
   Future callUserProvider(Uri uri) {
-    return userProviderTask.measure(() => provider.readFromUri(uri));
+    try {
+      return userProviderTask.measureIo(() => provider.readFromUri(uri));
+    } catch (ex, s) {
+      reportCrashInUserCode('Uncaught exception in input provider', ex, s);
+      rethrow;
+    }
   }
 
   Future<Packages> callUserPackagesDiscovery(Uri uri) {
-    return userPackagesDiscoveryTask
-        .measure(() => options.packagesDiscoveryProvider(uri));
-  }
-
-  Uri lookupLibraryUri(String libraryName) {
-    assert(invariant(NO_LOCATION_SPANNABLE, sdkLibraries != null,
-        message: "setupSdk() has not been run"));
-    return sdkLibraries[libraryName];
+    try {
+      return userPackagesDiscoveryTask
+          .measureIo(() => options.packagesDiscoveryProvider(uri));
+    } catch (ex, s) {
+      reportCrashInUserCode('Uncaught exception in package discovery', ex, s);
+      rethrow;
+    }
   }
 
   Uri resolvePatchUri(String libraryName) {
@@ -370,14 +346,15 @@
   final Map<String, String> definitions;
 
   // TODO(sigmund): break the circularity here: Compiler needs an environment to
-  // intialize the library loader, but the environment here needs to know about
+  // initialize the library loader, but the environment here needs to know about
   // how the sdk is set up and about whether the backend supports mirrors.
   CompilerImpl compiler;
 
   _Environment(this.definitions);
 
   String valueOf(String name) {
-    assert(invariant(NO_LOCATION_SPANNABLE, compiler.sdkLibraries != null,
+    assert(invariant(
+        NO_LOCATION_SPANNABLE, compiler.resolvedUriTranslator != null,
         message: "setupSdk() has not been run"));
 
     var result = definitions[name];
@@ -389,7 +366,7 @@
     // Private libraries are not exposed to the users.
     if (libraryName.startsWith("_")) return null;
 
-    if (compiler.sdkLibraries.containsKey(libraryName)) {
+    if (compiler.resolvedUriTranslator.sdkLibraries.containsKey(libraryName)) {
       // Dart2js always "supports" importing 'dart:mirrors' but will abort
       // the compilation at a later point if the backend doesn't support
       // mirrors. In this case 'mirrors' should not be in the environment.
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index 2d0ee99..dfb5ba9 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -6,7 +6,7 @@
 
 import 'common.dart';
 import 'common/names.dart' show Identifiers;
-import 'common/resolution.dart' show Parsing, Resolution;
+import 'common/resolution.dart' show ParsingContext, Resolution;
 import 'common/tasks.dart' show CompilerTask;
 import 'compiler.dart' show Compiler;
 import 'constants/expressions.dart';
@@ -30,9 +30,15 @@
 
   String get name => "Closure Simplifier";
 
-  ClosureClassMap computeClosureToClassMapping(
-      Element element, Node node, TreeElements elements) {
+  ClosureClassMap computeClosureToClassMapping(ResolvedAst resolvedAst) {
     return measure(() {
+      Element element = resolvedAst.element;
+      if (resolvedAst.kind != ResolvedAstKind.PARSED) {
+        return new ClosureClassMap(null, null, null, new ThisLocal(element));
+      }
+      Node node = resolvedAst.node;
+      TreeElements elements = resolvedAst.elements;
+
       ClosureClassMap cached = closureMappingCache[node];
       if (cached != null) return cached;
 
@@ -44,6 +50,8 @@
       if (node is FunctionExpression) {
         translator.translateFunction(element, node);
       } else if (element.isSynthesized) {
+        reporter.internalError(
+            element, "Unexpected synthesized element: $element");
         return new ClosureClassMap(null, null, null, new ThisLocal(element));
       } else {
         assert(element.isField);
@@ -123,7 +131,7 @@
   bool get hasResolvedAst => hasTreeElements;
 
   ResolvedAst get resolvedAst {
-    return new ResolvedAst(this, null, treeElements);
+    return new ParsedResolvedAst(this, null, null, treeElements);
   }
 
   Expression get initializer {
@@ -185,7 +193,7 @@
             // By assigning a fresh class-id we make sure that the hashcode
             // is unique, but also emit closure classes after all other
             // classes (since the emitter sorts classes by their id).
-            compiler.getNextFreeId(),
+            compiler.idGenerator.getNextFreeId(),
             STATE_DONE) {
     JavaScriptBackend backend = compiler.backend;
     ClassElement superclass = methodElement.isInstanceMember
@@ -213,7 +221,7 @@
 
   Token get position => node.getBeginToken();
 
-  Node parseNode(Parsing parsing) => node;
+  Node parseNode(ParsingContext parsing) => node;
 
   // A [ClosureClassElement] is nested inside a function or initializer in terms
   // of [enclosingElement], but still has to be treated as a top-level
@@ -335,10 +343,10 @@
 
   FunctionExpression get node => expression.node;
 
-  FunctionExpression parseNode(Parsing parsing) => node;
+  FunctionExpression parseNode(ParsingContext parsing) => node;
 
   ResolvedAst get resolvedAst {
-    return new ResolvedAst(this, node, treeElements);
+    return new ParsedResolvedAst(this, node, node.body, treeElements);
   }
 
   Element get analyzableElement => closureClass.methodElement.analyzableElement;
@@ -371,6 +379,27 @@
       f(LocalVariableElement variable, BoxFieldElement boxField)) {
     capturedVariables.forEach(f);
   }
+
+  String toString() {
+    String separator = '';
+    StringBuffer sb = new StringBuffer();
+    sb.write('ClosureScope(');
+    if (boxElement != null) {
+      sb.write('box=$boxElement');
+      separator = ',';
+    }
+    if (boxedLoopVariables.isNotEmpty) {
+      sb.write(separator);
+      sb.write('boxedLoopVariables=${boxedLoopVariables}');
+      separator = ',';
+    }
+    if (capturedVariables.isNotEmpty) {
+      sb.write(separator);
+      sb.write('capturedVariables=$capturedVariables');
+    }
+    sb.write(')');
+    return sb.toString();
+  }
 }
 
 class ClosureClassMap {
diff --git a/pkg/compiler/lib/src/common/backend_api.dart b/pkg/compiler/lib/src/common/backend_api.dart
index 71a8c82..6b809e9 100644
--- a/pkg/compiler/lib/src/common/backend_api.dart
+++ b/pkg/compiler/lib/src/common/backend_api.dart
@@ -8,43 +8,44 @@
 
 import '../common.dart';
 import '../common/codegen.dart' show CodegenImpact;
-import '../common/resolution.dart' show ResolutionImpact;
-import '../compiler.dart' show Compiler;
+import '../common/resolution.dart' show ResolutionImpact, Frontend;
 import '../compile_time_constants.dart'
     show BackendConstantEnvironment, ConstantCompilerTask;
-import '../constants/expressions.dart' show ConstantExpression;
+import '../compiler.dart' show Compiler;
 import '../constants/constant_system.dart' show ConstantSystem;
+import '../constants/expressions.dart' show ConstantExpression;
 import '../constants/values.dart' show ConstantValue;
 import '../dart_types.dart' show DartType, InterfaceType;
 import '../elements/elements.dart'
     show
         ClassElement,
-        ConstructorElement,
         Element,
         FunctionElement,
         LibraryElement,
         MetadataAnnotation,
         MethodElement;
-import '../enqueue.dart' show Enqueuer, CodegenEnqueuer, ResolutionEnqueuer;
+import '../enqueue.dart' show Enqueuer, EnqueueTask, CodegenEnqueuer, ResolutionEnqueuer;
 import '../io/code_output.dart' show CodeBuffer;
 import '../io/source_information.dart' show SourceInformationStrategy;
 import '../js_backend/backend_helpers.dart' as js_backend show BackendHelpers;
-import '../js_backend/js_backend.dart' as js_backend show JavaScriptBackend;
+import '../js_backend/js_backend.dart' as js_backend;
 import '../library_loader.dart' show LibraryLoader, LoadedLibraries;
 import '../native/native.dart' as native show NativeEnqueuer, maybeEnableNative;
 import '../patch_parser.dart'
     show checkNativeAnnotation, checkJsInteropAnnotation;
-import '../resolution/tree_elements.dart' show TreeElements;
 import '../serialization/serialization.dart'
-    show DeserializerPlugin, ObjectDecoder, ObjectEncoder, SerializerPlugin;
+    show DeserializerPlugin, SerializerPlugin;
 import '../tree/tree.dart' show Node, Send;
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/world_impact.dart' show ImpactStrategy, WorldImpact;
-
-import 'codegen.dart' show CodegenWorkItem;
-import 'registry.dart' show Registry;
-import 'tasks.dart' show CompilerTask;
-import 'work.dart' show ItemCompilationContext;
+import 'codegen.dart' show
+    CodegenWorkItem;
+import 'registry.dart' show
+    Registry;
+import 'tasks.dart' show
+    CompilerTask;
+import 'work.dart' show
+    ItemCompilationContext;
 
 abstract class Backend {
   final Compiler compiler;
@@ -361,9 +362,7 @@
   void onCodegenStart() {}
 
   /// Called after [element] has been resolved.
-  // TODO(johnniwinther): Change [TreeElements] to [Registry] or a dependency
-  // node. [elements] is currently unused by the implementation.
-  void onElementResolved(Element element, TreeElements elements) {}
+  void onElementResolved(Element element) {}
 
   // Does this element belong in the output
   bool shouldOutput(Element element) => true;
@@ -381,8 +380,10 @@
   void registerAsyncMarker(
       FunctionElement element, Enqueuer enqueuer, Registry registry) {}
 
-  /// Called when resolving a call to a foreign function.
-  void registerForeignCall(Send node, Element element,
+  /// Called when resolving a call to a foreign function. If a non-null value
+  /// is returned, this is stored as native data for [node] in the resolved
+  /// AST.
+  dynamic resolveForeignCall(Send node, Element element,
       CallStructure callStructure, ForeignResolver resolver) {}
 
   /// Returns the location of the patch-file associated with [libraryName]
@@ -398,6 +399,11 @@
       bool supportSerialization: true}) {
     return const ImpactStrategy();
   }
+
+  /// Backend access to the front-end.
+  Frontend get frontend => compiler.resolution;
+
+  EnqueueTask makeEnqueuer() => new EnqueueTask(compiler);
 }
 
 /// Interface for resolving calls to foreign functions.
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index 0a9cf75..4640bdb 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -4,6 +4,7 @@
 
 library dart2js.common.codegen;
 
+import '../closure.dart' show SynthesizedCallMethodElementX;
 import '../common.dart';
 import '../compiler.dart' show Compiler;
 import '../constants/values.dart' show ConstantValue;
@@ -14,9 +15,9 @@
         ClassElement,
         Element,
         FunctionElement,
-        LocalFunctionElement;
+        LocalFunctionElement,
+        ResolvedAst;
 import '../enqueue.dart' show CodegenEnqueuer;
-import '../resolution/tree_elements.dart' show TreeElements;
 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
 import '../universe/world_impact.dart'
     show WorldImpact, WorldImpactBuilder, WorldImpactVisitor;
@@ -225,6 +226,7 @@
 /// [WorkItem] used exclusively by the [CodegenEnqueuer].
 class CodegenWorkItem extends WorkItem {
   CodegenRegistry registry;
+  final ResolvedAst resolvedAst;
 
   factory CodegenWorkItem(Compiler compiler, AstElement element,
       ItemCompilationContext compilationContext) {
@@ -235,16 +237,14 @@
     assert(invariant(
         element, compiler.enqueuer.resolution.hasBeenProcessed(element),
         message: "$element has not been resolved."));
-    assert(invariant(element, element.resolvedAst.elements != null,
-        message: 'Resolution tree is null for $element in codegen work item'));
-    return new CodegenWorkItem.internal(element, compilationContext);
+    ResolvedAst resolvedAst = compiler.backend.frontend.getResolvedAst(element);
+    return new CodegenWorkItem.internal(resolvedAst, compilationContext);
   }
 
   CodegenWorkItem.internal(
-      AstElement element, ItemCompilationContext compilationContext)
-      : super(element, compilationContext);
-
-  TreeElements get resolutionTree => element.resolvedAst.elements;
+      ResolvedAst resolvedAst, ItemCompilationContext compilationContext)
+      : this.resolvedAst = resolvedAst,
+        super(resolvedAst.element, compilationContext);
 
   WorldImpact run(Compiler compiler, CodegenEnqueuer world) {
     if (world.isProcessed(element)) return const WorldImpact();
diff --git a/pkg/compiler/lib/src/common/registry.dart b/pkg/compiler/lib/src/common/registry.dart
index 0499858..96ee845 100644
--- a/pkg/compiler/lib/src/common/registry.dart
+++ b/pkg/compiler/lib/src/common/registry.dart
@@ -5,8 +5,8 @@
 library dart2js.common.registry;
 
 import '../dart_types.dart' show InterfaceType;
+import '../elements/elements.dart' show Element;
 import '../enqueue.dart' show Enqueuer;
-import '../elements/elements.dart' show Element, FunctionElement;
 import '../universe/use.dart' show DynamicUse, StaticUse;
 
 /// Interface for registration of element dependencies.
diff --git a/pkg/compiler/lib/src/common/resolution.dart b/pkg/compiler/lib/src/common/resolution.dart
index 42f9617..d049471 100644
--- a/pkg/compiler/lib/src/common/resolution.dart
+++ b/pkg/compiler/lib/src/common/resolution.dart
@@ -14,20 +14,19 @@
         AstElement,
         ClassElement,
         Element,
-        ErroneousElement,
         FunctionElement,
         FunctionSignature,
-        LocalFunctionElement,
         MetadataAnnotation,
-        MethodElement,
         ResolvedAst,
-        TypedefElement,
-        TypeVariableElement;
+        TypedefElement;
 import '../enqueue.dart' show ResolutionEnqueuer;
 import '../options.dart' show ParserOptions;
 import '../parser/element_listener.dart' show ScannerOptions;
-import '../tree/tree.dart' show AsyncForIn, Send, TypeAnnotation;
+import '../parser/parser_task.dart';
+import '../patch_parser.dart';
+import '../tree/tree.dart' show TypeAnnotation;
 import '../universe/world_impact.dart' show WorldImpact;
+import 'backend_api.dart';
 import 'work.dart' show ItemCompilationContext, WorkItem;
 
 /// [WorkItem] used exclusively by the [ResolutionEnqueuer].
@@ -186,9 +185,19 @@
   }
 }
 
+/// Interface for the accessing the front-end analysis.
+// TODO(johnniwinther): Find a better name for this.
+abstract class Frontend {
+  /// Returns the `ResolvedAst` for the [element].
+  ResolvedAst getResolvedAst(Element element);
+
+  /// Returns the [ResolutionImpact] for [element].
+  ResolutionImpact getResolutionImpact(Element element);
+}
+
 // TODO(johnniwinther): Rename to `Resolver` or `ResolverContext`.
-abstract class Resolution {
-  Parsing get parsing;
+abstract class Resolution implements Frontend {
+  ParsingContext get parsingContext;
   DiagnosticReporter get reporter;
   CoreTypes get coreTypes;
 
@@ -203,8 +212,15 @@
   FunctionSignature resolveSignature(FunctionElement function);
   DartType resolveTypeAnnotation(Element element, TypeAnnotation node);
 
+  /// Returns `true` if [element] has been resolved.
+  // TODO(johnniwinther): Normalize semantics between normal and deserialized
+  // elements; deserialized elements are always resolved but the method will
+  // return `false`.
   bool hasBeenResolved(Element element);
 
+  /// Resolve [element] if it has not already been resolved.
+  void ensureResolved(Element element);
+
   ResolutionWorkItem createWorkItem(
       Element element, ItemCompilationContext compilationContext);
 
@@ -220,6 +236,9 @@
   /// Returns the precomputed [ResolutionImpact] for [element].
   ResolutionImpact getResolutionImpact(Element element);
 
+  /// Returns the [ResolvedAst] for [element], computing it if necessary.
+  ResolvedAst computeResolvedAst(Element element);
+
   /// Returns the precomputed [WorldImpact] for [element].
   WorldImpact getWorldImpact(Element element);
 
@@ -234,13 +253,59 @@
   /// Later calls to [getWorldImpact] or [computeWorldImpact] returns an empty
   /// impact.
   void emptyCache();
+
+  void forgetElement(Element element);
 }
 
-// TODO(johnniwinther): Rename to `Parser` or `ParsingContext`.
-abstract class Parsing {
+/// A container of commonly used dependencies for tasks that involve parsing.
+abstract class ParsingContext {
+  factory ParsingContext(
+      DiagnosticReporter reporter,
+      ParserOptions parserOptions,
+      ParserTask parser,
+      PatchParserTask patchParser,
+      Backend backend) = _ParsingContext;
+
   DiagnosticReporter get reporter;
-  void parsePatchClass(ClassElement cls);
-  measure(f());
-  ScannerOptions getScannerOptionsFor(Element element);
   ParserOptions get parserOptions;
+  ParserTask get parser;
+  PatchParserTask get patchParser;
+
+  /// Use [patchParser] directly instead.
+  @deprecated
+  void parsePatchClass(ClassElement cls);
+
+  /// Use [parser] and measure directly instead.
+  @deprecated
+  measure(f());
+
+  /// Get the [ScannerOptions] to scan the given [element].
+  ScannerOptions getScannerOptionsFor(Element element);
+}
+
+class _ParsingContext implements ParsingContext {
+  final DiagnosticReporter reporter;
+  final ParserOptions parserOptions;
+  final ParserTask parser;
+  final PatchParserTask patchParser;
+  final Backend backend;
+
+  _ParsingContext(this.reporter, this.parserOptions, this.parser,
+      this.patchParser, this.backend);
+
+  @override
+  measure(f()) => parser.measure(f);
+
+  @override
+  void parsePatchClass(ClassElement cls) {
+    patchParser.measure(() {
+      if (cls.isPatch) {
+        patchParser.parsePatchClassNode(cls);
+      }
+    });
+  }
+
+  @override
+  ScannerOptions getScannerOptionsFor(Element element) => new ScannerOptions(
+      canUseNative: backend.canLibraryUseNative(element.library));
 }
diff --git a/pkg/compiler/lib/src/common/tasks.dart b/pkg/compiler/lib/src/common/tasks.dart
index 69e5f11..c5a77d3 100644
--- a/pkg/compiler/lib/src/common/tasks.dart
+++ b/pkg/compiler/lib/src/common/tasks.dart
@@ -4,7 +4,12 @@
 
 library dart2js.common.tasks;
 
-import 'dart:developer' show UserTag;
+import 'dart:async' show
+    Future,
+    Zone,
+    ZoneDelegate,
+    ZoneSpecification,
+    runZoned;
 
 import '../common.dart';
 import '../compiler.dart' show Compiler;
@@ -19,20 +24,27 @@
   DeferredTask(this.element, this.action);
 }
 
+/// A [CompilerTask] is used to measure where time is spent in the compiler.
+/// The main entry points are [measure] and [measureIo].
 class CompilerTask {
   final Compiler compiler;
   final Stopwatch watch;
-  UserTag profilerTag;
   final Map<String, GenericTask> _subtasks = <String, GenericTask>{};
 
+  int asyncCount = 0;
+
   CompilerTask(Compiler compiler)
       : this.compiler = compiler,
         watch = (compiler.options.verbose) ? new Stopwatch() : null;
 
   DiagnosticReporter get reporter => compiler.reporter;
 
+  Measurer get measurer => compiler.measurer;
+
   String get name => "Unknown task '${this.runtimeType}'";
 
+  bool get isRunning => watch?.isRunning == true;
+
   int get timing {
     if (watch == null) return 0;
     int total = watch.elapsedMilliseconds;
@@ -42,38 +54,161 @@
     return total;
   }
 
-  UserTag getProfilerTag() {
-    if (profilerTag == null) profilerTag = new UserTag(name);
-    return profilerTag;
-  }
-
-  measure(action()) {
-    // In verbose mode when watch != null.
-    if (watch == null) return action();
-    CompilerTask previous = compiler.measuredTask;
-    if (identical(this, previous)) return action();
-    compiler.measuredTask = this;
-    if (previous != null) previous.watch.stop();
-    watch.start();
-    UserTag oldTag = getProfilerTag().makeCurrent();
-    try {
-      return action();
-    } finally {
-      watch.stop();
-      oldTag.makeCurrent();
-      if (previous != null) previous.watch.start();
-      compiler.measuredTask = previous;
+  Duration get duration {
+    if (watch == null) return Duration.ZERO;
+    Duration total = watch.elapsed;
+    for (GenericTask subtask in _subtasks.values) {
+      total += subtask.duration;
     }
+    return total;
   }
 
+  /// Perform [action] and use [watch] to measure its runtime (including any
+  /// asynchronous callbacks, such as, [Future.then], but excluding code
+  /// measured by other tasks).
+  measure(action()) => watch == null ? action() : measureZoned(action);
+
+  /// Helper method that starts measuring with this [CompilerTask], that is,
+  /// make this task the currently measured task.
+  CompilerTask start() {
+    if (watch == null) return null;
+    CompilerTask previous = measurer.currentTask;
+    measurer.currentTask = this;
+    if (previous != null) previous.watch.stop();
+    // Regardless of whether [previous] is `null` we've returned from the
+    // eventloop.
+    measurer.stopAsyncWallClock();
+    watch.start();
+    return previous;
+  }
+
+  /// Helper method that stops measuring with this [CompilerTask], that is,
+  /// make [previous] the currently measured task.
+  void stop(CompilerTask previous) {
+    if (watch == null) return;
+    watch.stop();
+    if (previous != null) {
+      previous.watch.start();
+    } else {
+      // If there's no previous task, we're about to return control to the
+      // event loop. Start counting that as waiting asynchronous I/O.
+      measurer.startAsyncWallClock();
+    }
+    measurer.currentTask = previous;
+  }
+
+  /// Helper method for [measure]. Don't call this method directly as it
+  /// assumes that [watch] isn't null.
+  measureZoned(action()) {
+    // Using zones, we're able to track asynchronous operations correctly, as
+    // our zone will be asked to invoke `then` blocks. Then blocks (the closure
+    // passed to runZoned, and other closures) are run via the `run` functions
+    // below.
+
+    assert(watch != null);
+
+    // The current zone is already measuring `this` task.
+    if (Zone.current[measurer] == this) return action();
+
+    /// Run [f] in [zone]. Running must be delegated to [parent] to ensure that
+    /// various state is set up correctly (in particular that `Zone.current`
+    /// has the right value). Since [measureZoned] can be called recursively
+    /// (synchronously), some of the measuring zones we create will be parents
+    /// of other measuring zones, but we still need to call through the parent
+    /// chain. Consequently, we use a zone value keyed by [measurer] to see if
+    /// we should measure or not when delegating.
+    run(Zone self, ZoneDelegate parent, Zone zone, f()) {
+      if (zone[measurer] != this) return parent.run(zone, f);
+      CompilerTask previous = start();
+      try {
+        return parent.run(zone, f);
+      } finally {
+        stop(previous);
+      }
+    }
+
+    /// Same as [run] except that [f] takes one argument, [arg].
+    runUnary(Zone self, ZoneDelegate parent, Zone zone, f(arg), arg) {
+      if (zone[measurer] != this) return parent.runUnary(zone, f, arg);
+      CompilerTask previous = start();
+      try {
+        return parent.runUnary(zone, f, arg);
+      } finally {
+        stop(previous);
+      }
+    }
+
+    /// Same as [run] except that [f] takes two arguments ([a1] and [a2]).
+    runBinary(Zone self, ZoneDelegate parent, Zone zone, f(a1, a2), a1, a2) {
+      if (zone[measurer] != this) return parent.runBinary(zone, f, a1, a2);
+      CompilerTask previous = start();
+      try {
+        return parent.runBinary(zone, f, a1, a2);
+      } finally {
+        stop(previous);
+      }
+    }
+
+    return runZoned(
+        action,
+        zoneValues: { measurer: this },
+        zoneSpecification: new ZoneSpecification(
+            run: run, runUnary: runUnary, runBinary: runBinary));
+  }
+
+  /// Asynchronous version of [measure]. Use this when action returns a future
+  /// that's truly asynchronous, such I/O. Only one task can use this method
+  /// concurrently.
+  ///
+  /// Note: we assume that this method is used only by the compiler input
+  /// provider, but it could be used by other tasks as long as the input
+  /// provider will not be called by those tasks.
+  measureIo(Future action()) {
+    return watch == null ? action() : measureIoHelper(action);
+  }
+
+  /// Helper method for [measureIo]. Don't call this directly as it assumes
+  /// that [watch] isn't null.
+  Future measureIoHelper(Future action()) {
+    assert(watch != null);
+    if (measurer.currentAsyncTask == null) {
+      measurer.currentAsyncTask = this;
+    } else if (measurer.currentAsyncTask != this) {
+      throw "Can't track async task '$name' because"
+          " '${measurer.currentAsyncTask.name}' is already being tracked.";
+    }
+    asyncCount++;
+    return measure(action).whenComplete(() {
+      asyncCount--;
+      if (asyncCount == 0) measurer.currentAsyncTask = null;
+    });
+  }
+
+  /// Convenience function for combining
+  /// [DiagnosticReporter.withCurrentElement] and [measure].
   measureElement(Element element, action()) {
-    reporter.withCurrentElement(element, () => measure(action));
+    return watch == null
+        ? reporter.withCurrentElement(element, action)
+        : measureElementHelper(element, action);
+  }
+
+  /// Helper method for [measureElement]. Don't call this directly as it
+  /// assumes that [watch] isn't null.
+  measureElementHelper(Element element, action()) {
+    assert(watch != null);
+    return reporter.withCurrentElement(element, () => measure(action));
   }
 
   /// Measure the time spent in [action] (if in verbose mode) and accumulate it
   /// under a subtask with the given name.
   measureSubtask(String name, action()) {
-    if (watch == null) return action();
+    return watch == null ? action() : measureSubtaskHelper(name, action);
+  }
+
+  /// Helper method for [measureSubtask]. Don't call this directly as it
+  /// assumes that [watch] isn't null.
+  measureSubtaskHelper(String name, action()) {
+    assert(watch != null);
     // Use a nested CompilerTask for the measurement to ensure nested [measure]
     // calls work correctly. The subtasks will never themselves have nested
     // subtasks because they are not accessible outside.
@@ -85,6 +220,8 @@
   Iterable<String> get subtasks => _subtasks.keys;
 
   int getSubtaskTime(String subtask) => _subtasks[subtask].timing;
+
+  bool getSubtaskIsRunning(String subtask) => _subtasks[subtask].isRunning;
 }
 
 class GenericTask extends CompilerTask {
@@ -92,3 +229,48 @@
 
   GenericTask(this.name, Compiler compiler) : super(compiler);
 }
+
+class Measurer {
+  /// Measures the total runtime from this object was constructed.
+  ///
+  /// Note: MUST be first field to ensure [wallclock] is started before other
+  /// computations.
+  final Stopwatch wallClock = new Stopwatch()..start();
+
+  /// Measures gaps between zoned closures due to asynchronicity.
+  final Stopwatch asyncWallClock = new Stopwatch();
+
+  /// The currently running task, that is, the task whose [Stopwatch] is
+  /// currently running.
+  CompilerTask currentTask;
+
+  /// The current task which should be charged for asynchronous gaps.
+  CompilerTask currentAsyncTask;
+
+  /// Start counting the total elapsed time since the compiler started.
+  void startWallClock() {
+    wallClock.start();
+  }
+
+  /// Start counting the total elapsed time since the compiler started.
+  void stopWallClock() {
+    wallClock.stop();
+  }
+
+  /// Call this before returning to the eventloop.
+  void startAsyncWallClock() {
+    if (currentAsyncTask != null) {
+      currentAsyncTask.watch.start();
+    } else {
+      asyncWallClock.start();
+    }
+  }
+
+  /// Call this when the eventloop returns control to us.
+  void stopAsyncWallClock() {
+    if (currentAsyncTask != null) {
+      currentAsyncTask.watch.stop();
+    }
+    asyncWallClock.stop();
+  }
+}
diff --git a/pkg/compiler/lib/src/compile_time_constants.dart b/pkg/compiler/lib/src/compile_time_constants.dart
index 825176c..c4fe193 100644
--- a/pkg/compiler/lib/src/compile_time_constants.dart
+++ b/pkg/compiler/lib/src/compile_time_constants.dart
@@ -193,7 +193,7 @@
     AstElement currentElement = element.analyzableElement;
     return reporter.withCurrentElement(currentElement, () {
       // TODO(johnniwinther): Avoid this eager analysis.
-      _analyzeElementEagerly(compiler, currentElement);
+      compiler.resolution.ensureResolved(currentElement.declaration);
 
       ConstantExpression constant = compileVariableWithDefinitions(
           element, currentElement.resolvedAst.elements,
@@ -847,7 +847,7 @@
     // TODO(ahe): This is nasty: we must eagerly analyze the
     // constructor to ensure the redirectionTarget has been computed
     // correctly.  Find a way to avoid this.
-    _analyzeElementEagerly(compiler, constructor);
+    resolution.ensureResolved(constructor.declaration);
 
     // The redirection chain of this element may not have been resolved through
     // a post-process action, so we have to make sure it is done here.
@@ -1092,6 +1092,7 @@
   final ConstructorElement constructor;
   final Map<Element, AstConstant> definitions;
   final Map<Element, AstConstant> fieldValues;
+  final ResolvedAst resolvedAst;
 
   /**
    * Documentation wanted -- johnniwinther
@@ -1103,11 +1104,15 @@
       : this.constructor = constructor,
         this.definitions = new Map<Element, AstConstant>(),
         this.fieldValues = new Map<Element, AstConstant>(),
-        super(handler, _analyzeElementEagerly(compiler, constructor), compiler,
-            isConst: true) {
+        this.resolvedAst =
+            compiler.resolution.computeResolvedAst(constructor.declaration),
+        super(handler, null, compiler, isConst: true) {
     assert(invariant(constructor, constructor.isImplementation));
   }
 
+  @override
+  TreeElements get elements => resolvedAst.elements;
+
   AstConstant visitSend(Send send) {
     Element element = elements[send];
     if (Elements.isLocal(element)) {
@@ -1332,12 +1337,6 @@
             new NullConstantValue());
 }
 
-// TODO(johnniwinther): Clean this up.
-TreeElements _analyzeElementEagerly(Compiler compiler, AstElement element) {
-  compiler.resolution.computeWorldImpact(element.declaration);
-  return element.resolvedAst.elements;
-}
-
 class _CompilerEnvironment implements Environment {
   final Compiler compiler;
 
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 1b01849..4999d44 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -9,36 +9,29 @@
 import '../compiler_new.dart' as api;
 import 'cache_strategy.dart' show CacheStrategy;
 import 'closure.dart' as closureMapping show ClosureTask;
-import 'common.dart';
 import 'common/backend_api.dart' show Backend;
-import 'common/codegen.dart' show CodegenImpact, CodegenWorkItem;
+import 'common/codegen.dart' show CodegenWorkItem;
+import 'common/names.dart' show Selectors;
 import 'common/names.dart' show Identifiers, Uris;
 import 'common/registry.dart' show EagerRegistry, Registry;
 import 'common/resolution.dart'
-    show Parsing, Resolution, ResolutionWorkItem, ResolutionImpact;
-import 'common/tasks.dart' show CompilerTask, GenericTask;
+    show ParsingContext, Resolution, ResolutionWorkItem, ResolutionImpact;
+import 'common/tasks.dart' show CompilerTask, GenericTask, Measurer;
 import 'common/work.dart' show ItemCompilationContext, WorkItem;
+import 'common.dart';
 import 'compile_time_constants.dart';
 import 'constants/values.dart';
 import 'core_types.dart' show CoreClasses, CoreTypes;
 import 'dart_backend/dart_backend.dart' as dart_backend;
 import 'dart_types.dart' show DartType, DynamicType, InterfaceType, Types;
-import 'deferred_load.dart' show DeferredLoadTask, OutputUnit;
+import 'deferred_load.dart' show DeferredLoadTask;
 import 'diagnostics/code_location.dart';
 import 'diagnostics/diagnostic_listener.dart' show DiagnosticReporter;
 import 'diagnostics/invariant.dart' show REPORT_EXCESS_RESOLUTION;
 import 'diagnostics/messages.dart' show Message, MessageTemplate;
 import 'dump_info.dart' show DumpInfoTask;
 import 'elements/elements.dart';
-import 'elements/modelx.dart'
-    show
-        ErroneousElementX,
-        ClassElementX,
-        CompilationUnitElementX,
-        DeferredLoaderGetterElementX,
-        MethodElementX,
-        LibraryElementX,
-        PrefixElementX;
+import 'elements/modelx.dart' show ErroneousElementX;
 import 'enqueue.dart'
     show
         CodegenEnqueuer,
@@ -58,30 +51,27 @@
         LibraryLoaderTask,
         LoadedLibraries,
         LibraryLoaderListener,
-        ResolvedUriTranslator,
         ScriptLoader;
 import 'mirrors_used.dart' show MirrorUsageAnalyzerTask;
-import 'common/names.dart' show Selectors;
 import 'null_compiler_output.dart' show NullCompilerOutput, NullSink;
-import 'options.dart' show CompilerOptions, DiagnosticOptions, ParserOptions;
+import 'options.dart' show CompilerOptions, DiagnosticOptions;
 import 'parser/diet_parser_task.dart' show DietParserTask;
-import 'parser/element_listener.dart' show ScannerOptions;
 import 'parser/parser_task.dart' show ParserTask;
 import 'patch_parser.dart' show PatchParserTask;
 import 'resolution/registry.dart' show ResolutionRegistry;
 import 'resolution/resolution.dart' show ResolverTask;
 import 'resolution/tree_elements.dart' show TreeElementMapping;
+import 'resolved_uri_translator.dart';
 import 'scanner/scanner_task.dart' show ScannerTask;
-import 'serialization/task.dart' show SerializationTask;
 import 'script.dart' show Script;
+import 'serialization/task.dart' show SerializationTask;
 import 'ssa/nodes.dart' show HInstruction;
-import 'tracer.dart' show Tracer;
 import 'tokens/token.dart' show StringToken, Token, TokenPair;
 import 'tokens/token_map.dart' show TokenMap;
+import 'tracer.dart' show Tracer;
 import 'tree/tree.dart' show Node, TypeAnnotation;
 import 'typechecker.dart' show TypeCheckerTask;
 import 'types/types.dart' as ti;
-import 'universe/call_structure.dart' show CallStructure;
 import 'universe/selector.dart' show Selector;
 import 'universe/universe.dart' show Universe;
 import 'universe/use.dart' show StaticUse;
@@ -89,15 +79,25 @@
 import 'util/util.dart' show Link, Setlet;
 import 'world.dart' show World;
 
-abstract class Compiler implements LibraryLoaderListener, IdGenerator {
-  final Stopwatch totalCompileTime = new Stopwatch();
+typedef Backend MakeBackendFuncion(Compiler compiler);
+
+typedef CompilerDiagnosticReporter MakeReporterFunction(
+    Compiler compiler, CompilerOptions options);
+
+abstract class Compiler implements LibraryLoaderListener {
+  /// Helper instance for measurements in [CompilerTask].
+  ///
+  /// Note: MUST be first field to ensure [Measurer.wallclock] is started
+  /// before other computations.
+  final Measurer measurer = new Measurer();
+
   final IdGenerator idGenerator = new IdGenerator();
   World world;
   Types types;
   _CompilerCoreTypes _coreTypes;
-  _CompilerDiagnosticReporter _reporter;
+  CompilerDiagnosticReporter _reporter;
   _CompilerResolution _resolution;
-  _CompilerParsing _parsing;
+  ParsingContext _parsingContext;
 
   final CacheStrategy cacheStrategy;
 
@@ -141,14 +141,10 @@
 
   List<Uri> librariesToAnalyzeWhenRun;
 
-  /// The set of platform libraries reported as unsupported.
-  ///
-  /// For instance when importing 'dart:io' without '--categories=Server'.
-  Set<Uri> disallowedLibraryUris = new Setlet<Uri>();
+  ResolvedUriTranslator get resolvedUriTranslator;
 
   Tracer tracer;
 
-  CompilerTask measuredTask;
   LibraryElement coreLibrary;
   LibraryElement asyncLibrary;
 
@@ -165,7 +161,7 @@
   CoreClasses get coreClasses => _coreTypes;
   CoreTypes get coreTypes => _coreTypes;
   Resolution get resolution => _resolution;
-  Parsing get parsing => _parsing;
+  ParsingContext get parsingContext => _parsingContext;
 
   ClassElement typedDataClass;
 
@@ -179,8 +175,17 @@
   // TODO(johnniwinther): Move this to the JavaScriptBackend.
   ClassElement nativeAnnotationClass;
 
-  // Initialized after symbolClass has been resolved.
-  FunctionElement symbolConstructor;
+  ConstructorElement _symbolConstructor;
+  ConstructorElement get symbolConstructor {
+    if (_symbolConstructor == null) {
+      ClassElement symbolClass = coreClasses.symbolClass;
+      symbolClass.ensureResolved(resolution);
+      _symbolConstructor = symbolClass.lookupConstructor('');
+      assert(invariant(symbolClass, _symbolConstructor != null,
+          message: "Default constructor not found ${symbolClass}."));
+    }
+    return _symbolConstructor;
+  }
 
   // Initialized when dart:mirrors is loaded.
   ClassElement mirrorSystemClass;
@@ -191,13 +196,6 @@
   // Initialized after mirrorSystemClass has been resolved.
   FunctionElement mirrorSystemGetNameFunction;
 
-  // Initialized when dart:_internal is loaded.
-  ClassElement symbolImplementationClass;
-
-  // Initialized when symbolImplementationClass has been resolved.
-  // TODO(johnniwinther): Move this to [BackendHelpers].
-  FunctionElement symbolValidatedConstructor;
-
   // Initialized when mirrorsUsedClass has been resolved.
   FunctionElement mirrorsUsedConstructor;
 
@@ -219,8 +217,11 @@
   /// The [String.fromEnvironment] constructor.
   ConstructorElement stringEnvironment;
 
+  // TODO(zarah): Remove this map and incorporate compile-time errors
+  // in the model.
   /// Tracks elements with compile-time errors.
-  final Set<Element> elementsWithCompileTimeErrors = new Set<Element>();
+  final Map<Element, List<DiagnosticMessage>> elementsWithCompileTimeErrors =
+      new Map<Element, List<DiagnosticMessage>>();
 
   final Environment environment;
   // TODO(sigmund): delete once we migrate the rest of the compiler to use
@@ -245,6 +246,8 @@
 
   GenericTask reuseLibraryTask;
 
+  GenericTask selfTask;
+
   /// The constant environment for the frontend interpretation of compile-time
   /// constants.
   ConstantEnvironment constants;
@@ -257,9 +260,6 @@
   /// A customizable filter that is applied to enqueued work items.
   QueueFilter enqueuerFilter = new QueueFilter();
 
-  final Selector symbolValidatedConstructorSelector =
-      new Selector.call(const PublicName('validated'), CallStructure.ONE_ARG);
-
   static const String CREATE_INVOCATION_MIRROR = 'createInvocationMirror';
 
   bool enabledRuntimeType = false;
@@ -281,32 +281,28 @@
   static const int PHASE_COMPILING = 3;
   int phase;
 
-  bool compilationFailedInternal = false;
-
-  bool get compilationFailed => compilationFailedInternal;
-
-  void set compilationFailed(bool value) {
-    if (value) {
-      elementsWithCompileTimeErrors.add(currentElement);
-    }
-    compilationFailedInternal = value;
-  }
+  bool compilationFailed = false;
 
   Compiler(
       {CompilerOptions options,
       api.CompilerOutput outputProvider,
-      this.environment: const _EmptyEnvironment()})
+      this.environment: const _EmptyEnvironment(),
+      MakeBackendFuncion makeBackend,
+      MakeReporterFunction makeReporter})
       : this.options = options,
         this.cacheStrategy = new CacheStrategy(options.hasIncrementalSupport),
         this.userOutputProvider = outputProvider == null
             ? const NullCompilerOutput()
             : outputProvider {
     world = new World(this);
+    if (makeReporter != null) {
+      _reporter = makeReporter(this, options);
+    } else {
+      _reporter = new CompilerDiagnosticReporter(this, options);
+    }
+    _resolution = new _CompilerResolution(this);
     // TODO(johnniwinther): Initialize core types in [initializeCoreClasses] and
     // make its field final.
-    _reporter = new _CompilerDiagnosticReporter(this, options);
-    _parsing = new _CompilerParsing(this);
-    _resolution = new _CompilerResolution(this);
     _coreTypes = new _CompilerCoreTypes(_resolution);
     types = new Types(_resolution);
     tracer = new Tracer(this, this.outputProvider);
@@ -319,7 +315,9 @@
     // for global dependencies.
     globalDependencies = new GlobalDependencyRegistry(this);
 
-    if (options.emitJavaScript) {
+    if (makeBackend != null) {
+      backend = makeBackend(this);
+    } else if (options.emitJavaScript) {
       js_backend.JavaScriptBackend jsBackend = new js_backend.JavaScriptBackend(
           this,
           generateSourceMap: options.generateSourceMap,
@@ -340,19 +338,20 @@
     }
 
     tasks = [
-      dietParser = new DietParserTask(this, parsing.parserOptions, idGenerator),
+      dietParser =
+          new DietParserTask(this, options, idGenerator, backend, reporter),
       scanner = createScannerTask(),
       serialization = new SerializationTask(this),
       libraryLoader = new LibraryLoaderTask(
           this,
-          new _ResolvedUriTranslator(this),
+          this.resolvedUriTranslator,
           new _ScriptLoader(this),
           new _ElementScanner(scanner),
           this.serialization,
           this,
           environment),
-      parser = new ParserTask(this, parsing.parserOptions),
-      patchParser = new PatchParserTask(this, parsing.parserOptions),
+      parser = new ParserTask(this, options),
+      patchParser = new PatchParserTask(this, options),
       resolver = createResolverTask(),
       closureToClassMapper = new closureMapping.ClosureTask(this),
       checker = new TypeCheckerTask(this),
@@ -360,11 +359,15 @@
       constants = backend.constantCompilerTask,
       deferredLoadTask = new DeferredLoadTask(this),
       mirrorUsageAnalyzerTask = new MirrorUsageAnalyzerTask(this),
-      enqueuer = new EnqueueTask(this),
+      enqueuer = backend.makeEnqueuer(),
       dumpInfoTask = new DumpInfoTask(this),
       reuseLibraryTask = new GenericTask('Reuse library', this),
+      selfTask = new GenericTask('self', this),
     ];
 
+    _parsingContext =
+        new ParsingContext(reporter, options, parser, patchParser, backend);
+
     tasks.addAll(backend.tasks);
   }
 
@@ -391,10 +394,6 @@
   bool get disableTypeInference =>
       options.disableTypeInference || compilationFailed;
 
-  // TODO(het): remove this and pass idGenerator directly instead
-  @deprecated
-  int getNextFreeId() => idGenerator.getNextFreeId();
-
   void unimplemented(Spannable spannable, String methodName) {
     reporter.internalError(spannable, "$methodName not implemented.");
   }
@@ -402,19 +401,19 @@
   // Compiles the dart script at [uri].
   //
   // The resulting future will complete with true if the compilation
-  // succeded.
-  Future<bool> run(Uri uri) {
-    totalCompileTime.start();
+  // succeeded.
+  Future<bool> run(Uri uri) => selfTask.measureSubtask("Compiler.run", () {
+    measurer.startWallClock();
 
     return new Future.sync(() => runInternal(uri))
         .catchError((error) => _reporter.onError(uri, error))
         .whenComplete(() {
       tracer.close();
-      totalCompileTime.stop();
+      measurer.stopWallClock();
     }).then((_) {
       return !compilationFailed;
     });
-  }
+  });
 
   /// This method is called immediately after the [LibraryElement] [library] has
   /// been created.
@@ -448,8 +447,6 @@
     if (uri == Uris.dart_core) {
       initializeCoreClasses();
       identicalFunction = coreLibrary.find('identical');
-    } else if (uri == Uris.dart__internal) {
-      symbolImplementationClass = findRequiredElement(library, 'Symbol');
     } else if (uri == Uris.dart_mirrors) {
       mirrorSystemClass = findRequiredElement(library, 'MirrorSystem');
       mirrorsUsedClass = findRequiredElement(library, 'MirrorsUsed');
@@ -524,13 +521,6 @@
     return importChains;
   }
 
-  /// Register that [uri] was recognized but disallowed as a dependency.
-  ///
-  /// For instance import of 'dart:io' without '--categories=Server'.
-  void registerDisallowedLibraryUse(Uri uri) {
-    disallowedLibraryUris.add(uri);
-  }
-
   /// This method is called when all new libraries loaded through
   /// [LibraryLoader.loadLibrary] has been loaded and their imports/exports
   /// have been computed.
@@ -541,7 +531,7 @@
   /// libraries.
   Future onLibrariesLoaded(LoadedLibraries loadedLibraries) {
     return new Future.sync(() {
-      for (Uri uri in disallowedLibraryUris) {
+      for (Uri uri in resolvedUriTranslator.disallowedLibraryUris) {
         if (loadedLibraries.containsLibrary(uri)) {
           Set<String> importChains =
               computeImportChainsFor(loadedLibraries, uri);
@@ -618,14 +608,11 @@
   // [JavaScriptBackend]. Currently needed for testing.
   String get patchVersion => backend.patchVersion;
 
+  // TODO(johnniwinther): Remove this. All elements should be looked up on
+  // demand.
   void onClassResolved(ClassElement cls) {
     if (mirrorSystemClass == cls) {
       mirrorSystemGetNameFunction = cls.lookupLocalMember('getName');
-    } else if (coreClasses.symbolClass == cls) {
-      symbolConstructor = cls.constructors.head;
-    } else if (symbolImplementationClass == cls) {
-      symbolValidatedConstructor =
-          cls.lookupConstructor(symbolValidatedConstructorSelector.name);
     } else if (mirrorsUsedClass == cls) {
       mirrorsUsedConstructor = cls.constructors.head;
     } else if (coreClasses.intClass == cls) {
@@ -813,7 +800,9 @@
   }
 
   /// Performs the compilation when all libraries have been loaded.
-  void compileLoadedLibraries() {
+  void compileLoadedLibraries()
+      => selfTask.measureSubtask("Compiler.compileLoadedLibraries", () {
+
     computeMain();
 
     mirrorUsageAnalyzerTask.analyzeUsage(mainApp);
@@ -916,7 +905,7 @@
     backend.sourceInformationStrategy.onComplete();
 
     checkQueues();
-  }
+  });
 
   void fullyEnqueueLibrary(LibraryElement library, Enqueuer world) {
     void enqueueAll(Element element) {
@@ -952,15 +941,20 @@
   /**
    * Empty the [world] queue.
    */
-  void emptyQueue(Enqueuer world) {
+  void emptyQueue(Enqueuer world)
+      => selfTask.measureSubtask("Compiler.emptyQueue", () {
     world.forEach((WorkItem work) {
-      reporter.withCurrentElement(work.element, () {
-        world.applyImpact(work.element, work.run(this, world));
-      });
+      reporter.withCurrentElement(
+          work.element, () => selfTask.measureSubtask("world.applyImpact", () {
+        world.applyImpact(
+            work.element,
+            selfTask.measureSubtask("work.run", () => work.run(this, world)));
+      }));
     });
-  }
+  });
 
-  void processQueue(Enqueuer world, Element main) {
+  void processQueue(Enqueuer world, Element main)
+      => selfTask.measureSubtask("Compiler.processQueue", () {
     world.nativeEnqueuer.processNativeClasses(libraryLoader.libraries);
     if (main != null && !main.isMalformed) {
       FunctionElement mainMethod = main;
@@ -988,7 +982,7 @@
     impactStrategy.onImpactUsed(world.impactUse);
     backend.onQueueClosed();
     assert(compilationFailed || world.checkNoEnqueuedInvokedInstanceMethods());
-  }
+  });
 
   /**
    * Perform various checks of the queues. This includes checking that
@@ -1029,7 +1023,8 @@
     }
   }
 
-  WorldImpact analyzeElement(Element element) {
+  WorldImpact analyzeElement(Element element)
+      => selfTask.measureSubtask("Compiler.analyzeElement", () {
     assert(invariant(
         element,
         element.impliesType ||
@@ -1043,9 +1038,11 @@
         message: 'Element $element is not analyzable.'));
     assert(invariant(element, element.isDeclaration));
     return resolution.computeWorldImpact(element);
-  }
+  });
 
-  WorldImpact analyze(ResolutionWorkItem work, ResolutionEnqueuer world) {
+  WorldImpact analyze(ResolutionWorkItem work,
+                      ResolutionEnqueuer world)
+      => selfTask.measureSubtask("Compiler.analyze", () {
     assert(invariant(work.element, identical(world, enqueuer.resolution)));
     assert(invariant(work.element, !work.isAnalyzed,
         message: 'Element ${work.element} has already been analyzed'));
@@ -1063,10 +1060,10 @@
       return const WorldImpact();
     }
     WorldImpact worldImpact = analyzeElement(element);
-    backend.onElementResolved(element, element.resolvedAst.elements);
+    backend.onElementResolved(element);
     world.registerProcessedElement(element);
     return worldImpact;
-  }
+  });
 
   WorldImpact codegen(CodegenWorkItem work, CodegenEnqueuer world) {
     assert(invariant(work.element, identical(world, enqueuer.codegen)));
@@ -1084,7 +1081,7 @@
       List<DiagnosticMessage> infos, api.Diagnostic kind);
 
   void reportCrashInUserCode(String message, exception, stackTrace) {
-    _reporter.onCrashInUserCode(message, exception, stackTrace);
+    reporter.onCrashInUserCode(message, exception, stackTrace);
   }
 
   /// Messages for which compile-time errors are reported but compilation
@@ -1110,26 +1107,7 @@
     if (markCompilationAsFailed(message, kind)) {
       compilationFailed = true;
     }
-  }
-
-  // TODO(sigmund): move this dart doc somewhere else too.
-  /**
-   * Translates the [resolvedUri] into a readable URI.
-   *
-   * The [importingLibrary] holds the library importing [resolvedUri] or
-   * [:null:] if [resolvedUri] is loaded as the main library. The
-   * [importingLibrary] is used to grant access to internal libraries from
-   * platform libraries and patch libraries.
-   *
-   * If the [resolvedUri] is not accessible from [importingLibrary], this method
-   * is responsible for reporting errors.
-   *
-   * See [LibraryLoader] for terminology on URIs.
-   */
-  Uri translateResolvedUri(
-      LibraryElement importingLibrary, Uri resolvedUri, Spannable spannable) {
-    unimplemented(importingLibrary, 'Compiler.translateResolvedUri');
-    return null;
+    registerCompiletimeError(currentElement, message);
   }
 
   /**
@@ -1255,6 +1233,7 @@
   }
 
   void forgetElement(Element element) {
+    resolution.forgetElement(element);
     enqueuer.forgetElement(element);
     if (element is MemberElement) {
       for (Element closure in element.nestedClosures) {
@@ -1265,8 +1244,24 @@
     backend.forgetElement(element);
   }
 
+  /// Returns [true] if a compile-time error has been reported for element.
   bool elementHasCompileTimeError(Element element) {
-    return elementsWithCompileTimeErrors.contains(element);
+    return elementsWithCompileTimeErrors.containsKey(element);
+  }
+
+  /// Associate [element] with a compile-time error [message].
+  void registerCompiletimeError(Element element, DiagnosticMessage message) {
+    // The information is only needed if [generateCodeWithCompileTimeErrors].
+    if (options.generateCodeWithCompileTimeErrors) {
+      if (element == null) {
+        // Record as global error.
+        // TODO(zarah): Extend element model to represent compile-time
+        // errors instead of using a map.
+        element = mainFunction;
+      }
+      elementsWithCompileTimeErrors.
+          putIfAbsent(element, () => <DiagnosticMessage>[]).add(message);
+    }
   }
 
   EventSink<String> outputProvider(String name, String extension) {
@@ -1438,7 +1433,7 @@
   }
 }
 
-class _CompilerDiagnosticReporter extends DiagnosticReporter {
+class CompilerDiagnosticReporter extends DiagnosticReporter {
   final Compiler compiler;
   final DiagnosticOptions options;
 
@@ -1453,7 +1448,7 @@
   /// suppressed for each library.
   Map<Uri, SuppressionInfo> suppressedWarnings = <Uri, SuppressionInfo>{};
 
-  _CompilerDiagnosticReporter(this.compiler, this.options);
+  CompilerDiagnosticReporter(this.compiler, this.options);
 
   Element get currentElement => _currentElement;
 
@@ -1529,6 +1524,13 @@
     if (kind == api.Diagnostic.ERROR ||
         kind == api.Diagnostic.CRASH ||
         (options.fatalWarnings && kind == api.Diagnostic.WARNING)) {
+      Element errorElement;
+      if (message.spannable is Element) {
+        errorElement = message.spannable;
+      } else {
+        errorElement = currentElement;
+      }
+      compiler.registerCompiletimeError(errorElement, message);
       compiler.fatalDiagnosticReported(message, infos, kind);
     }
   }
@@ -1818,6 +1820,7 @@
     throw error;
   }
 
+  @override
   void onCrashInUserCode(String message, exception, stackTrace) {
     hasCrashed = true;
     print('$message: ${tryToString(exception)}');
@@ -1858,7 +1861,7 @@
   DiagnosticReporter get reporter => compiler.reporter;
 
   @override
-  Parsing get parsing => compiler.parsing;
+  ParsingContext get parsingContext => compiler.parsingContext;
 
   @override
   CoreTypes get coreTypes => compiler.coreTypes;
@@ -1894,7 +1897,20 @@
   }
 
   @override
+  void ensureResolved(Element element) {
+    if (compiler.serialization.isDeserialized(element)) {
+      return;
+    }
+    computeWorldImpact(element);
+  }
+
+  @override
   bool hasResolvedAst(Element element) {
+    assert(invariant(element, element.isDeclaration,
+        message: "Element $element must be the declaration."));
+    if (compiler.serialization.isDeserialized(element)) {
+      return compiler.serialization.hasResolvedAst(element);
+    }
     return element is AstElement &&
         hasBeenResolved(element) &&
         element.hasResolvedAst;
@@ -1902,7 +1918,12 @@
 
   @override
   ResolvedAst getResolvedAst(Element element) {
+    assert(invariant(element, element.isDeclaration,
+        message: "Element $element must be the declaration."));
     if (hasResolvedAst(element)) {
+      if (compiler.serialization.isDeserialized(element)) {
+        return compiler.serialization.getResolvedAst(element);
+      }
       AstElement astElement = element;
       return astElement.resolvedAst;
     }
@@ -1911,15 +1932,32 @@
     return null;
   }
 
+  @override
+  ResolvedAst computeResolvedAst(Element element) {
+    ensureResolved(element);
+    return getResolvedAst(element);
+  }
 
   @override
   bool hasResolutionImpact(Element element) {
+    assert(invariant(element, element.isDeclaration,
+        message: "Element $element must be the declaration."));
+    if (compiler.serialization.isDeserialized(element)) {
+      return compiler.serialization.hasResolutionImpact(element);
+    }
     return _resolutionImpactCache.containsKey(element);
   }
 
   @override
   ResolutionImpact getResolutionImpact(Element element) {
-    ResolutionImpact resolutionImpact = _resolutionImpactCache[element];
+    assert(invariant(element, element.isDeclaration,
+        message: "Element $element must be the declaration."));
+    ResolutionImpact resolutionImpact;
+    if (compiler.serialization.isDeserialized(element)) {
+      resolutionImpact = compiler.serialization.getResolutionImpact(element);
+    } else {
+      resolutionImpact = _resolutionImpactCache[element];
+    }
     assert(invariant(element, resolutionImpact != null,
         message: "ResolutionImpact not available for $element."));
     return resolutionImpact;
@@ -1927,6 +1965,8 @@
 
   @override
   WorldImpact getWorldImpact(Element element) {
+    assert(invariant(element, element.isDeclaration,
+        message: "Element $element must be the declaration."));
     WorldImpact worldImpact = _worldImpactCache[element];
     assert(invariant(element, worldImpact != null,
         message: "WorldImpact not computed for $element."));
@@ -1935,11 +1975,14 @@
 
   @override
   WorldImpact computeWorldImpact(Element element) {
+    assert(invariant(element, element.isDeclaration,
+        message: "Element $element must be the declaration."));
     return _worldImpactCache.putIfAbsent(element, () {
       assert(compiler.parser != null);
       Node tree = compiler.parser.parse(element);
       assert(invariant(element, !element.isSynthesized || tree == null));
       ResolutionImpact resolutionImpact = compiler.resolver.resolve(element);
+
       if (compiler.serialization.supportSerialization ||
           retainCachesForTesting) {
         // [ResolutionImpact] is currently only used by serialization. The
@@ -1963,6 +2006,8 @@
 
   @override
   void uncacheWorldImpact(Element element) {
+    assert(invariant(element, element.isDeclaration,
+        message: "Element $element must be the declaration."));
     if (retainCachesForTesting) return;
     if (compiler.serialization.isDeserialized(element)) return;
     assert(invariant(element, _worldImpactCache[element] != null,
@@ -1995,34 +2040,12 @@
       return new ResolutionWorkItem(element, compilationContext);
     }
   }
-}
-
-// TODO(johnniwinther): Move [ParserTask], [PatchParserTask], [DietParserTask]
-// and [ScannerTask] here.
-class _CompilerParsing implements Parsing {
-  final Compiler compiler;
-
-  _CompilerParsing(this.compiler);
 
   @override
-  DiagnosticReporter get reporter => compiler.reporter;
-
-  @override
-  measure(f()) => compiler.parser.measure(f);
-
-  @override
-  void parsePatchClass(ClassElement cls) {
-    compiler.patchParser.measure(() {
-      if (cls.isPatch) {
-        compiler.patchParser.parsePatchClassNode(cls);
-      }
-    });
+  void forgetElement(Element element) {
+    _worldImpactCache.remove(element);
+    _resolutionImpactCache.remove(element);
   }
-
-  ScannerOptions getScannerOptionsFor(Element element) =>
-      new ScannerOptions.from(compiler, element.library);
-
-  ParserOptions get parserOptions => compiler.options;
 }
 
 class GlobalDependencyRegistry extends EagerRegistry {
@@ -2049,17 +2072,6 @@
   }
 }
 
-// TODO(sigmund): in the future, each of these classes should be self contained
-// and not use references to `compiler`.
-class _ResolvedUriTranslator implements ResolvedUriTranslator {
-  Compiler compiler;
-  _ResolvedUriTranslator(this.compiler);
-
-  Uri translate(LibraryElement importingLibrary, Uri resolvedUri,
-          [Spannable spannable]) =>
-      compiler.translateResolvedUri(importingLibrary, resolvedUri, spannable);
-}
-
 class _ScriptLoader implements ScriptLoader {
   Compiler compiler;
   _ScriptLoader(this.compiler);
diff --git a/pkg/compiler/lib/src/constants/constructors.dart b/pkg/compiler/lib/src/constants/constructors.dart
index c2b53fc..b8e7471 100644
--- a/pkg/compiler/lib/src/constants/constructors.dart
+++ b/pkg/compiler/lib/src/constants/constructors.dart
@@ -5,7 +5,7 @@
 library dart2js.constants.constructors;
 
 import '../dart_types.dart';
-import '../elements/elements.dart' show ConstructorElement, FieldElement;
+import '../elements/elements.dart' show FieldElement;
 import '../universe/call_structure.dart' show CallStructure;
 import '../util/util.dart';
 import 'evaluation.dart';
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
index 809d7e0..d476dd6b 100644
--- a/pkg/compiler/lib/src/constants/expressions.dart
+++ b/pkg/compiler/lib/src/constants/expressions.dart
@@ -11,7 +11,6 @@
 import '../elements/elements.dart'
     show
         ConstructorElement,
-        Element,
         FieldElement,
         FunctionElement,
         PrefixElement,
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index 1cc0271..40bda63 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -8,7 +8,7 @@
 import '../core_types.dart';
 import '../dart_types.dart';
 import '../elements/elements.dart'
-    show ClassElement, Element, FieldElement, FunctionElement, PrefixElement;
+    show FieldElement, FunctionElement, PrefixElement;
 import '../tree/tree.dart' hide unparse;
 import '../util/util.dart' show Hashing;
 
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 7927ba0..dd756c6 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
@@ -6,10 +6,10 @@
 
 import '../closure.dart' as closure;
 import '../common.dart';
-import '../common/names.dart' show Names, Selectors;
+import '../common/names.dart' show Selectors;
 import '../compile_time_constants.dart' show BackendConstantEnvironment;
 import '../constants/constant_system.dart';
-import '../constants/values.dart' show ConstantValue, PrimitiveConstantValue;
+import '../constants/values.dart' show ConstantValue;
 import '../dart_types.dart';
 import '../elements/elements.dart';
 import '../io/source_information.dart';
@@ -27,7 +27,6 @@
 import '../types/types.dart' show TypeMask;
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector, SelectorKind;
-
 import 'cps_ir_builder_task.dart' show GlobalProgramInformation;
 import 'cps_ir_nodes.dart' as ir;
 
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 e9d1845..bc77a98 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
@@ -4,44 +4,39 @@
 
 library dart2js.ir_builder_task;
 
+import 'package:js_runtime/shared/embedded_names.dart'
+    show JsBuiltin, JsGetName;
+
 import '../closure.dart' as closure;
 import '../common.dart';
 import '../common/names.dart' show Identifiers, Names, Selectors;
 import '../common/tasks.dart' show CompilerTask;
 import '../compiler.dart' show Compiler;
 import '../constants/expressions.dart';
+import '../constants/values.dart' show ConstantValue;
+import '../constants/values.dart';
 import '../dart_types.dart';
 import '../elements/elements.dart';
-import '../elements/modelx.dart'
-    show
-        SynthesizedConstructorElementX,
-        ConstructorBodyElementX,
-        FunctionSignatureX;
+import '../elements/modelx.dart' show ConstructorBodyElementX;
 import '../io/source_information.dart';
+import '../js/js.dart' as js show js, Template, Expression, Name;
 import '../js_backend/backend_helpers.dart' show BackendHelpers;
 import '../js_backend/js_backend.dart'
     show JavaScriptBackend, SyntheticConstantKind;
-import '../resolution/tree_elements.dart' show TreeElements;
-import '../resolution/semantic_visitor.dart';
+import '../native/native.dart' show NativeBehavior, HasCapturedPlaceholders;
 import '../resolution/operators.dart' as op;
+import '../resolution/semantic_visitor.dart';
+import '../resolution/tree_elements.dart' show TreeElements;
+import '../ssa/types.dart' show TypeMaskFactory;
 import '../tree/tree.dart' as ast;
 import '../types/types.dart' show TypeMask;
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
-import '../constants/values.dart' show ConstantValue;
-import 'cps_ir_nodes.dart' as ir;
-import 'cps_ir_builder.dart';
-import '../native/native.dart' show NativeBehavior, HasCapturedPlaceholders;
-
-// TODO(karlklose): remove.
-import '../js/js.dart' as js show js, Template, Expression, Name;
-import '../ssa/types.dart' show TypeMaskFactory;
 import '../util/util.dart';
-
-import 'package:js_runtime/shared/embedded_names.dart'
-    show JsBuiltin, JsGetName;
-import '../constants/values.dart';
+import 'cps_ir_builder.dart';
+import 'cps_ir_nodes.dart' as ir;
 import 'type_mask_system.dart' show TypeMaskSystem;
+// TODO(karlklose): remove.
 
 typedef void IrBuilderCallback(Element element, ir.FunctionDefinition irNode);
 
@@ -79,14 +74,14 @@
     return measure(() {
       bailoutMessage = null;
 
-      TreeElements elementsMapping = element.resolvedAst.elements;
+      ResolvedAst resolvedAst = element.resolvedAst;
       element = element.implementation;
       return reporter.withCurrentElement(element, () {
         SourceInformationBuilder sourceInformationBuilder =
             sourceInformationStrategy.createBuilderForContext(element);
 
-        IrBuilderVisitor builder = new IrBuilderVisitor(elementsMapping,
-            compiler, sourceInformationBuilder, typeMaskSystem);
+        IrBuilderVisitor builder = new IrBuilderVisitor(
+            resolvedAst, compiler, sourceInformationBuilder, typeMaskSystem);
         ir.FunctionDefinition irNode = builder.buildExecutable(element);
         if (irNode == null) {
           bailoutMessage = builder.bailoutMessage;
@@ -123,7 +118,7 @@
         BaseImplementationOfIndexCompoundsMixin<ir.Primitive, dynamic>,
         BaseImplementationOfSuperIndexSetIfNullMixin<ir.Primitive, dynamic>
     implements SemanticSendVisitor<ir.Primitive, dynamic> {
-  final TreeElements elements;
+  final ResolvedAst resolvedAst;
   final Compiler compiler;
   final SourceInformationBuilder sourceInformationBuilder;
   final TypeMaskSystem typeMaskSystem;
@@ -155,8 +150,10 @@
   // arguments, and what the arguments are.
 
   /// Construct a top-level visitor.
-  IrBuilderVisitor(this.elements, this.compiler, this.sourceInformationBuilder,
-      this.typeMaskSystem);
+  IrBuilderVisitor(this.resolvedAst, this.compiler,
+      this.sourceInformationBuilder, this.typeMaskSystem);
+
+  TreeElements get elements => resolvedAst.elements;
 
   JavaScriptBackend get backend => compiler.backend;
   BackendHelpers get helpers => backend.helpers;
@@ -193,7 +190,7 @@
   /// one currently being built.
   ClosureScope getClosureScopeForFunction(FunctionElement function) {
     closure.ClosureClassMap map = compiler.closureToClassMapper
-        .computeClosureToClassMapping(function, function.node, elements);
+        .computeClosureToClassMapping(function.resolvedAst);
     return new ClosureScope(map.capturingScopes[function.node]);
   }
 
@@ -505,7 +502,7 @@
   /// Every visitor can only be applied to nodes in one context, because
   /// the [elements] field is specific to that context.
   IrBuilderVisitor makeVisitorForContext(AstElement context) {
-    return new IrBuilderVisitor(context.resolvedAst.elements, compiler,
+    return new IrBuilderVisitor(context.resolvedAst, compiler,
         sourceInformationBuilder.forContext(context), typeMaskSystem);
   }
 
@@ -545,7 +542,7 @@
   void loadArguments(ConstructorElement target, CallStructure call,
       List<ir.Primitive> arguments) {
     assert(target.isImplementation);
-    assert(target == elements.analyzedElement);
+    assert(target.declaration == resolvedAst.element);
     FunctionSignature signature = target.functionSignature;
 
     // Establish a scope in case parameters are captured.
@@ -620,7 +617,7 @@
       List<ConstructorElement> supers,
       Map<FieldElement, ir.Primitive> fieldValues) {
     assert(constructor.isImplementation);
-    assert(constructor == elements.analyzedElement);
+    assert(constructor.declaration == resolvedAst.element);
     ClassElement enclosingClass = constructor.enclosingClass.implementation;
     // Evaluate declaration-site field initializers, unless this constructor
     // redirects to another using a `this()` initializer. In that case, these
@@ -714,7 +711,7 @@
     ConstructorElement constructor = body.constructor;
     ast.FunctionExpression node = constructor.node;
     closureClassMap = compiler.closureToClassMapper
-        .computeClosureToClassMapping(constructor, node, elements);
+        .computeClosureToClassMapping(constructor.resolvedAst);
 
     // We compute variables boxed in mutable variables on entry to each try
     // block, not including variables captured by a closure (which are boxed
@@ -745,7 +742,7 @@
     assert(elements[node] != null);
 
     closureClassMap = compiler.closureToClassMapper
-        .computeClosureToClassMapping(element, node, elements);
+        .computeClosureToClassMapping(element.resolvedAst);
     TryBoxedVariables variables = _analyzeTryBoxedVariables(node);
     tryStatements = variables.tryStatements;
     IrBuilder builder = getBuilderFor(element);
@@ -758,7 +755,7 @@
       return null; // Nothing to do.
     }
     closureClassMap = compiler.closureToClassMapper
-        .computeClosureToClassMapping(element, element.node, elements);
+        .computeClosureToClassMapping(element.resolvedAst);
     IrBuilder builder = getBuilderFor(element);
     return withBuilder(builder, () {
       irBuilder.buildFunctionHeader(<Local>[]);
@@ -908,7 +905,6 @@
       //
       assert(parameters.length == 1 || parameters.length == 2);
       ir.Primitive allocation = irBuilder.buildLocalGet(parameters[0]);
-      ClassElement classElement = element.enclosingElement;
 
       // Only call setRuntimeTypeInfo if JSArray requires the type parameter.
       if (requiresRuntimeTypes) {
@@ -1130,7 +1126,7 @@
         <ir.Primitive>[stream, dummyTypeArgument],
         sourceInformationBuilder.buildGeneric(node)));
 
-    ir.Node buildTryBody(IrBuilder builder) {
+    buildTryBody(IrBuilder builder) {
       ir.Node buildLoopCondition(IrBuilder builder) {
         ir.Primitive moveNext = builder.buildDynamicInvocation(
             iterator,
@@ -2271,7 +2267,7 @@
       // libraries contain a dummy const constructor implementation that
       // doesn't perform validation and the compiler compiles a call to
       // (non-const) Symbol.validated when it sees new Symbol(...).
-      target = compiler.symbolValidatedConstructor;
+      target = helpers.symbolValidatedConstructor;
     } else {
       target = constructor.implementation;
     }
@@ -3201,8 +3197,7 @@
     }
 
     Link<ast.Node> argumentNodes = argumentList.nodes;
-    NativeBehavior behavior =
-        compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
+    NativeBehavior behavior = elements.getNativeData(node);
     switch (function.name) {
       case 'JS':
         validateArgumentCount(minimum: 2);
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 3e82f93..7ba13c8 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
@@ -2098,10 +2098,6 @@
 //                            UTILITY STUFF
 // ----------------------------------------------------------------------------
 
-Reference<Primitive> _reference(Primitive definition) {
-  return new Reference<Primitive>(definition);
-}
-
 Reference<Primitive> _optionalReference(Primitive definition) {
   return definition == null ? null : new Reference<Primitive>(definition);
 }
diff --git a/pkg/compiler/lib/src/cps_ir/inline.dart b/pkg/compiler/lib/src/cps_ir/inline.dart
index cbb673d..9454e38 100644
--- a/pkg/compiler/lib/src/cps_ir/inline.dart
+++ b/pkg/compiler/lib/src/cps_ir/inline.dart
@@ -4,21 +4,21 @@
 
 library cps_ir.optimization.inline;
 
+import 'package:js_ast/js_ast.dart' as js;
+
+import '../dart_types.dart' show DartType, GenericType;
+import '../elements/elements.dart';
+import '../js_backend/codegen/task.dart' show CpsFunctionCompiler;
+import '../js_backend/js_backend.dart' show JavaScriptBackend;
+import '../types/types.dart' show TypeMask;
+import '../universe/call_structure.dart' show CallStructure;
+import '../universe/selector.dart' show Selector;
+import '../world.dart' show World;
 import 'cps_fragment.dart';
 import 'cps_ir_builder.dart' show ThisParameterLocal;
 import 'cps_ir_nodes.dart';
 import 'optimizers.dart';
 import 'type_mask_system.dart' show TypeMaskSystem;
-import '../dart_types.dart' show DartType, GenericType;
-import '../world.dart' show World;
-import '../elements/elements.dart';
-import '../js_backend/js_backend.dart' show JavaScriptBackend;
-import '../js_backend/codegen/task.dart' show CpsFunctionCompiler;
-import '../types/types.dart'
-    show FlatTypeMask, ForwardingTypeMask, TypeMask, UnionTypeMask;
-import '../universe/call_structure.dart' show CallStructure;
-import '../universe/selector.dart' show Selector;
-import 'package:js_ast/js_ast.dart' as js;
 
 /// Inlining stack entries.
 ///
@@ -211,7 +211,8 @@
     // Do not inline in functions containing try statements.  V8 does not
     // optimize code in such functions, so inlining will move optimizable code
     // into a context where it cannot be optimized.
-    if (function.resolvedAst.elements.containsTryStatement) {
+    if (function.resolvedAst.kind == ResolvedAstKind.PARSED &&
+        function.resolvedAst.elements.containsTryStatement) {
       return;
     }
 
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 c77bd02..a2bb010 100644
--- a/pkg/compiler/lib/src/cps_ir/type_mask_system.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_mask_system.dart
@@ -4,7 +4,8 @@
 
 library dart2js.type_mask_system;
 
-import '../common/names.dart' show Selectors, Identifiers;
+import '../closure.dart' show ClosureFieldElement, BoxLocal, TypeVariableLocal;
+import '../common/names.dart' show Identifiers;
 import '../compiler.dart' as dart2js show Compiler;
 import '../constants/values.dart';
 import '../dart_types.dart' as types;
@@ -12,11 +13,10 @@
 import '../js_backend/backend_helpers.dart' show BackendHelpers;
 import '../js_backend/js_backend.dart' show JavaScriptBackend;
 import '../types/abstract_value_domain.dart';
-import '../types/types.dart';
 import '../types/constants.dart' show computeTypeMask;
+import '../types/types.dart';
 import '../universe/selector.dart' show Selector;
 import '../world.dart' show World;
-import '../closure.dart' show ClosureFieldElement, BoxLocal, TypeVariableLocal;
 
 class TypeMaskSystem implements AbstractValueDomain {
   final TypesTask inferrer;
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 0518e488..336dfc6 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -4,28 +4,20 @@
 
 library dart2js.cmdline;
 
-import 'dart:async' show Future, EventSink;
+import 'dart:async' show Future;
 import 'dart:convert' show UTF8, LineSplitter;
-import 'dart:io'
-    show
-        exit,
-        File,
-        FileMode,
-        Platform,
-        RandomAccessFile,
-        FileSystemException,
-        stdin,
-        stderr;
+import 'dart:io' show exit, File, FileMode, Platform, stdin, stderr;
+
+import 'package:package_config/discovery.dart' show findPackages;
 
 import '../compiler.dart' as api;
 import 'commandline_options.dart';
+import 'filenames.dart';
 import 'io/source_file.dart';
 import 'source_file_provider.dart';
-import 'filenames.dart';
+import 'util/command_line.dart';
 import 'util/uri_extras.dart';
 import 'util/util.dart' show stackTraceFilePrefix;
-import 'util/command_line.dart';
-import 'package:package_config/discovery.dart' show findPackages;
 
 const String LIBRARY_ROOT = '../../../../../sdk';
 const String OUTPUT_LANGUAGE_DART = 'Dart';
diff --git a/pkg/compiler/lib/src/dart_backend/backend.dart b/pkg/compiler/lib/src/dart_backend/backend.dart
index 8d9d0cc..3501182 100644
--- a/pkg/compiler/lib/src/dart_backend/backend.dart
+++ b/pkg/compiler/lib/src/dart_backend/backend.dart
@@ -236,7 +236,7 @@
     if (useMirrorHelperLibrary &&
         loadedLibraries.containsLibrary(Uris.dart_mirrors)) {
       return compiler.libraryLoader
-          .loadLibrary(compiler.translateResolvedUri(
+          .loadLibrary(compiler.resolvedUriTranslator.translate(
               loadedLibraries.getLibrary(Uris.dart_mirrors),
               MirrorRenamerImpl.DART_MIRROR_HELPER,
               null))
@@ -317,7 +317,6 @@
             superclass.forEachLocalMember((MemberElement element) {
               if (element.isConstructor || element.isStatic) return;
 
-              FunctionElement function = element.asFunctionElement();
               element.computeType(resolution);
               Selector selector = new Selector.fromElement(element);
               registerUse(new DynamicUse(selector, null));
diff --git a/pkg/compiler/lib/src/dart_backend/backend_ast_to_frontend_ast.dart b/pkg/compiler/lib/src/dart_backend/backend_ast_to_frontend_ast.dart
index 1ab7882..81eae70 100644
--- a/pkg/compiler/lib/src/dart_backend/backend_ast_to_frontend_ast.dart
+++ b/pkg/compiler/lib/src/dart_backend/backend_ast_to_frontend_ast.dart
@@ -1106,7 +1106,7 @@
           bound =
               makeType(TypeGenerator.createType(typeVariable.element.bound));
         }
-        tree.TypeVariable node = new tree.TypeVariable(id, bound);
+        tree.TypeVariable node = new tree.TypeVariable(id, extendsToken, bound);
         treeElements.setType(node, typeVariable);
         typeVariableList.add(node);
       }
diff --git a/pkg/compiler/lib/src/dart_types.dart b/pkg/compiler/lib/src/dart_types.dart
index 41ce1e5..685077d 100644
--- a/pkg/compiler/lib/src/dart_types.dart
+++ b/pkg/compiler/lib/src/dart_types.dart
@@ -6,12 +6,11 @@
 
 import 'dart:math' show min;
 
-import 'common.dart';
 import 'common/resolution.dart' show Resolution;
+import 'common.dart';
 import 'core_types.dart';
-import 'elements/modelx.dart'
-    show LibraryElementX, TypeDeclarationElementX, TypedefElementX;
 import 'elements/elements.dart';
+import 'elements/modelx.dart' show TypeDeclarationElementX;
 import 'ordered_typeset.dart' show OrderedTypeSet;
 import 'util/util.dart' show equalElements;
 
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 0d377aa..5ce0d30 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -4,9 +4,9 @@
 
 library deferred_load;
 
-import 'common.dart';
 import 'common/backend_api.dart' show Backend;
 import 'common/tasks.dart' show CompilerTask;
+import 'common.dart';
 import 'compiler.dart' show Compiler;
 import 'constants/values.dart'
     show
@@ -21,31 +21,21 @@
         AstElement,
         ClassElement,
         Element,
-        ElementKind,
         Elements,
         ExportElement,
         FunctionElement,
         ImportElement,
         LibraryElement,
-        LocalFunctionElement,
         MetadataAnnotation,
         PrefixElement,
-        ScopeContainerElement,
+        ResolvedAstKind,
         TypedefElement;
 import 'js_backend/js_backend.dart' show JavaScriptBackend;
 import 'resolution/resolution.dart' show AnalyzableElementX;
 import 'resolution/tree_elements.dart' show TreeElements;
 import 'tree/tree.dart' as ast;
-import 'tree/tree.dart'
-    show
-        Import,
-        LibraryTag,
-        LibraryDependency,
-        LiteralDartString,
-        LiteralString,
-        NewExpression,
-        Node;
-import 'universe/use.dart' show DynamicUse, StaticUse, TypeUse, TypeUseKind;
+import 'tree/tree.dart' show Import, Node;
+import 'universe/use.dart' show StaticUse, TypeUse, TypeUseKind;
 import 'universe/world_impact.dart'
     show ImpactUseCase, WorldImpact, WorldImpactVisitorImpl;
 import 'util/setlet.dart' show Setlet;
@@ -337,6 +327,10 @@
             }),
             IMPACT_USE);
 
+        if (analyzableElement.resolvedAst.kind != ResolvedAstKind.PARSED) {
+          return;
+        }
+
         TreeElements treeElements = analyzableElement.resolvedAst.elements;
         assert(treeElements != null);
 
diff --git a/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart b/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart
index 3cb959f..e31edde 100644
--- a/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart
+++ b/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart
@@ -60,6 +60,10 @@
 
   DiagnosticMessage createMessage(Spannable spannable, MessageKind messageKind,
       [Map arguments = const {}]);
+
+  /// Called when an [exception] is thrown from user-provided code, like from
+  /// the input provider or diagnostics handler.
+  void onCrashInUserCode(String message, exception, stackTrace) {}
 }
 
 class DiagnosticMessage {
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 726d914..854feb1 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -5,21 +5,21 @@
 library dump_info;
 
 import 'dart:convert'
-    show ChunkedConversionSink, HtmlEscape, JsonEncoder, StringConversionSink;
+    show ChunkedConversionSink, JsonEncoder, StringConversionSink;
 
 import 'package:dart2js_info/info.dart';
 
-import 'common.dart';
 import 'common/tasks.dart' show CompilerTask;
-import 'constants/values.dart' show ConstantValue, InterceptorConstantValue;
+import 'common.dart';
 import 'compiler.dart' show Compiler;
+import 'constants/values.dart' show ConstantValue, InterceptorConstantValue;
 import 'deferred_load.dart' show OutputUnit;
 import 'elements/elements.dart';
 import 'elements/visitor.dart';
 import 'info/send_info.dart' show collectSendMeasurements;
+import 'js/js.dart' as jsAst;
 import 'js_backend/js_backend.dart' show JavaScriptBackend;
 import 'js_emitter/full_emitter/emitter.dart' as full show Emitter;
-import 'js/js.dart' as jsAst;
 import 'types/types.dart' show TypeMask;
 import 'universe/universe.dart' show ReceiverConstraint;
 import 'universe/world_impact.dart'
@@ -579,7 +579,7 @@
         dart2jsVersion:
             compiler.options.hasBuildId ? compiler.options.buildId : null,
         compilationMoment: new DateTime.now(),
-        compilationDuration: compiler.totalCompileTime.elapsed,
+        compilationDuration: compiler.measurer.wallClock.elapsed,
         toJsonDuration: stopwatch.elapsedMilliseconds,
         dumpInfoDuration: this.timing,
         noSuchMethodEnabled: compiler.backend.enabledNoSuchMethod,
diff --git a/pkg/compiler/lib/src/elements/common.dart b/pkg/compiler/lib/src/elements/common.dart
index bbc682a..9cdce47 100644
--- a/pkg/compiler/lib/src/elements/common.dart
+++ b/pkg/compiler/lib/src/elements/common.dart
@@ -88,6 +88,13 @@
   bool get impliesType => (kind.category & ElementCategory.IMPLIES_TYPE) != 0;
 
   @override
+  bool get isAssignable {
+    if (isFinal || isConst) return false;
+    if (isFunction || isConstructor) return false;
+    return true;
+  }
+
+  @override
   Element get declaration => this;
 
   @override
@@ -130,6 +137,20 @@
     }
     return cls;
   }
+
+  @override
+  Element get outermostEnclosingMemberOrTopLevel {
+    // TODO(lrn): Why is this called "Outermost"?
+    // TODO(johnniwinther): Clean up this method: This method does not return
+    // the outermost for elements in closure classses, but some call-sites rely
+    // on that behavior.
+    for (Element e = this; e != null; e = e.enclosingElement) {
+      if (e.isClassMember || e.isTopLevel) {
+        return e;
+      }
+    }
+    return null;
+  }
 }
 
 abstract class LibraryElementCommon implements LibraryElement {
@@ -455,8 +476,6 @@
     optionalParameters.forEach(function);
   }
 
-  Element get firstOptionalParameter => optionalParameters.first;
-
   void forEachParameter(void function(Element parameter)) {
     forEachRequiredParameter(function);
     forEachOptionalParameter(function);
diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart
index 86a5f41..54ecf63 100644
--- a/pkg/compiler/lib/src/elements/elements.dart
+++ b/pkg/compiler/lib/src/elements/elements.dart
@@ -1106,7 +1106,6 @@
   int get requiredParameterCount;
   int get optionalParameterCount;
   bool get optionalParametersAreNamed;
-  FormalElement get firstOptionalParameter;
   bool get hasOptionalParameters;
 
   int get parameterCount;
@@ -1196,6 +1195,21 @@
   String toString() {
     return '${isAsync ? 'async' : 'sync'}${isYielding ? '*' : ''}';
   }
+
+  /// Canonical list of marker values.
+  ///
+  /// Added to make [AsyncMarker] enum-like.
+  static const List<AsyncMarker> values = const <AsyncMarker>[
+    SYNC,
+    SYNC_STAR,
+    ASYNC,
+    ASYNC_STAR
+  ];
+
+  /// Index to this marker within [values].
+  ///
+  /// Added to make [AsyncMarker] enum-like.
+  int get index => values.indexOf(this);
 }
 
 /// A top level, static or instance function.
@@ -1626,14 +1640,86 @@
   ResolvedAst get resolvedAst;
 }
 
-class ResolvedAst {
+/// Enum values for different ways of defining semantics for an element.
+enum ResolvedAstKind {
+  /// The semantics of the element is defined in terms of an AST with resolved
+  /// data mapped in [TreeElements].
+  PARSED,
+
+  /// The element is an implicit default constructor. No AST or [TreeElements]
+  /// are provided.
+  DEFAULT_CONSTRUCTOR,
+
+  /// The element is an implicit forwarding constructor on a mixin application.
+  /// No AST or [TreeElements] are provided.
+  FORWARDING_CONSTRUCTOR,
+}
+
+/// [ResolvedAst] contains info that define the semantics of an element.
+abstract class ResolvedAst {
+  /// The element whose semantics is defined.
+  Element get element;
+
+  /// The kind of semantics definition used for this object.
+  ResolvedAstKind get kind;
+
+  /// The root AST node for the declaration of [element]. This only available if
+  /// [kind] is `ResolvedAstKind.PARSED`.
+  Node get node;
+
+  /// The AST node for the 'body' of [element].
+  ///
+  /// For functions and constructors this is the root AST node of the method
+  /// body, and for variables this is the root AST node of the initializer, if
+  /// available.
+  ///
+  /// This only available if [kind] is `ResolvedAstKind.PARSED`.
+  Node get body;
+
+  /// The [TreeElements] containing the resolution data for [node]. This only
+  /// available of [kind] is `ResolvedAstKind.PARSED`.
+  TreeElements get elements;
+}
+
+/// [ResolvedAst] implementation used for elements whose semantics is defined in
+/// terms an AST and a [TreeElements].
+class ParsedResolvedAst implements ResolvedAst {
   final Element element;
   final Node node;
+  final Node body;
   final TreeElements elements;
 
-  ResolvedAst(this.element, this.node, this.elements);
+  ParsedResolvedAst(this.element, this.node, this.body, this.elements);
 
-  String toString() => '$element:$node';
+  ResolvedAstKind get kind => ResolvedAstKind.PARSED;
+
+  String toString() => '$kind:$element:$node';
+}
+
+/// [ResolvedAst] implementation used for synthesized elements whose semantics
+/// is not defined in terms an AST and a [TreeElements].
+class SynthesizedResolvedAst implements ResolvedAst {
+  final Element element;
+  final ResolvedAstKind kind;
+
+  SynthesizedResolvedAst(this.element, this.kind);
+
+  @override
+  TreeElements get elements {
+    throw new UnsupportedError('$this does not provide a TreeElements');
+  }
+
+  @override
+  Node get node {
+    throw new UnsupportedError('$this does not have a root AST node');
+  }
+
+  @override
+  Node get body {
+    throw new UnsupportedError('$this does not have a body AST node');
+  }
+
+  String toString() => '$kind:$element';
 }
 
 /// A [MemberSignature] is a member of an interface.
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index fe64aec..5a4cc108 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -5,7 +5,7 @@
 library elements.modelx;
 
 import '../common.dart';
-import '../common/resolution.dart' show Resolution, Parsing;
+import '../common/resolution.dart' show Resolution, ParsingContext;
 import '../compiler.dart' show Compiler;
 import '../constants/constant_constructors.dart';
 import '../constants/constructors.dart';
@@ -52,7 +52,7 @@
 
   Modifiers get modifiers => Modifiers.EMPTY;
 
-  Node parseNode(Parsing parsing) {
+  Node parseNode(ParsingContext parsing) {
     parsing.reporter.internalError(this, 'parseNode not implemented on $this.');
     return null;
   }
@@ -109,12 +109,6 @@
     return enclosingElement != null && enclosingElement.isCompilationUnit;
   }
 
-  bool get isAssignable {
-    if (isFinal || isConst) return false;
-    if (isFunction || isConstructor) return false;
-    return true;
-  }
-
   Token get position => null;
 
   SourceSpan get sourcePosition {
@@ -177,19 +171,6 @@
     return null;
   }
 
-  Element get outermostEnclosingMemberOrTopLevel {
-    // TODO(lrn): Why is this called "Outermost"?
-    // TODO(johnniwinther): Clean up this method: This method does not return
-    // the outermost for elements in closure classses, but some call-sites rely
-    // on that behavior.
-    for (Element e = this; e != null; e = e.enclosingElement) {
-      if (e.isClassMember || e.isTopLevel) {
-        return e;
-      }
-    }
-    return null;
-  }
-
   /**
    * Creates the scope for this element.
    */
@@ -1328,7 +1309,7 @@
 
   TypedefType computeType(Resolution resolution) {
     if (thisTypeCache != null) return thisTypeCache;
-    Typedef node = parseNode(resolution.parsing);
+    Typedef node = parseNode(resolution.parsingContext);
     setThisAndRawTypes(createTypeVariables(node.typeParameters));
     ensureResolved(resolution);
     return thisTypeCache;
@@ -1401,7 +1382,7 @@
     metadataInternal = metadata;
   }
 
-  VariableDefinitions parseNode(Element element, Parsing parsing) {
+  VariableDefinitions parseNode(Element element, ParsingContext parsing) {
     return definitions;
   }
 
@@ -1480,7 +1461,7 @@
     return initializerCache;
   }
 
-  Node parseNode(Parsing parsing) {
+  Node parseNode(ParsingContext parsing) {
     if (definitionsCache != null) return definitionsCache;
 
     VariableDefinitions definitions = variables.parseNode(this, parsing);
@@ -1530,7 +1511,7 @@
     if (variables.type != null) return variables.type;
     // Call [parseNode] to ensure that [definitionsCache] and [initializerCache]
     // are set as a consequence of calling [computeType].
-    parseNode(resolution.parsing);
+    parseNode(resolution.parsingContext);
     return variables.computeType(this, resolution);
   }
 
@@ -1700,7 +1681,7 @@
 
   Token get position => identifier.getBeginToken();
 
-  Node parseNode(Parsing parsing) => definitions;
+  Node parseNode(ParsingContext parsing) => definitions;
 
   DartType computeType(Resolution resolution) {
     assert(invariant(this, type != null,
@@ -1860,7 +1841,7 @@
     throw "internal error: AbstractFieldElement has no type";
   }
 
-  Node parseNode(Parsing parsing) {
+  Node parseNode(ParsingContext parsing) {
     throw "internal error: AbstractFieldElement has no node";
   }
 
@@ -2114,7 +2095,7 @@
 
   bool get hasNode => true;
 
-  FunctionExpression parseNode(Parsing parsing) => node;
+  FunctionExpression parseNode(ParsingContext parsing) => node;
 
   Token get position {
     // Use the name as position if this is not an unnamed closure.
@@ -2271,7 +2252,7 @@
   // error messages.
   Token get position => null;
 
-  FunctionExpression parseNode(Parsing parsing) => null;
+  FunctionExpression parseNode(ParsingContext parsing) => null;
 
   bool get hasNode => false;
 
@@ -2328,24 +2309,31 @@
  */
 class SynthesizedConstructorElementX extends ConstructorElementX {
   final ConstructorElement definingConstructor;
-  final bool isDefaultConstructor;
+  ResolvedAst _resolvedAst;
 
   SynthesizedConstructorElementX.notForDefault(
       String name, this.definingConstructor, Element enclosing)
-      : isDefaultConstructor = false,
-        super(name, ElementKind.GENERATIVE_CONSTRUCTOR, Modifiers.EMPTY,
-            enclosing);
+      : super(name, ElementKind.GENERATIVE_CONSTRUCTOR, Modifiers.EMPTY,
+            enclosing) {
+    _resolvedAst = new SynthesizedResolvedAst(
+        this, ResolvedAstKind.FORWARDING_CONSTRUCTOR);
+  }
 
   SynthesizedConstructorElementX.forDefault(
       this.definingConstructor, Element enclosing)
-      : isDefaultConstructor = true,
-        super('', ElementKind.GENERATIVE_CONSTRUCTOR, Modifiers.EMPTY,
+      : super('', ElementKind.GENERATIVE_CONSTRUCTOR, Modifiers.EMPTY,
             enclosing) {
     functionSignature = new FunctionSignatureX(
         type: new FunctionType.synthesized(enclosingClass.thisType));
+    _resolvedAst =
+        new SynthesizedResolvedAst(this, ResolvedAstKind.DEFAULT_CONSTRUCTOR);
   }
 
-  FunctionExpression parseNode(Parsing parsing) => null;
+  bool get isDefaultConstructor {
+    return _resolvedAst.kind == ResolvedAstKind.DEFAULT_CONSTRUCTOR;
+  }
+
+  FunctionExpression parseNode(ParsingContext parsing) => null;
 
   bool get hasNode => false;
 
@@ -2355,6 +2343,10 @@
 
   bool get isSynthesized => true;
 
+  bool get hasResolvedAst => true;
+
+  ResolvedAst get resolvedAst => _resolvedAst;
+
   DartType get type {
     if (isDefaultConstructor) {
       return super.type;
@@ -2522,7 +2514,7 @@
       rawTypeCache = origin.rawType;
     } else if (thisTypeCache == null) {
       computeThisAndRawType(
-          resolution, computeTypeParameters(resolution.parsing));
+          resolution, computeTypeParameters(resolution.parsingContext));
     }
     return thisTypeCache;
   }
@@ -2544,7 +2536,7 @@
     return new InterfaceType(this, typeArguments);
   }
 
-  List<DartType> computeTypeParameters(Parsing parsing);
+  List<DartType> computeTypeParameters(ParsingContext parsing);
 
   bool get isObject {
     assert(invariant(this, isResolved,
@@ -2676,7 +2668,7 @@
     addMember(constructor, reporter);
   }
 
-  List<DartType> computeTypeParameters(Parsing parsing) {
+  List<DartType> computeTypeParameters(ParsingContext parsing) {
     ClassNode node = parseNode(parsing);
     return createTypeVariables(node.typeParameters);
   }
@@ -2694,6 +2686,31 @@
   }
 }
 
+/// This element is used to encode an enum class.
+///
+/// For instance
+///
+///     enum A { b, c, }
+///
+/// is modelled as
+///
+///     class A {
+///       final int index;
+///
+///       const A(this.index);
+///
+///       String toString() {
+///         return const <int, A>{0: 'A.b', 1: 'A.c'}[index];
+///       }
+///
+///       static const A b = const A(0);
+///       static const A c = const A(1);
+///
+///       static const List<A> values = const <A>[b, c];
+///     }
+///
+///  where the `A` class is encoded using this element.
+///
 class EnumClassElementX extends ClassElementX
     implements EnumClassElement, DeclarationSite {
   final Enum node;
@@ -2712,14 +2729,15 @@
   bool get isEnumClass => true;
 
   @override
-  Node parseNode(Parsing parsing) => node;
+  Node parseNode(ParsingContext parsing) => node;
 
   @override
   accept(ElementVisitor visitor, arg) {
     return visitor.visitEnumClassElement(this, arg);
   }
 
-  List<DartType> computeTypeParameters(Parsing parsing) => const <DartType>[];
+  List<DartType> computeTypeParameters(ParsingContext parsing) =>
+      const <DartType>[];
 
   List<FieldElement> get enumValues {
     assert(invariant(this, _enumValues != null,
@@ -2737,6 +2755,31 @@
   DeclarationSite get declarationSite => this;
 }
 
+/// This element is used to encode the implicit constructor in an enum class.
+///
+/// For instance
+///
+///     enum A { b, c, }
+///
+/// is modelled as
+///
+///     class A {
+///       final int index;
+///
+///       const A(this.index);
+///
+///       String toString() {
+///         return const <int, A>{0: 'A.b', 1: 'A.c'}[index];
+///       }
+///
+///       static const A b = const A(0);
+///       static const A c = const A(1);
+///
+///       static const List<A> values = const <A>[b, c];
+///     }
+///
+///  where the `const A(...)` constructor is encoded using this element.
+///
 class EnumConstructorElementX extends ConstructorElementX {
   final FunctionExpression node;
 
@@ -2752,12 +2795,37 @@
   bool get hasNode => true;
 
   @override
-  FunctionExpression parseNode(Parsing parsing) => node;
+  FunctionExpression parseNode(ParsingContext parsing) => node;
 
   @override
   SourceSpan get sourcePosition => enclosingClass.sourcePosition;
 }
 
+/// This element is used to encode the implicit methods in an enum class.
+///
+/// For instance
+///
+///     enum A { b, c, }
+///
+/// is modelled as
+///
+///     class A {
+///       final int index;
+///
+///       const A(this.index);
+///
+///       String toString() {
+///         return const <int, A>{0: 'A.b', 1: 'A.c'}[index];
+///       }
+///
+///       static const A b = const A(0);
+///       static const A c = const A(1);
+///
+///       static const List<A> values = const <A>[b, c];
+///     }
+///
+///  where the `toString` method is encoded using this element.
+///
 class EnumMethodElementX extends MethodElementX {
   final FunctionExpression node;
 
@@ -2769,12 +2837,38 @@
   bool get hasNode => true;
 
   @override
-  FunctionExpression parseNode(Parsing parsing) => node;
+  FunctionExpression parseNode(ParsingContext parsing) => node;
 
   @override
   SourceSpan get sourcePosition => enclosingClass.sourcePosition;
 }
 
+/// This element is used to encode the initializing formal of the implicit
+/// constructor in an enum class.
+///
+/// For instance
+///
+///     enum A { b, c, }
+///
+/// is modelled as
+///
+///     class A {
+///       final int index;
+///
+///       const A(this.index);
+///
+///       String toString() {
+///         return const <int, A>{0: 'A.b', 1: 'A.c'}[index];
+///       }
+///
+///       static const A b = const A(0);
+///       static const A c = const A(1);
+///
+///       static const List<A> values = const <A>[b, c];
+///     }
+///
+///  where the `this.index` formal is encoded using this element.
+///
 class EnumFormalElementX extends InitializingFormalElementX {
   EnumFormalElementX(
       ConstructorElement constructor,
@@ -2789,6 +2883,31 @@
   SourceSpan get sourcePosition => enclosingClass.sourcePosition;
 }
 
+/// This element is used to encode the implicitly fields in an enum class.
+///
+/// For instance
+///
+///     enum A { b, c, }
+///
+/// is modelled as
+///
+///     class A {
+///       final int index;
+///
+///       const A(this.index);
+///
+///       String toString() {
+///         return const <int, A>{0: 'A.b', 1: 'A.c'}[index];
+///       }
+///
+///       static const A b = const A(0);
+///       static const A c = const A(1);
+///
+///       static const List<A> values = const <A>[b, c];
+///     }
+///
+///  where the `index` and `values` fields are encoded using this element.
+///
 class EnumFieldElementX extends FieldElementX {
   EnumFieldElementX(Identifier name, EnumClassElementX enumClass,
       VariableList variableList, Node definition,
@@ -2803,6 +2922,31 @@
   SourceSpan get sourcePosition => enclosingClass.sourcePosition;
 }
 
+/// This element is used to encode the constant value in an enum class.
+///
+/// For instance
+///
+///     enum A { b, c, }
+///
+/// is modelled as
+///
+///     class A {
+///       final int index;
+///
+///       const A(this.index);
+///
+///       String toString() {
+///         return const <int, A>{0: 'A.b', 1: 'A.c'}[index];
+///       }
+///
+///       static const A b = const A(0);
+///       static const A c = const A(1);
+///
+///       static const List<A> values = const <A>[b, c];
+///     }
+///
+///  where the `b` and `c` fields are encoded using this element.
+///
 class EnumConstantElementX extends EnumFieldElementX
     implements EnumConstantElement {
   final int index;
@@ -2818,8 +2962,7 @@
 
   @override
   SourceSpan get sourcePosition {
-    return new SourceSpan(
-        enclosingClass.sourcePosition.uri,
+    return new SourceSpan(enclosingClass.sourcePosition.uri,
         position.charOffset, position.charEnd);
   }
 }
@@ -2848,7 +2991,7 @@
 
   Token get position => node.getBeginToken();
 
-  Node parseNode(Parsing parsing) => node;
+  Node parseNode(ParsingContext parsing) => node;
 
   void addMember(Element element, DiagnosticReporter reporter) {
     throw new UnsupportedError("Cannot add member to $this.");
@@ -2868,7 +3011,7 @@
     addConstructor(constructor);
   }
 
-  List<DartType> computeTypeParameters(Parsing parsing) {
+  List<DartType> computeTypeParameters(ParsingContext parsing) {
     NamedMixinApplication named = node.asNamedMixinApplication();
     if (named == null) {
       throw new SpannableAssertionFailure(
@@ -2992,7 +3135,7 @@
 
   bool get hasNode => true;
 
-  Node parseNode(Parsing parsing) => node;
+  Node parseNode(ParsingContext parsing) => node;
 
   Token get position => node.getBeginToken();
 
@@ -3055,7 +3198,7 @@
     return this;
   }
 
-  Node parseNode(Parsing parsing);
+  Node parseNode(ParsingContext parsing);
 
   String toString() => 'MetadataAnnotation($constant, $resolutionState)';
 }
@@ -3066,7 +3209,7 @@
 
   ParameterMetadataAnnotation(Metadata this.metadata);
 
-  Node parseNode(Parsing parsing) => metadata.expression;
+  Node parseNode(ParsingContext parsing) => metadata.expression;
 
   Token get beginToken => metadata.getBeginToken();
 
@@ -3126,7 +3269,15 @@
   }
 
   ResolvedAst get resolvedAst {
-    return new ResolvedAst(
-        declaration, definingElement.node, definingElement.treeElements);
+    Node node = definingElement.node;
+    Node body;
+    if (definingElement.isField) {
+      FieldElement field = definingElement;
+      body = field.initializer;
+    } else if (node != null && node.asFunctionExpression() != null) {
+      body = node.asFunctionExpression().body;
+    }
+    return new ParsedResolvedAst(
+        declaration, node, body, definingElement.treeElements);
   }
 }
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index ff3c21c..8f1f1b7 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -6,13 +6,13 @@
 
 import 'dart:collection' show Queue;
 
-import 'common.dart';
+import 'common/codegen.dart' show CodegenWorkItem;
 import 'common/names.dart' show Identifiers;
 import 'common/resolution.dart' show Resolution;
-import 'common/work.dart' show ItemCompilationContext, WorkItem;
-import 'common/tasks.dart' show CompilerTask, DeferredAction, DeferredTask;
-import 'common/codegen.dart' show CodegenWorkItem;
 import 'common/resolution.dart' show ResolutionWorkItem;
+import 'common/tasks.dart' show CompilerTask, DeferredAction, DeferredTask;
+import 'common/work.dart' show ItemCompilationContext, WorkItem;
+import 'common.dart';
 import 'compiler.dart' show Compiler;
 import 'dart_types.dart' show DartType, InterfaceType;
 import 'elements/elements.dart'
@@ -25,10 +25,8 @@
         Elements,
         FunctionElement,
         LibraryElement,
-        LocalFunctionElement,
         Member,
         MemberElement,
-        MethodElement,
         Name,
         TypedElement,
         TypedefElement;
@@ -41,7 +39,7 @@
     show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind;
 import 'universe/world_impact.dart'
     show ImpactUseCase, WorldImpact, WorldImpactVisitor;
-import 'util/util.dart' show Link, Setlet;
+import 'util/util.dart' show Setlet;
 
 typedef ItemCompilationContext ItemCompilationContextCreator();
 
@@ -703,6 +701,8 @@
   void forgetElement(Element element) {
     universe.forgetElement(element, compiler);
     _processedClasses.remove(element);
+    instanceMembersByName[element.name]?.remove(element);
+    instanceFunctionsByName[element.name]?.remove(element);
   }
 }
 
diff --git a/pkg/compiler/lib/src/id_generator.dart b/pkg/compiler/lib/src/id_generator.dart
index 4c92ea9..9107c7a 100644
--- a/pkg/compiler/lib/src/id_generator.dart
+++ b/pkg/compiler/lib/src/id_generator.dart
@@ -10,4 +10,4 @@
   ///
   /// This identifier is guaranteed to be unique.
   int getNextFreeId() => _nextFreeId++;
-}
\ No newline at end of file
+}
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
index 5d4623a..78ef6bb 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
@@ -705,6 +705,7 @@
     implements SemanticSendVisitor<T, dynamic> {
   final Compiler compiler;
   final AstElement analyzedElement;
+  final ResolvedAst resolvedAst;
   final TypeSystem<T> types;
   final E inferrer;
   final Map<JumpTarget, List<LocalsHandler<T>>> breaksFor =
@@ -713,7 +714,8 @@
       new Map<JumpTarget, List<LocalsHandler<T>>>();
   LocalsHandler<T> locals;
   final List<T> cascadeReceiverStack = new List<T>();
-  final TreeElements elements;
+
+  TreeElements get elements => resolvedAst.elements;
 
   bool accumulateIsChecks = false;
   bool conditionIsSimple = false;
@@ -733,12 +735,11 @@
     }
   }
 
-  InferrerVisitor(
-      AstElement analyzedElement, this.inferrer, this.types, this.compiler,
+  InferrerVisitor(AstElement analyzedElement, this.resolvedAst, this.inferrer,
+      this.types, this.compiler,
       [LocalsHandler<T> handler])
       : this.analyzedElement = analyzedElement,
-        this.locals = handler,
-        this.elements = analyzedElement.resolvedAst.elements {
+        this.locals = handler {
     if (handler != null) return;
     Node node = analyzedElement.node;
     FieldInitializationScope<T> fieldScope =
diff --git a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
index e3b2327c..b148b11 100644
--- a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
@@ -4,34 +4,26 @@
 
 library simple_types_inferrer;
 
-import '../closure.dart' show ClosureClassMap, ClosureScope;
+import '../closure.dart' show ClosureClassMap;
 import '../common.dart';
 import '../common/names.dart' show Selectors;
 import '../compiler.dart' show Compiler;
 import '../constants/values.dart' show ConstantValue, IntConstantValue;
 import '../core_types.dart' show CoreClasses, CoreTypes;
 import '../cps_ir/cps_ir_nodes.dart' as cps_ir show Node;
-import '../dart_types.dart'
-    show DartType, FunctionType, InterfaceType, TypeKind;
+import '../dart_types.dart' show DartType;
 import '../elements/elements.dart';
 import '../js_backend/js_backend.dart' as js;
 import '../native/native.dart' as native;
-import '../resolution/tree_elements.dart' show TreeElements;
 import '../resolution/operators.dart' as op;
+import '../resolution/tree_elements.dart' show TreeElements;
 import '../tree/tree.dart' as ast;
-import '../types/types.dart'
-    show
-        TypesInferrer,
-        FlatTypeMask,
-        TypeMask,
-        ContainerTypeMask,
-        ValueTypeMask;
-import '../util/util.dart' show Link, Setlet;
+import '../types/types.dart' show TypeMask;
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
 import '../universe/side_effects.dart' show SideEffects;
+import '../util/util.dart' show Link, Setlet;
 import '../world.dart' show ClassWorld;
-
 import 'inferrer_visitor.dart';
 
 /**
@@ -339,16 +331,24 @@
   final Setlet<Entity> capturedVariables = new Setlet<Entity>();
 
   SimpleTypeInferrerVisitor.internal(
-      analyzedElement, this.outermostElement, inferrer, compiler, locals)
-      : super(analyzedElement, inferrer, inferrer.types, compiler, locals),
+      AstElement analyzedElement,
+      ResolvedAst resolvedAst,
+      this.outermostElement,
+      inferrer,
+      compiler,
+      locals)
+      : super(analyzedElement, resolvedAst, inferrer, inferrer.types, compiler,
+            locals),
         this.inferrer = inferrer {
     assert(outermostElement != null);
   }
 
-  SimpleTypeInferrerVisitor(Element element, Compiler compiler,
-      InferrerEngine<T, TypeSystem<T>> inferrer, [LocalsHandler<T> handler])
+  SimpleTypeInferrerVisitor(Element element, ResolvedAst resolvedAst,
+      Compiler compiler, InferrerEngine<T, TypeSystem<T>> inferrer,
+      [LocalsHandler<T> handler])
       : this.internal(
             element,
+            resolvedAst,
             element.outermostEnclosingMemberOrTopLevel.implementation,
             inferrer,
             compiler,
@@ -375,8 +375,8 @@
     // be handled specially, in that we are computing their LUB at
     // each update, and reading them yields the type that was found in a
     // previous analysis of [outermostElement].
-    ClosureClassMap closureData = compiler.closureToClassMapper
-        .computeClosureToClassMapping(analyzedElement, node, elements);
+    ClosureClassMap closureData =
+        compiler.closureToClassMapper.computeClosureToClassMapping(resolvedAst);
     closureData.forEachCapturedVariable((variable, field) {
       locals.setCaptured(variable, field);
     });
@@ -402,8 +402,8 @@
       SimpleTypeInferrerVisitor visitor = this;
       if (inferrer.hasAlreadyComputedTypeOfParameterDefault(element)) return;
       if (element.functionDeclaration != analyzedElement) {
-        visitor = new SimpleTypeInferrerVisitor(
-            element.functionDeclaration, compiler, inferrer);
+        visitor = new SimpleTypeInferrerVisitor(element.functionDeclaration,
+            element.functionDeclaration.resolvedAst, compiler, inferrer);
       }
       T type =
           (defaultValue == null) ? types.nullType : visitor.visit(defaultValue);
@@ -552,7 +552,7 @@
     LocalsHandler closureLocals =
         new LocalsHandler<T>.from(locals, node, useOtherTryBlock: false);
     SimpleTypeInferrerVisitor visitor = new SimpleTypeInferrerVisitor<T>(
-        element, compiler, inferrer, closureLocals);
+        element, element.resolvedAst, compiler, inferrer, closureLocals);
     visitor.run();
     inferrer.recordReturnType(element, visitor.returnType);
 
@@ -1513,8 +1513,7 @@
     String name = element.name;
     handleStaticSend(node, selector, mask, element, arguments);
     if (name == 'JS' || name == 'JS_EMBEDDED_GLOBAL' || name == 'JS_BUILTIN') {
-      native.NativeBehavior nativeBehavior =
-          compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
+      native.NativeBehavior nativeBehavior = elements.getNativeData(node);
       sideEffects.add(nativeBehavior.sideEffects);
       return inferrer.typeOfNativeBehavior(nativeBehavior);
     } else if (name == 'JS_OPERATOR_AS_PREFIX' || name == 'JS_STRING_CONCAT') {
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index e19436f..1cfc52a 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -7,34 +7,31 @@
 import 'dart:collection' show Queue;
 
 import '../common.dart';
-import '../common/names.dart' show Identifiers, Names;
+import '../common/names.dart' show Identifiers;
 import '../compiler.dart' show Compiler;
 import '../constants/values.dart';
-import '../dart_types.dart'
-    show DartType, FunctionType, InterfaceType, TypeKind;
+import '../dart_types.dart' show DartType;
 import '../elements/elements.dart';
 import '../js_backend/js_backend.dart' show Annotations, JavaScriptBackend;
 import '../resolution/tree_elements.dart' show TreeElementMapping;
 import '../tree/tree.dart' as ast
-    show DartString, Node, LiteralBool, Send, SendSet, TryStatement;
+    show DartString, Node, LiteralBool, TryStatement;
+import '../types/constants.dart' show computeTypeMask;
 import '../types/types.dart'
     show ContainerTypeMask, MapTypeMask, TypeMask, TypesInferrer;
-import '../types/constants.dart' show computeTypeMask;
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
 import '../universe/side_effects.dart' show SideEffects;
-import '../util/util.dart' show ImmutableEmptySet, Setlet;
+import '../util/util.dart' show Setlet;
 import '../world.dart' show ClassWorld;
-
-import 'inferrer_visitor.dart' show ArgumentsTypes, TypeSystem;
-import 'simple_types_inferrer.dart';
-
 import 'closure_tracer.dart';
+import 'debug.dart' as debug;
+import 'inferrer_visitor.dart' show ArgumentsTypes, TypeSystem;
 import 'list_tracer.dart';
 import 'map_tracer.dart';
-import 'type_graph_nodes.dart';
+import 'simple_types_inferrer.dart';
 import 'type_graph_dump.dart';
-import 'debug.dart' as debug;
+import 'type_graph_nodes.dart';
 
 class TypeInformationSystem extends TypeSystem<TypeInformation> {
   final Compiler compiler;
@@ -830,13 +827,13 @@
     processLoopInformation();
   }
 
-  void analyze(Element element, ArgumentsTypes arguments) {
+  void analyze(AstElement element, ArgumentsTypes arguments) {
     element = element.implementation;
     if (analyzedElements.contains(element)) return;
     analyzedElements.add(element);
 
-    SimpleTypeInferrerVisitor visitor =
-        new SimpleTypeInferrerVisitor(element, compiler, this);
+    SimpleTypeInferrerVisitor visitor = new SimpleTypeInferrerVisitor(
+        element, element.resolvedAst, compiler, this);
     TypeInformation type;
     reporter.withCurrentElement(element, () {
       type = visitor.run();
@@ -1003,7 +1000,7 @@
       bool visitingRequiredParameter = true;
       signature.forEachParameter((Element parameter) {
         if (signature.hasOptionalParameters &&
-            parameter == signature.firstOptionalParameter) {
+            parameter == signature.optionalParameters.first) {
           visitingRequiredParameter = false;
         }
         TypeInformation type = visitingRequiredParameter
@@ -1239,7 +1236,7 @@
       // TODO(ngeoffray): Not sure why the resolver would put a null
       // mapping.
       if (!compiler.enqueuer.resolution.hasBeenProcessed(element)) return;
-      TreeElementMapping mapping = element.resolvedAst.elements;
+      ResolvedAst resolvedAst = element.resolvedAst;
       element = element.implementation;
       if (element.impliesType) return;
       assert(invariant(
@@ -1253,7 +1250,11 @@
       if (element.isAbstract) return;
       // Put the other operators in buckets by length, later to be added in
       // length order.
-      int length = mapping.getSelectorCount();
+      int length = 0;
+      if (resolvedAst.kind == ResolvedAstKind.PARSED) {
+        TreeElementMapping mapping = resolvedAst.elements;
+        length = mapping.getSelectorCount();
+      }
       max = length > max ? length : max;
       Setlet<Element> set =
           methodSizes.putIfAbsent(length, () => new Setlet<Element>());
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index 1815539..2bc3670 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -11,12 +11,10 @@
 import '../compiler.dart' show Compiler;
 import '../constants/values.dart';
 import '../cps_ir/cps_ir_nodes.dart' as cps_ir show Node;
-import '../dart_types.dart'
-    show DartType, FunctionType, InterfaceType, TypeKind;
+import '../dart_types.dart' show DartType, FunctionType, TypeKind;
 import '../elements/elements.dart';
 import '../native/native.dart' as native;
-import '../tree/tree.dart' as ast
-    show DartString, Node, LiteralBool, Send, SendSet, TryStatement;
+import '../tree/tree.dart' as ast show DartString, Node, LiteralBool, Send;
 import '../types/types.dart'
     show
         ContainerTypeMask,
@@ -27,11 +25,10 @@
 import '../universe/selector.dart' show Selector;
 import '../util/util.dart' show ImmutableEmptySet, Setlet;
 import '../world.dart' show ClassWorld;
-
+import 'debug.dart' as debug;
 import 'inferrer_visitor.dart' show ArgumentsTypes;
 import 'type_graph_inferrer.dart'
     show TypeGraphInferrerEngine, TypeInformationSystem;
-import 'debug.dart' as debug;
 
 /**
  * Common class for all nodes in the graph. The current nodes are:
diff --git a/pkg/compiler/lib/src/info/send_info.dart b/pkg/compiler/lib/src/info/send_info.dart
index b0f5f1e..86f3845 100644
--- a/pkg/compiler/lib/src/info/send_info.dart
+++ b/pkg/compiler/lib/src/info/send_info.dart
@@ -8,21 +8,20 @@
 import 'package:dart2js_info/src/measurements.dart';
 import 'package:dart2js_info/src/util.dart' show recursiveDiagnosticString;
 
+import '../closure.dart';
 import '../common.dart';
 import '../compiler.dart' show Compiler;
+import '../constants/expressions.dart';
 import '../dart_types.dart';
-import '../closure.dart';
 import '../elements/elements.dart';
 import '../elements/visitor.dart' show ElementVisitor;
+import '../parser/partial_elements.dart' show PartialElement;
 import '../resolution/operators.dart';
 import '../resolution/semantic_visitor.dart';
 import '../resolution/tree_elements.dart';
-import '../constants/expressions.dart';
-import '../parser/partial_elements.dart' show PartialElement;
 import '../tree/tree.dart';
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
-
 import 'analysis_result.dart';
 import 'naive_analysis_result.dart';
 import 'trusted_types_analysis_result.dart';
@@ -34,7 +33,6 @@
   return reporter.withCurrentElement(f, () {
     // TODO(sigmund): enable for platform too.
     if (f.library.isPlatformLibrary) return null;
-    var name = _qualifiedName(f);
     if (!f.hasNode) {
       if (f is PartialElement) return const Measurements.unreachableFunction();
       assert(f is ConstructorElement && f.isSynthesized);
@@ -64,11 +62,6 @@
   });
 }
 
-_qualifiedName(FunctionElement f) {
-  var cls = f.enclosingClass;
-  return (cls != null) ? '${cls.name}.${f.name}' : f.name;
-}
-
 /// Visitor that categorizes data about an individual send.
 class _StatsVisitor<T> extends Visitor
     with SemanticSendResolvedMixin<dynamic, T>
@@ -2363,7 +2356,6 @@
     return null;
   }
 
-  @override
   R visitVariableElement(VariableElement e, A arg) => null;
 
   @override
@@ -2381,7 +2373,6 @@
   @override
   R visitAbstractFieldElement(AbstractFieldElement e, A arg) => null;
 
-  @override
   R visitFunctionElement(FunctionElement e, A arg) => null;
 
   @override
diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart
index 83460d5..38df221 100644
--- a/pkg/compiler/lib/src/io/position_information.dart
+++ b/pkg/compiler/lib/src/io/position_information.dart
@@ -8,12 +8,11 @@
 library dart2js.source_information.position;
 
 import '../common.dart';
-import '../elements/elements.dart' show AstElement, FieldElement, LocalElement;
+import '../elements/elements.dart' show AstElement, FieldElement, ResolvedAst, ResolvedAstKind;
 import '../js/js.dart' as js;
-import '../js/js_source_mapping.dart';
 import '../js/js_debug.dart';
+import '../js/js_source_mapping.dart';
 import '../tree/tree.dart' show FunctionExpression, Node, Send;
-
 import 'code_output.dart' show CodeBuffer;
 import 'source_file.dart';
 import 'source_information.dart';
@@ -148,16 +147,17 @@
         sourceFile = element.implementation.compilationUnit.script.file,
         name = computeElementNameForSourceMaps(element);
 
-  SourceInformation buildDeclaration(AstElement element) {
-    if (element.isSynthesized) {
+  SourceInformation buildDeclaration(ResolvedAst resolvedAst) {
+    if (resolvedAst.kind != ResolvedAstKind.PARSED) {
+      SourceSpan span = resolvedAst.element.sourcePosition;
       return new PositionSourceInformation(new OffsetSourceLocation(
-          sourceFile, element.position.charOffset, name));
+          sourceFile, span.begin, name));
     } else {
       return new PositionSourceInformation(
           new OffsetSourceLocation(sourceFile,
-              element.resolvedAst.node.getBeginToken().charOffset, name),
+              resolvedAst.node.getBeginToken().charOffset, name),
           new OffsetSourceLocation(sourceFile,
-              element.resolvedAst.node.getEndToken().charOffset, name));
+              resolvedAst.node.getEndToken().charOffset, name));
     }
   }
 
diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart
index ec2b933..cf3872c 100644
--- a/pkg/compiler/lib/src/io/source_information.dart
+++ b/pkg/compiler/lib/src/io/source_information.dart
@@ -5,9 +5,9 @@
 library dart2js.source_information;
 
 import '../common.dart';
-import '../elements/elements.dart' show AstElement, LocalElement;
-import '../tree/tree.dart' show Node, Send;
+import '../elements/elements.dart' show AstElement, LocalElement, ResolvedAst;
 import '../js/js.dart' show JavaScriptNodeSourceInformation;
+import '../tree/tree.dart' show Node;
 import 'source_file.dart';
 
 /// Interface for passing source information, for instance for use in source
@@ -56,8 +56,9 @@
   /// Create a [SourceInformationBuilder] for [element].
   SourceInformationBuilder forContext(AstElement element) => this;
 
-  /// Generate [SourceInformation] the declaration of [element].
-  SourceInformation buildDeclaration(AstElement element) => null;
+  /// Generate [SourceInformation] the declaration of the element in
+  /// [resolvedAst].
+  SourceInformation buildDeclaration(ResolvedAst resolvedAst) => null;
 
   /// Generate [SourceInformation] for the generic [node].
   @deprecated
diff --git a/pkg/compiler/lib/src/io/start_end_information.dart b/pkg/compiler/lib/src/io/start_end_information.dart
index b08477f..b749d8a 100644
--- a/pkg/compiler/lib/src/io/start_end_information.dart
+++ b/pkg/compiler/lib/src/io/start_end_information.dart
@@ -9,12 +9,11 @@
 
 import '../common.dart';
 import '../diagnostics/messages.dart' show MessageTemplate;
-import '../elements/elements.dart' show AstElement, LocalElement;
+import '../elements/elements.dart' show AstElement, ResolvedAst, ResolvedAstKind;
 import '../js/js.dart' as js;
 import '../js/js_source_mapping.dart';
 import '../tokens/token.dart' show Token;
-import '../tree/tree.dart' show Node, Send;
-
+import '../tree/tree.dart' show Node;
 import 'source_file.dart';
 import 'source_information.dart';
 
@@ -61,30 +60,31 @@
   // TODO(johnniwinther): Inline this in
   // [StartEndSourceInformationBuilder.buildDeclaration].
   static StartEndSourceInformation _computeSourceInformation(
-      AstElement element) {
-    AstElement implementation = element.implementation;
-    SourceFile sourceFile = implementation.compilationUnit.script.file;
-    String name = computeElementNameForSourceMaps(element);
-    Node node = implementation.node;
-    Token beginToken;
-    Token endToken;
-    if (node == null) {
+      ResolvedAst resolvedAst) {
+    String name = computeElementNameForSourceMaps(resolvedAst.element);
+    SourceFile sourceFile;
+    int begin;
+    int end;
+    if (resolvedAst.kind != ResolvedAstKind.PARSED) {
       // Synthesized node. Use the enclosing element for the location.
-      beginToken = endToken = element.position;
+      sourceFile = resolvedAst.element.compilationUnit.script.file;
+      begin = end = resolvedAst.element.sourcePosition.begin;
     } else {
-      beginToken = node.getBeginToken();
-      endToken = node.getEndToken();
+      AstElement implementation = resolvedAst.element.implementation;
+      sourceFile = implementation.compilationUnit.script.file;
+      Node node = resolvedAst.node;
+      begin = node.getBeginToken().charOffset;
+      end = node.getEndToken().charOffset;
     }
     // TODO(johnniwinther): find the right sourceFile here and remove offset
     // checks below.
     SourceLocation sourcePosition, endSourcePosition;
-    if (beginToken.charOffset < sourceFile.length) {
+    if (begin < sourceFile.length) {
       sourcePosition =
-          new OffsetSourceLocation(sourceFile, beginToken.charOffset, name);
+          new OffsetSourceLocation(sourceFile, begin, name);
     }
-    if (endToken.charOffset < sourceFile.length) {
-      endSourcePosition =
-          new OffsetSourceLocation(sourceFile, endToken.charOffset, name);
+    if (end < sourceFile.length) {
+      endSourcePosition = new OffsetSourceLocation(sourceFile, end, name);
     }
     return new StartEndSourceInformation(sourcePosition, endSourcePosition);
   }
@@ -162,8 +162,8 @@
       : sourceFile = element.compilationUnit.script.file,
         name = computeElementNameForSourceMaps(element);
 
-  SourceInformation buildDeclaration(AstElement element) {
-    return StartEndSourceInformation._computeSourceInformation(element);
+  SourceInformation buildDeclaration(ResolvedAst resolvedAst) {
+    return StartEndSourceInformation._computeSourceInformation(resolvedAst);
   }
 
   SourceLocation sourceFileLocationForToken(Token token) {
diff --git a/pkg/compiler/lib/src/js/js.dart b/pkg/compiler/lib/src/js/js.dart
index cefac18..bad0d12 100644
--- a/pkg/compiler/lib/src/js/js.dart
+++ b/pkg/compiler/lib/src/js/js.dart
@@ -5,16 +5,16 @@
 library js;
 
 import 'package:js_ast/js_ast.dart';
-export 'package:js_ast/js_ast.dart';
 
 import '../common.dart';
 import '../compiler.dart' show Compiler;
 import '../dump_info.dart' show DumpInfoTask;
-import '../io/code_output.dart' show CodeBuffer, CodeOutput;
+import '../io/code_output.dart' show CodeBuffer;
 import '../js_emitter/js_emitter.dart' show USE_LAZY_EMITTER;
-
 import 'js_source_mapping.dart';
 
+export 'package:js_ast/js_ast.dart';
+
 String prettyPrint(Node node, Compiler compiler,
     {bool allowVariableMinification: true,
     Renamer renamerForNames: JavaScriptPrintingOptions.identityRenamer}) {
diff --git a/pkg/compiler/lib/src/js/js_source_mapping.dart b/pkg/compiler/lib/src/js/js_source_mapping.dart
index 86b2601..df49903 100644
--- a/pkg/compiler/lib/src/js/js_source_mapping.dart
+++ b/pkg/compiler/lib/src/js/js_source_mapping.dart
@@ -4,11 +4,10 @@
 
 library js.source_mapping;
 
-import 'js.dart';
-import '../io/code_output.dart'
-    show BufferedCodeOutput, CodeBuffer, SourceLocations;
+import '../io/code_output.dart' show BufferedCodeOutput, SourceLocations;
 import '../io/source_information.dart'
     show SourceLocation, SourceInformation, SourceInformationStrategy;
+import 'js.dart';
 
 /// [SourceInformationStrategy] that can associate source information with
 /// JavaScript output.
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 7f751db..0e8c98e 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -511,6 +511,8 @@
   final BackendHelpers helpers;
   final BackendImpacts impacts;
 
+  final JSFrontendAccess frontend;
+
   JavaScriptBackend(Compiler compiler,
       {bool generateSourceMap: true,
       bool useStartupEmitter: false,
@@ -529,6 +531,7 @@
             : const JavaScriptSourceInformationStrategy(),
         helpers = new BackendHelpers(compiler),
         impacts = new BackendImpacts(compiler),
+        frontend = new JSFrontendAccess(compiler),
         super(compiler) {
     emitter = new CodeEmitterTask(
         compiler, namer, generateSourceMap, useStartupEmitter);
@@ -619,7 +622,7 @@
     assert(invariant(element, element.isDeclaration, message: ""));
     if (element == helpers.streamIteratorConstructor ||
         element == helpers.compiler.symbolConstructor ||
-        element == helpers.compiler.symbolValidatedConstructor ||
+        helpers.isSymbolValidatedConstructor(element) ||
         element == helpers.syncCompleterConstructor ||
         element == coreClasses.symbolClass ||
         element == helpers.objectNoSuchMethod) {
@@ -1291,16 +1294,16 @@
   }
 
   /// Called when resolving a call to a foreign function.
-  void registerForeignCall(Send node, Element element,
+  native.NativeBehavior resolveForeignCall(Send node, Element element,
       CallStructure callStructure, ForeignResolver resolver) {
     native.NativeResolutionEnqueuer nativeEnqueuer =
         compiler.enqueuer.resolution.nativeEnqueuer;
     if (element.name == 'JS') {
-      nativeEnqueuer.registerJsCall(node, resolver);
+      return nativeEnqueuer.resolveJsCall(node, resolver);
     } else if (element.name == 'JS_EMBEDDED_GLOBAL') {
-      nativeEnqueuer.registerJsEmbeddedGlobalCall(node, resolver);
+      return nativeEnqueuer.resolveJsEmbeddedGlobalCall(node, resolver);
     } else if (element.name == 'JS_BUILTIN') {
-      nativeEnqueuer.registerJsBuiltinCall(node, resolver);
+      return nativeEnqueuer.resolveJsBuiltinCall(node, resolver);
     } else if (element.name == 'JS_INTERCEPTOR_CONSTANT') {
       // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names
       // a class that will be instantiated outside the program by attaching a
@@ -1312,13 +1315,16 @@
           TypeConstantExpression typeConstant = constant;
           if (typeConstant.type is InterfaceType) {
             resolver.registerInstantiatedType(typeConstant.type);
-            return;
+            // No native behavior for this call.
+            return null;
           }
         }
       }
       reporter.reportErrorMessage(
           node, MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
     }
+    // No native behavior for this call.
+    return null;
   }
 
   void enableNoSuchMethod(Enqueuer world) {
@@ -1443,8 +1449,16 @@
   WorldImpact codegen(CodegenWorkItem work) {
     Element element = work.element;
     if (compiler.elementHasCompileTimeError(element)) {
-      generatedCode[element] = jsAst.js(
-          "function () { throw new Error('Compile time error in $element') }");
+      DiagnosticMessage message =
+          // If there's more than one error, the first is probably most
+          // informative, as the following errors may be side-effects of the
+          // first error.
+          compiler.elementsWithCompileTimeErrors[element].first;
+      String messageText = message.message.computeMessage();
+      jsAst.LiteralString messageLiteral =
+          js.escapedString("Compile time error in $element: $messageText");
+      generatedCode[element] = js(
+          "function () { throw new Error(#); }", [messageLiteral]);
       return const CodegenImpact();
     }
     var kind = element.kind;
@@ -2252,7 +2266,8 @@
     lookupMapAnalysis.onCodegenStart();
   }
 
-  void onElementResolved(Element element, TreeElements elements) {
+  @override
+  void onElementResolved(Element element) {
     if (element.isMalformed) {
       // Elements that are marker as malformed during parsing or resolution
       // might be registered here. These should just be ignored.
@@ -2474,6 +2489,32 @@
   }
 }
 
+class JSFrontendAccess implements Frontend {
+  final Compiler compiler;
+
+  JSFrontendAccess(this.compiler);
+
+  Resolution get resolution => compiler.resolution;
+
+  @override
+  ResolutionImpact getResolutionImpact(Element element) {
+    return resolution.getResolutionImpact(element);
+  }
+
+  @override
+  ResolvedAst getResolvedAst(Element element) {
+    if (element is SynthesizedCallMethodElementX) {
+      return element.resolvedAst;
+    } else if (element is ConstructorBodyElementX) {
+      return element.resolvedAst;
+    } else {
+      assert(invariant(element, resolution.hasResolvedAst(element.declaration),
+          message: 'No ResolvedAst for $element'));
+      return resolution.getResolvedAst(element.declaration);
+    }
+  }
+}
+
 /// Handling of special annotations for tests.
 class Annotations {
   static final Uri PACKAGE_EXPECT =
diff --git a/pkg/compiler/lib/src/js_backend/backend_helpers.dart b/pkg/compiler/lib/src/js_backend/backend_helpers.dart
index aac308d..5863104 100644
--- a/pkg/compiler/lib/src/js_backend/backend_helpers.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_helpers.dart
@@ -18,8 +18,11 @@
         EnumClassElement,
         FunctionElement,
         LibraryElement,
-        MethodElement;
+        MethodElement,
+        PublicName;
 import '../library_loader.dart' show LoadedLibraries;
+import '../universe/call_structure.dart' show CallStructure;
+import '../universe/selector.dart' show Selector;
 
 import 'js_backend.dart';
 
@@ -174,6 +177,28 @@
   /// Holds the class for the [JsBuiltins] enum.
   EnumClassElement jsBuiltinEnum;
 
+  ClassElement _symbolImplementationClass;
+  ClassElement get symbolImplementationClass {
+    return _symbolImplementationClass ??= find(internalLibrary, 'Symbol');
+  }
+
+  final Selector symbolValidatedConstructorSelector =
+      new Selector.call(const PublicName('validated'), CallStructure.ONE_ARG);
+
+  ConstructorElement _symbolValidatedConstructor;
+
+  bool isSymbolValidatedConstructor(Element element) {
+    if (_symbolValidatedConstructor != null) {
+      return element == _symbolValidatedConstructor;
+    }
+    return false;
+  }
+
+  ConstructorElement get symbolValidatedConstructor {
+    return _symbolValidatedConstructor ??= _findConstructor(
+        symbolImplementationClass, symbolValidatedConstructorSelector.name);
+  }
+
   // TODO(johnniwinther): Make these private.
   // TODO(johnniwinther): Split into findHelperFunction and findHelperClass and
   // add a check that the element has the expected kind.
@@ -187,6 +212,14 @@
     return element;
   }
 
+  ConstructorElement _findConstructor(ClassElement cls, String name) {
+    cls.ensureResolved(resolution);
+    ConstructorElement constructor = cls.lookupConstructor(name);
+    assert(invariant(cls, constructor != null,
+        message: "Constructor '$name' not found in '${cls}'."));
+    return constructor;
+  }
+
   void onLibraryCreated(LibraryElement library) {
     Uri uri = library.canonicalUri;
     if (uri == DART_JS_HELPER) {
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index 3edac4f..ee1dab9 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -291,8 +291,8 @@
 
   BackendImpact get symbolConstructor {
     if (_symbolConstructor == null) {
-      _symbolConstructor = new BackendImpact(
-          staticUses: [helpers.compiler.symbolValidatedConstructor]);
+      _symbolConstructor =
+          new BackendImpact(staticUses: [helpers.symbolValidatedConstructor]);
     }
     return _symbolConstructor;
   }
diff --git a/pkg/compiler/lib/src/js_backend/backend_serialization.dart b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
index c7c2039..cc7cc03f 100644
--- a/pkg/compiler/lib/src/js_backend/backend_serialization.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
@@ -5,13 +5,26 @@
 library js_backend.serialization;
 
 import '../common/backend_api.dart' show BackendSerialization;
+import '../dart_types.dart';
 import '../elements/elements.dart';
+import '../js/js.dart' as js;
+import '../native/native.dart';
 import '../serialization/serialization.dart'
     show DeserializerPlugin, ObjectDecoder, ObjectEncoder, SerializerPlugin;
 import '../serialization/keys.dart';
+import '../universe/side_effects.dart';
 import 'js_backend.dart';
 
 const String _BACKEND_DATA_TAG = 'jsBackendData';
+const Key DART_TYPES_RETURNED = const Key('dartTypesReturned');
+const Key SPECIAL_TYPES_RETURNED = const Key('specialTypesReturned');
+const Key DART_TYPES_INSTANTIATED = const Key('dartTypesInstantiated');
+const Key SPECIAL_TYPES_INSTANTIATED = const Key('specialTypesInstantiated');
+const Key CODE_TEMPLATE = const Key('codeTemplate');
+const Key SIDE_EFFECTS = const Key('sideEffects');
+const Key THROW_BEHAVIOR = const Key('throwBehavior');
+const Key IS_ALLOCATION = const Key('isAllocation');
+const Key USE_GVN = const Key('useGvn');
 
 class JavaScriptBackendSerialization implements BackendSerialization {
   final JavaScriptBackendSerializer serializer;
@@ -22,6 +35,10 @@
         deserializer = new JavaScriptBackendDeserializer(backend);
 }
 
+const Key JS_INTEROP_NAME = const Key('jsInteropName');
+const Key NATIVE_MEMBER_NAME = const Key('nativeMemberName');
+const Key NATIVE_CLASS_TAG_INFO = const Key('nativeClassTagInfo');
+
 class JavaScriptBackendSerializer implements SerializerPlugin {
   final JavaScriptBackend backend;
 
@@ -29,13 +46,58 @@
 
   @override
   void onElement(Element element, ObjectEncoder createEncoder(String tag)) {
-    // TODO(johnniwinther): Add more data, e.g. js-interop names, native tags,
-    // etc.
-    String nativeName = backend.nativeData.nativeMemberName[element];
-    if (nativeName != null) {
-      ObjectEncoder encoder = createEncoder(_BACKEND_DATA_TAG);
-      encoder.setString(Key.NAME, nativeName);
+    ObjectEncoder encoder;
+    ObjectEncoder getEncoder() {
+      return encoder ??= createEncoder(_BACKEND_DATA_TAG);
     }
+
+    String jsInteropName = backend.nativeData.jsInteropNames[element];
+    if (jsInteropName != null) {
+      getEncoder().setString(JS_INTEROP_NAME, jsInteropName);
+    }
+    String nativeMemberName = backend.nativeData.nativeMemberName[element];
+    if (nativeMemberName != null) {
+      getEncoder().setString(NATIVE_MEMBER_NAME, nativeMemberName);
+    }
+    String nativeClassTagInfo = backend.nativeData.nativeClassTagInfo[element];
+    if (nativeClassTagInfo != null) {
+      getEncoder().setString(NATIVE_CLASS_TAG_INFO, nativeClassTagInfo);
+    }
+  }
+
+  /// Returns a list of the [DartType]s in [types].
+  static List<DartType> filterDartTypes(List types) {
+    return types.where((type) => type is DartType).toList();
+  }
+
+  /// Returns a list of the names of the [SpecialType]s in [types].
+  static List<String> filterSpecialTypes(List types) {
+    return types
+        .where((type) => type is SpecialType)
+        .map((SpecialType type) => type.name)
+        .toList();
+  }
+
+  @override
+  void onData(NativeBehavior behavior, ObjectEncoder encoder) {
+    encoder.setTypes(
+        DART_TYPES_RETURNED, filterDartTypes(behavior.typesReturned));
+    encoder.setStrings(
+        SPECIAL_TYPES_RETURNED, filterSpecialTypes(behavior.typesReturned));
+
+    encoder.setTypes(
+        DART_TYPES_INSTANTIATED, filterDartTypes(behavior.typesInstantiated));
+    encoder.setStrings(SPECIAL_TYPES_INSTANTIATED,
+        filterSpecialTypes(behavior.typesInstantiated));
+
+    if (behavior.codeTemplateText != null) {
+      encoder.setString(CODE_TEMPLATE, behavior.codeTemplateText);
+    }
+
+    encoder.setInt(SIDE_EFFECTS, behavior.sideEffects.flags);
+    encoder.setEnum(THROW_BEHAVIOR, behavior.throwBehavior);
+    encoder.setBool(IS_ALLOCATION, behavior.isAllocation);
+    encoder.setBool(USE_GVN, behavior.useGvn);
   }
 }
 
@@ -48,8 +110,52 @@
   void onElement(Element element, ObjectDecoder getDecoder(String tag)) {
     ObjectDecoder decoder = getDecoder(_BACKEND_DATA_TAG);
     if (decoder != null) {
-      String nativeName = decoder.getString(Key.NAME);
-      backend.nativeData.nativeMemberName[element] = nativeName;
+      String jsInteropName =
+          decoder.getString(JS_INTEROP_NAME, isOptional: true);
+      if (jsInteropName != null) {
+        backend.nativeData.jsInteropNames[element] = jsInteropName;
+      }
+      String nativeMemberName =
+          decoder.getString(NATIVE_MEMBER_NAME, isOptional: true);
+      if (nativeMemberName != null) {
+        backend.nativeData.nativeMemberName[element] = nativeMemberName;
+      }
+      String nativeClassTagInfo =
+          decoder.getString(NATIVE_CLASS_TAG_INFO, isOptional: true);
+      if (nativeClassTagInfo != null) {
+        backend.nativeData.nativeClassTagInfo[element] = nativeClassTagInfo;
+      }
     }
   }
+
+  @override
+  NativeBehavior onData(ObjectDecoder decoder) {
+    SideEffects sideEffects =
+        new SideEffects.fromFlags(decoder.getInt(SIDE_EFFECTS));
+    NativeBehavior behavior = new NativeBehavior.internal(sideEffects);
+
+    behavior.typesReturned
+        .addAll(decoder.getTypes(DART_TYPES_RETURNED, isOptional: true));
+    behavior.typesReturned.addAll(decoder
+        .getStrings(SPECIAL_TYPES_RETURNED, isOptional: true)
+        .map(SpecialType.fromName));
+
+    behavior.typesReturned
+        .addAll(decoder.getTypes(DART_TYPES_INSTANTIATED, isOptional: true));
+    behavior.typesReturned.addAll(decoder
+        .getStrings(SPECIAL_TYPES_INSTANTIATED, isOptional: true)
+        .map(SpecialType.fromName));
+
+    behavior.codeTemplateText =
+        decoder.getString(CODE_TEMPLATE, isOptional: true);
+    if (behavior.codeTemplateText != null) {
+      behavior.codeTemplate = js.js.parseForeignJS(behavior.codeTemplateText);
+    }
+
+    behavior.throwBehavior =
+        decoder.getEnum(THROW_BEHAVIOR, NativeThrowBehavior.values);
+    behavior.isAllocation = decoder.getBool(IS_ALLOCATION);
+    behavior.useGvn = decoder.getBool(USE_GVN);
+    return behavior;
+  }
 }
diff --git a/pkg/compiler/lib/src/js_backend/codegen/glue.dart b/pkg/compiler/lib/src/js_backend/codegen/glue.dart
index eafef0e..096573f 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/glue.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/glue.dart
@@ -4,22 +4,21 @@
 
 library code_generator_dependencies;
 
-import '../backend_helpers.dart' show BackendHelpers;
-import '../js_backend.dart';
-
 import '../../common.dart';
 import '../../common/codegen.dart' show CodegenRegistry;
 import '../../compiler.dart' show Compiler;
 import '../../constants/values.dart';
-import '../../dart_types.dart' show DartType, TypeVariableType, InterfaceType;
-import '../../enqueue.dart' show CodegenEnqueuer;
+import '../../dart_types.dart' show DartType, TypeVariableType;
 import '../../elements/elements.dart';
-import '../../js_emitter/js_emitter.dart';
+import '../../enqueue.dart' show CodegenEnqueuer;
 import '../../js/js.dart' as js;
+import '../../js_emitter/js_emitter.dart';
 import '../../native/native.dart' show NativeBehavior;
+import '../../types/types.dart';
 import '../../universe/selector.dart' show Selector;
 import '../../world.dart' show ClassWorld;
-import '../../types/types.dart';
+import '../backend_helpers.dart' show BackendHelpers;
+import '../js_backend.dart';
 
 /// Encapsulates the dependencies of the function-compiler to the compiler,
 /// backend and emitter.
diff --git a/pkg/compiler/lib/src/js_backend/codegen/task.dart b/pkg/compiler/lib/src/js_backend/codegen/task.dart
index 061e44a..cf21b0b 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/task.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/task.dart
@@ -351,6 +351,6 @@
   js.Node attachPosition(js.Node node, AstElement element) {
     return node.withSourceInformation(sourceInformationFactory
         .createBuilderForContext(element)
-        .buildDeclaration(element));
+        .buildDeclaration(backend.frontend.getResolvedAst(element)));
   }
 }
diff --git a/pkg/compiler/lib/src/js_backend/js_backend.dart b/pkg/compiler/lib/src/js_backend/js_backend.dart
index ca13518..6be55db 100644
--- a/pkg/compiler/lib/src/js_backend/js_backend.dart
+++ b/pkg/compiler/lib/src/js_backend/js_backend.dart
@@ -4,7 +4,7 @@
 
 library js_backend;
 
-import 'dart:async' show EventSink, Future;
+import 'dart:async' show Future;
 import 'dart:collection' show HashMap;
 
 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames;
@@ -13,17 +13,22 @@
 import '../closure.dart';
 import '../common.dart';
 import '../common/backend_api.dart'
-    show Backend, BackendSerialization, ImpactTransformer, ForeignResolver;
-import '../common/codegen.dart'
-    show CodegenImpact, CodegenRegistry, CodegenWorkItem;
+    show Backend, ImpactTransformer, ForeignResolver;
+import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem;
 import '../common/names.dart' show Identifiers, Names, Selectors, Uris;
 import '../common/registry.dart' show EagerRegistry, Registry;
-import '../common/tasks.dart' show CompilerTask;
 import '../common/resolution.dart'
-    show Feature, ListLiteralUse, MapLiteralUse, Resolution, ResolutionImpact;
+    show
+        Feature,
+        Frontend,
+        ListLiteralUse,
+        MapLiteralUse,
+        Resolution,
+        ResolutionImpact;
+import '../common/tasks.dart' show CompilerTask;
 import '../common/work.dart' show ItemCompilationContext;
-import '../compiler.dart' show Compiler;
 import '../compile_time_constants.dart';
+import '../compiler.dart' show Compiler;
 import '../constants/constant_system.dart';
 import '../constants/expressions.dart';
 import '../constants/values.dart';
@@ -33,11 +38,12 @@
 import '../diagnostics/invariant.dart' show DEBUG_MODE;
 import '../dump_info.dart' show DumpInfoTask;
 import '../elements/elements.dart';
+import '../elements/modelx.dart' show ConstructorBodyElementX;
 import '../elements/visitor.dart' show BaseElementVisitor;
 import '../enqueue.dart' show Enqueuer, ResolutionEnqueuer;
 import '../io/code_output.dart';
-import '../io/source_information.dart' show SourceInformationStrategy;
 import '../io/position_information.dart' show PositionSourceInformationStrategy;
+import '../io/source_information.dart' show SourceInformationStrategy;
 import '../io/start_end_information.dart'
     show StartEndSourceInformationStrategy;
 import '../js/js.dart' as jsAst;
@@ -45,18 +51,13 @@
 import '../js/js_source_mapping.dart' show JavaScriptSourceInformationStrategy;
 import '../js/rewrite_async.dart';
 import '../js_emitter/js_emitter.dart'
-    show
-        CodeEmitterTask,
-        Emitter,
-        MetadataCollector,
-        Placeholder,
-        USE_LAZY_EMITTER;
+    show CodeEmitterTask, MetadataCollector, Placeholder;
 import '../library_loader.dart' show LibraryLoader, LoadedLibraries;
 import '../native/native.dart' as native;
 import '../resolution/tree_elements.dart' show TreeElements;
 import '../ssa/builder.dart' show SsaFunctionCompiler;
-import '../ssa/nodes.dart' show HTypeConversion, HInstruction;
 import '../ssa/codegen.dart' show SsaCodeGenerator;
+import '../ssa/nodes.dart' show HTypeConversion, HInstruction;
 import '../tree/tree.dart';
 import '../types/types.dart';
 import '../universe/call_structure.dart' show CallStructure;
@@ -74,15 +75,14 @@
 import '../util/characters.dart';
 import '../util/util.dart';
 import '../world.dart' show ClassWorld;
-
 import 'backend_helpers.dart';
 import 'backend_impact.dart';
 import 'backend_serialization.dart' show JavaScriptBackendSerialization;
 import 'codegen/task.dart';
 import 'constant_system_javascript.dart';
-import 'native_data.dart' show NativeData;
 import 'js_interop_analysis.dart' show JsInteropAnalysis;
 import 'lookup_map_analysis.dart' show LookupMapAnalysis;
+import 'native_data.dart' show NativeData;
 import 'patch_resolver.dart';
 
 part 'backend.dart';
@@ -90,8 +90,8 @@
 part 'constant_emitter.dart';
 part 'constant_handler_javascript.dart';
 part 'custom_elements_analysis.dart';
-part 'frequency_namer.dart';
 part 'field_naming_mixin.dart';
+part 'frequency_namer.dart';
 part 'minify_namer.dart';
 part 'namer.dart';
 part 'namer_names.dart';
diff --git a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
index 2798ac3..448f979 100644
--- a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
@@ -5,15 +5,9 @@
 /// Analysis to determine how to generate code for typed JavaScript interop.
 library compiler.src.js_backend.js_interop_analysis;
 
-import '../diagnostics/messages.dart' show MessageKind;
 import '../constants/values.dart'
-    show
-        ConstantValue,
-        ConstructedConstantValue,
-        ListConstantValue,
-        NullConstantValue,
-        StringConstantValue,
-        TypeConstantValue;
+    show ConstantValue, ConstructedConstantValue, StringConstantValue;
+import '../diagnostics/messages.dart' show MessageKind;
 import '../elements/elements.dart'
     show
         ClassElement,
@@ -23,12 +17,10 @@
         LibraryElement,
         ParameterElement,
         MetadataAnnotation;
-
 import '../js/js.dart' as jsAst;
 import '../js/js.dart' show js;
 import '../universe/selector.dart' show Selector;
 import '../universe/universe.dart' show SelectorConstraints;
-
 import 'backend_helpers.dart' show BackendHelpers;
 import 'js_backend.dart' show JavaScriptBackend;
 
diff --git a/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart b/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
index a1543bd..ee4272a 100644
--- a/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
@@ -5,6 +5,8 @@
 /// Analysis to determine how to generate code for `LookupMap`s.
 library compiler.src.js_backend.lookup_map_analysis;
 
+import 'package:pub_semver/pub_semver.dart';
+
 import '../common.dart';
 import '../common/registry.dart' show Registry;
 import '../compiler.dart' show Compiler;
@@ -17,19 +19,10 @@
         StringConstantValue,
         TypeConstantValue;
 import '../dart_types.dart' show DartType;
+import '../dart_types.dart' show InterfaceType;
 import '../elements/elements.dart'
-    show
-        ClassElement,
-        Element,
-        Elements,
-        FieldElement,
-        FunctionElement,
-        FunctionSignature,
-        LibraryElement,
-        VariableElement;
+    show ClassElement, FieldElement, LibraryElement, VariableElement;
 import 'js_backend.dart' show JavaScriptBackend;
-import '../dart_types.dart' show DynamicType, InterfaceType;
-import 'package:pub_semver/pub_semver.dart';
 
 /// An analysis and optimization to remove unused entries from a `LookupMap`.
 ///
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 70d7eb7..4e8fe30 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -346,7 +346,6 @@
   /// The non-minifying namer's [callPrefix] with a dollar after it.
   static const String _callPrefixDollar = r'call$';
 
-  static final jsAst.Name _literalSuper = new StringBackedName("super");
   static final jsAst.Name _literalDollar = new StringBackedName(r'$');
   static final jsAst.Name _literalUnderscore = new StringBackedName('_');
   static final jsAst.Name literalPlus = new StringBackedName('+');
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
index cb4dc4f..0e02c6c 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
@@ -4,20 +4,13 @@
 
 library dart2js.js_emitter.full_emitter;
 
-import 'dart:convert';
 import 'dart:collection' show HashMap;
+import 'dart:convert';
 
 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames;
 import 'package:js_runtime/shared/embedded_names.dart'
     show JsBuiltin, JsGetName;
 
-import '../headers.dart';
-import '../js_emitter.dart' hide Emitter;
-import '../js_emitter.dart' as js_emitter show Emitter;
-import '../model.dart';
-import '../program_builder/program_builder.dart';
-import '../constant_ordering.dart' show deepCompareConstants;
-
 import '../../common.dart';
 import '../../common/names.dart' show Names;
 import '../../compiler.dart' show Compiler;
@@ -28,21 +21,16 @@
 import '../../elements/elements.dart'
     show
         ClassElement,
-        ConstructorBodyElement,
         Element,
         Elements,
-        ElementKind,
         FieldElement,
         FunctionElement,
         FunctionSignature,
         LibraryElement,
         MetadataAnnotation,
         MethodElement,
-        MemberElement,
         Name,
-        ParameterElement,
         TypedefElement,
-        TypeVariableElement,
         VariableElement;
 import '../../hash/sha1.dart' show Hasher;
 import '../../io/code_output.dart';
@@ -54,25 +42,25 @@
 import '../../js_backend/backend_helpers.dart' show BackendHelpers;
 import '../../js_backend/js_backend.dart'
     show
-        CheckedModeHelper,
         CompoundName,
         ConstantEmitter,
-        CustomElementsAnalysis,
         GetterName,
         JavaScriptBackend,
         JavaScriptConstantCompiler,
         Namer,
-        RuntimeTypes,
         SetterName,
-        Substitution,
-        TypeCheck,
-        TypeChecks,
         TypeVariableHandler;
 import '../../universe/call_structure.dart' show CallStructure;
 import '../../universe/selector.dart' show Selector;
-import '../../util/characters.dart' show $$, $A, $HASH, $PERIOD, $Z, $a, $z;
+import '../../util/characters.dart' show $$, $A, $HASH, $Z, $a, $z;
 import '../../util/uri_extras.dart' show relativize;
 import '../../util/util.dart' show equalElements;
+import '../constant_ordering.dart' show deepCompareConstants;
+import '../headers.dart';
+import '../js_emitter.dart' hide Emitter;
+import '../js_emitter.dart' as js_emitter show Emitter;
+import '../model.dart';
+import '../program_builder/program_builder.dart';
 
 part 'class_builder.dart';
 part 'class_emitter.dart';
diff --git a/pkg/compiler/lib/src/js_emitter/js_emitter.dart b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
index 0a305ed..c1543de 100644
--- a/pkg/compiler/lib/src/js_emitter/js_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
@@ -8,17 +8,13 @@
 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames;
 import 'package:js_runtime/shared/embedded_names.dart' show JsBuiltin;
 
+import '../closure.dart'
+    show ClosureClassElement, ClosureClassMap, ClosureFieldElement;
 import '../common.dart';
 import '../common/names.dart' show Identifiers;
 import '../common/tasks.dart' show CompilerTask;
 import '../compiler.dart' show Compiler;
 import '../constants/values.dart';
-import '../closure.dart'
-    show
-        ClosureClassElement,
-        ClosureClassMap,
-        ClosureFieldElement,
-        CapturedVariable;
 import '../core_types.dart' show CoreClasses;
 import '../dart_types.dart'
     show
@@ -32,17 +28,14 @@
 import '../elements/elements.dart'
     show
         ClassElement,
-        ConstructorBodyElement,
         ConstructorElement,
         Element,
-        Elements,
         ElementKind,
         FieldElement,
         FunctionElement,
         FunctionSignature,
         MetadataAnnotation,
         MethodElement,
-        MemberElement,
         MixinApplicationElement,
         ParameterElement,
         TypeVariableElement;
@@ -51,17 +44,12 @@
 import '../js_backend/backend_helpers.dart' show BackendHelpers;
 import '../js_backend/js_backend.dart'
     show
-        CheckedModeHelper,
-        CompoundName,
-        ConstantEmitter,
         CustomElementsAnalysis,
-        GetterName,
         JavaScriptBackend,
         JavaScriptConstantCompiler,
         Namer,
         RuntimeTypes,
         RuntimeTypesEncoder,
-        SetterName,
         Substitution,
         TypeCheck,
         TypeChecks,
@@ -70,7 +58,6 @@
 import '../universe/selector.dart' show Selector;
 import '../universe/universe.dart' show SelectorConstraints;
 import '../util/util.dart' show Setlet;
-
 import 'full_emitter/emitter.dart' as full_js_emitter;
 import 'lazy_emitter/emitter.dart' as lazy_js_emitter;
 import 'model.dart';
diff --git a/pkg/compiler/lib/src/js_emitter/lazy_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/lazy_emitter/emitter.dart
index e3f287b..64e1f79b 100644
--- a/pkg/compiler/lib/src/js_emitter/lazy_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/lazy_emitter/emitter.dart
@@ -4,8 +4,7 @@
 
 library dart2js.js_emitter.lazy_emitter;
 
-import 'package:js_runtime/shared/embedded_names.dart'
-    show JsBuiltin, METADATA, TYPES;
+import 'package:js_runtime/shared/embedded_names.dart' show JsBuiltin;
 
 import '../../common.dart';
 import '../../compiler.dart' show Compiler;
@@ -14,12 +13,10 @@
     show ClassElement, Element, FieldElement, FunctionElement;
 import '../../js/js.dart' as js;
 import '../../js_backend/js_backend.dart' show JavaScriptBackend, Namer;
-
 import '../js_emitter.dart' show NativeEmitter;
 import '../js_emitter.dart' as emitterTask show Emitter;
 import '../model.dart';
 import '../program_builder/program_builder.dart' show ProgramBuilder;
-
 import 'model_emitter.dart';
 
 class Emitter implements emitterTask.Emitter {
diff --git a/pkg/compiler/lib/src/js_emitter/model.dart b/pkg/compiler/lib/src/js_emitter/model.dart
index c7adf76..a9a6d26 100644
--- a/pkg/compiler/lib/src/js_emitter/model.dart
+++ b/pkg/compiler/lib/src/js_emitter/model.dart
@@ -7,9 +7,7 @@
 import '../constants/values.dart' show ConstantValue;
 import '../deferred_load.dart' show OutputUnit;
 import '../elements/elements.dart' show Element;
-import '../js/js.dart' as js
-    show Expression, Literal, Name, Statement, TokenFinalizer;
-
+import '../js/js.dart' as js show Expression, Name, Statement, TokenFinalizer;
 import 'js_emitter.dart' show MetadataCollector;
 
 class Program {
diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
index 6377d27..78f3cda 100644
--- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
@@ -35,11 +35,6 @@
 
   BackendHelpers get helpers => backend.helpers;
 
-  jsAst.Expression get defPropFunction {
-    Element element = helpers.defineProperty;
-    return emitterTask.staticFunctionAccess(element);
-  }
-
   /**
    * Prepares native classes for emission. Returns the unneeded classes.
    *
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 5d5afe6..145070f 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -4,6 +4,35 @@
 
 library dart2js.js_emitter.program_builder;
 
+import '../../closure.dart' show ClosureFieldElement;
+import '../../common.dart';
+import '../../common/names.dart' show Names, Selectors;
+import '../../compiler.dart' show Compiler;
+import '../../constants/values.dart'
+    show ConstantValue, InterceptorConstantValue;
+import '../../core_types.dart' show CoreClasses;
+import '../../dart_types.dart' show DartType, FunctionType, TypedefType;
+import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit;
+import '../../elements/elements.dart'
+    show
+        ClassElement,
+        Element,
+        Elements,
+        FieldElement,
+        FunctionElement,
+        FunctionSignature,
+        GetterElement,
+        LibraryElement,
+        MethodElement,
+        ParameterElement,
+        TypedefElement,
+        VariableElement;
+import '../../js/js.dart' as js;
+import '../../js_backend/backend_helpers.dart' show BackendHelpers;
+import '../../js_backend/js_backend.dart'
+    show Namer, JavaScriptBackend, JavaScriptConstantCompiler, StringBackedName;
+import '../../universe/selector.dart' show Selector;
+import '../../universe/universe.dart' show Universe, SelectorConstraints;
 import '../js_emitter.dart'
     show
         ClassStubGenerator,
@@ -17,40 +46,9 @@
         TypeTestProperties;
 import '../model.dart';
 
-import '../../closure.dart' show ClosureFieldElement;
-import '../../common.dart';
-import '../../common/names.dart' show Names, Selectors;
-import '../../compiler.dart' show Compiler;
-import '../../constants/values.dart'
-    show ConstantValue, InterceptorConstantValue;
-import '../../core_types.dart' show CoreClasses;
-import '../../dart_types.dart' show DartType, FunctionType, TypedefType;
-import '../../elements/elements.dart'
-    show
-        ClassElement,
-        Element,
-        Elements,
-        FieldElement,
-        FunctionElement,
-        FunctionSignature,
-        GetterElement,
-        LibraryElement,
-        MethodElement,
-        Name,
-        ParameterElement,
-        TypedefElement,
-        VariableElement;
-import '../../js/js.dart' as js;
-import '../../js_backend/backend_helpers.dart' show BackendHelpers;
-import '../../js_backend/js_backend.dart'
-    show Namer, JavaScriptBackend, JavaScriptConstantCompiler, StringBackedName;
-import '../../universe/selector.dart' show Selector;
-import '../../universe/universe.dart' show Universe, SelectorConstraints;
-import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit;
-
 part 'collector.dart';
-part 'registry.dart';
 part 'field_visitor.dart';
+part 'registry.dart';
 
 /// Builds a self-contained representation of the program that can then be
 /// emitted more easily by the individual emitters.
diff --git a/pkg/compiler/lib/src/library_loader.dart b/pkg/compiler/lib/src/library_loader.dart
index b666bfa..d555a73 100644
--- a/pkg/compiler/lib/src/library_loader.dart
+++ b/pkg/compiler/lib/src/library_loader.dart
@@ -6,9 +6,9 @@
 
 import 'dart:async';
 
-import 'common.dart';
 import 'common/names.dart' show Uris;
 import 'common/tasks.dart' show CompilerTask;
+import 'common.dart';
 import 'compiler.dart' show Compiler;
 import 'elements/elements.dart'
     show
@@ -16,8 +16,7 @@
         Element,
         ImportElement,
         ExportElement,
-        LibraryElement,
-        PrefixElement;
+        LibraryElement;
 import 'elements/modelx.dart'
     show
         CompilationUnitElementX,
@@ -30,11 +29,15 @@
         PrefixElementX,
         SyntheticImportElement;
 import 'environment.dart';
+import 'resolved_uri_translator.dart';
 import 'script.dart';
 import 'serialization/serialization.dart' show LibraryDeserializer;
 import 'tree/tree.dart';
 import 'util/util.dart' show Link, LinkBuilder;
 
+typedef Future<Iterable<LibraryElement>> ReuseLibrariesFunction(
+    Iterable<LibraryElement> libraries);
+
 /**
  * [CompilerTask] for loading libraries and setting up the import/export scopes.
  *
@@ -167,6 +170,10 @@
 
   /// Asynchronous version of [reset].
   Future resetAsync(Future<bool> reuseLibrary(LibraryElement library));
+
+  /// Similar to [resetAsync] but [reuseLibrary] maps all libraries to a list
+  /// of libraries that can be reused.
+  Future<Null> resetLibraries(ReuseLibrariesFunction reuseLibraries);
 }
 
 /// Handle for creating synthesized/patch libraries during library loading.
@@ -345,7 +352,17 @@
     return measure(() {
       assert(currentHandler == null);
 
-      wrapper(lib) => reuseLibrary(lib).then((reuse) => reuse ? lib : null);
+      Future<LibraryElement> wrapper(LibraryElement library) {
+        try {
+          return reuseLibrary(library)
+              .then((bool reuse) => reuse ? library : null);
+        } catch (exception, trace) {
+          reporter.onCrashInUserCode(
+              'Uncaught exception in reuseLibrary', exception, trace);
+          rethrow;
+        }
+      }
+
       List<Future<LibraryElement>> reusedLibrariesFuture =
           // TODO(sigmund): make measurements separate from compiler
           compiler.reuseLibraryTask.measure(
@@ -353,12 +370,32 @@
 
       return Future
           .wait(reusedLibrariesFuture)
-          .then((List<LibraryElement> reusedLibraries) {
+          .then((Iterable<LibraryElement> reusedLibraries) {
         resetImplementation(reusedLibraries.where((e) => e != null));
       });
     });
   }
 
+  Future<Null> resetLibraries(
+      Future<Iterable<LibraryElement>> reuseLibraries(
+          Iterable<LibraryElement> libraries)) {
+    assert(currentHandler == null);
+    return compiler.reuseLibraryTask.measure(() {
+      return new Future<Iterable<LibraryElement>>(() {
+        // Wrap in Future to shield against errors in user code.
+        return reuseLibraries(libraryCanonicalUriMap.values);
+      }).catchError((exception, StackTrace trace) {
+        compiler.reportCrashInUserCode(
+            'Uncaught exception in reuseLibraries', exception, trace);
+        throw exception; // Async rethrow.
+      }).then((Iterable<LibraryElement> reusedLibraries) {
+        measure(() {
+          resetImplementation(reusedLibraries);
+        });
+      });
+    });
+  }
+
   /// Insert [library] in the internal maps. Used for compiler reuse.
   void mapLibrary(LibraryElement library) {
     libraryCanonicalUriMap[library.canonicalUri] = library;
@@ -1405,17 +1442,6 @@
   String toString() => 'root=$rootLibrary,libraries=${loadedLibraries.keys}';
 }
 
-/// API used by the library loader to translate internal SDK URIs into file
-/// system readable URIs.
-abstract class ResolvedUriTranslator {
-  // TODO(sigmund): move here the comments from library loader.
-  /// Translate the resolved [uri] in the context of [importingLibrary].
-  ///
-  /// Use [spannable] for error reporting.
-  Uri translate(LibraryElement importingLibrary, Uri uri,
-      [Spannable spannable]);
-}
-
 // TODO(sigmund): remove ScriptLoader & ElementScanner. Such abstraction seems
 // rather low-level. It might be more practical to split the library-loading
 // task itself.  The task would continue to do the work of recursively loading
diff --git a/pkg/compiler/lib/src/mirrors/dart2js_mirrors.dart b/pkg/compiler/lib/src/mirrors/dart2js_mirrors.dart
index 745712a..9ca158b 100644
--- a/pkg/compiler/lib/src/mirrors/dart2js_mirrors.dart
+++ b/pkg/compiler/lib/src/mirrors/dart2js_mirrors.dart
@@ -18,16 +18,15 @@
 import '../tokens/token.dart';
 import '../tokens/token_constants.dart' as Tokens;
 import '../tree/tree.dart';
-import '../util/util.dart' show Link, LinkBuilder;
 import '../util/characters.dart' show $CR, $LF;
-
-import 'source_mirrors.dart';
+import '../util/util.dart' show Link;
 import 'mirrors_util.dart';
+import 'source_mirrors.dart';
 
-part 'dart2js_library_mirror.dart';
-part 'dart2js_type_mirrors.dart';
-part 'dart2js_member_mirrors.dart';
 part 'dart2js_instance_mirrors.dart';
+part 'dart2js_library_mirror.dart';
+part 'dart2js_member_mirrors.dart';
+part 'dart2js_type_mirrors.dart';
 
 //------------------------------------------------------------------------------
 // Utility types and functions for the dart2js mirror system
diff --git a/pkg/compiler/lib/src/mirrors_used.dart b/pkg/compiler/lib/src/mirrors_used.dart
index 15f7c6d..a13469e 100644
--- a/pkg/compiler/lib/src/mirrors_used.dart
+++ b/pkg/compiler/lib/src/mirrors_used.dart
@@ -4,8 +4,8 @@
 
 library dart2js.mirrors_used;
 
-import 'common.dart';
 import 'common/tasks.dart' show CompilerTask;
+import 'common.dart';
 import 'compile_time_constants.dart' show ConstantCompiler;
 import 'compiler.dart' show Compiler;
 import 'constants/expressions.dart';
@@ -16,7 +16,7 @@
         ListConstantValue,
         StringConstantValue,
         TypeConstantValue;
-import 'dart_types.dart' show DartType, InterfaceType, TypeKind;
+import 'dart_types.dart' show DartType, InterfaceType;
 import 'elements/elements.dart'
     show
         ClassElement,
@@ -27,8 +27,7 @@
         ScopeContainerElement,
         VariableElement;
 import 'resolution/tree_elements.dart' show TreeElements;
-import 'tree/tree.dart'
-    show Import, LibraryTag, NamedArgument, NewExpression, Node;
+import 'tree/tree.dart' show NamedArgument, NewExpression, Node;
 
 /**
  * Compiler task that analyzes MirrorsUsed annotations.
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index edca67c..daa6ddc 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -4,7 +4,7 @@
 
 import '../common.dart';
 import '../common/backend_api.dart' show ForeignResolver;
-import '../common/resolution.dart' show Parsing, Resolution;
+import '../common/resolution.dart' show ParsingContext, Resolution;
 import '../compiler.dart' show Compiler;
 import '../constants/values.dart';
 import '../core_types.dart' show CoreTypes;
@@ -28,6 +28,14 @@
   static const JsObject = const SpecialType._('=Object');
 
   int get hashCode => name.hashCode;
+
+  static SpecialType fromName(String name) {
+    if (name == '=Object') {
+      return JsObject;
+    } else {
+      throw new UnsupportedError("Unknown SpecialType '$name'.");
+    }
+  }
 }
 
 /// Description of the exception behaviour of native code.
@@ -70,6 +78,21 @@
     if (this == MUST) return 'must';
     return 'NativeThrowBehavior($_bits)';
   }
+
+  /// Canonical list of marker values.
+  ///
+  /// Added to make [NativeThrowBehavior] enum-like.
+  static const List<NativeThrowBehavior> values = const <NativeThrowBehavior>[
+    NEVER,
+    MAY_THROW_ONLY_ON_FIRST_ARGUMENT_ACCESS,
+    MAY,
+    MUST,
+  ];
+
+  /// Index to this marker within [values].
+  ///
+  /// Added to make [NativeThrowBehavior] enum-like.
+  int get index => values.indexOf(this);
 }
 
 /**
@@ -109,11 +132,12 @@
   /// [DartType]s or [SpecialType]s instantiated by the native element.
   final List typesInstantiated = [];
 
+  String codeTemplateText;
   // If this behavior is for a JS expression, [codeTemplate] contains the
   // parsed tree.
   js.Template codeTemplate;
 
-  final SideEffects sideEffects = new SideEffects.empty();
+  final SideEffects sideEffects;
 
   NativeThrowBehavior throwBehavior = NativeThrowBehavior.MAY;
 
@@ -128,6 +152,10 @@
   static NativeBehavior get CHANGES_OTHER => NativeBehavior._makeChangesOther();
   static NativeBehavior get DEPENDS_OTHER => NativeBehavior._makeDependsOther();
 
+  NativeBehavior() : sideEffects = new SideEffects.empty();
+
+  NativeBehavior.internal(this.sideEffects);
+
   String toString() {
     return 'NativeBehavior('
         'returns: ${typesReturned}'
@@ -460,7 +488,7 @@
   }
 
   static NativeBehavior ofJsCall(Send jsCall, DiagnosticReporter reporter,
-      Parsing parsing, CoreTypes coreTypes, ForeignResolver resolver) {
+      ParsingContext parsing, CoreTypes coreTypes, ForeignResolver resolver) {
     // The first argument of a JS-call is a string encoding various attributes
     // of the code.
     //
@@ -490,8 +518,8 @@
       return behavior;
     }
 
-    behavior.codeTemplate =
-        js.js.parseForeignJS(codeArgument.dartString.slowToString());
+    behavior.codeTemplateText = codeArgument.dartString.slowToString();
+    behavior.codeTemplate = js.js.parseForeignJS(behavior.codeTemplateText);
 
     String specString = specArgument.dartString.slowToString();
 
@@ -551,7 +579,7 @@
       NativeBehavior behavior,
       Send jsBuiltinOrEmbeddedGlobalCall,
       DiagnosticReporter reporter,
-      Parsing parsing,
+      ParsingContext parsing,
       CoreTypes coreTypes,
       ForeignResolver resolver,
       {bool isBuiltin,
@@ -619,7 +647,7 @@
   static NativeBehavior ofJsBuiltinCall(
       Send jsBuiltinCall,
       DiagnosticReporter reporter,
-      Parsing parsing,
+      ParsingContext parsing,
       CoreTypes coreTypes,
       ForeignResolver resolver) {
     NativeBehavior behavior = new NativeBehavior();
@@ -635,7 +663,7 @@
   static NativeBehavior ofJsEmbeddedGlobalCall(
       Send jsEmbeddedGlobalCall,
       DiagnosticReporter reporter,
-      Parsing parsing,
+      ParsingContext parsing,
       CoreTypes coreTypes,
       ForeignResolver resolver) {
     NativeBehavior behavior = new NativeBehavior();
@@ -773,7 +801,8 @@
       StringConstantValue specStringConstant = fields.single;
       String specString = specStringConstant.toDartString().slowToString();
       for (final typeString in specString.split('|')) {
-        var type = _parseType(typeString, compiler.parsing, lookup, annotation);
+        var type =
+            _parseType(typeString, compiler.parsingContext, lookup, annotation);
         if (types == null) types = [];
         types.add(type);
       }
@@ -815,7 +844,6 @@
         _escape(parameter, resolution);
       }
     } else {
-      DartType instantiated = null;
       JavaScriptBackend backend = compiler?.backend;
       if (!isInterop) {
         typesInstantiated.add(type);
@@ -848,8 +876,8 @@
     }
   }
 
-  static dynamic _parseType(
-      String typeString, Parsing parsing, lookup(name), locationNodeOrElement) {
+  static dynamic _parseType(String typeString, ParsingContext parsing,
+      lookup(name), locationNodeOrElement) {
     DiagnosticReporter reporter = parsing.reporter;
     if (typeString == '=Object') return SpecialType.JsObject;
     if (typeString == 'dynamic') {
@@ -874,7 +902,7 @@
     return const DynamicType();
   }
 
-  static _errorNode(locationNodeOrElement, Parsing parsing) {
+  static _errorNode(locationNodeOrElement, ParsingContext parsing) {
     if (locationNodeOrElement is Node) return locationNodeOrElement;
     return locationNodeOrElement.parseNode(parsing);
   }
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index 03f3fc2..c04509b 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -7,22 +7,20 @@
 import '../common.dart';
 import '../common/backend_api.dart' show ForeignResolver;
 import '../common/registry.dart' show Registry;
-import '../common/resolution.dart' show Parsing, Resolution;
+import '../common/resolution.dart' show Resolution;
 import '../compiler.dart' show Compiler;
 import '../constants/values.dart';
 import '../core_types.dart' show CoreTypes;
 import '../dart_types.dart';
-import '../enqueue.dart' show Enqueuer, ResolutionEnqueuer;
 import '../elements/elements.dart';
-import '../elements/modelx.dart'
-    show BaseClassElementX, ElementX, FunctionElementX, LibraryElementX;
+import '../elements/modelx.dart' show FunctionElementX;
+import '../enqueue.dart' show Enqueuer;
 import '../js_backend/backend_helpers.dart' show BackendHelpers;
 import '../js_backend/js_backend.dart';
 import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter;
 import '../tokens/token.dart' show BeginGroupToken, Token;
-import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN, STRING_TOKEN;
+import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
 import '../tree/tree.dart';
-
 import 'behavior.dart';
 
 /**
@@ -50,8 +48,6 @@
   /// Computes types instantiated due to setting a native field.
   void registerFieldStore(Element field) {}
 
-  NativeBehavior getNativeBehaviorOf(Send node) => new NativeBehavior();
-
   /// Returns whether native classes are being used.
   bool hasInstantiatedNativeClasses() => false;
 
@@ -97,10 +93,6 @@
   final queue = new Queue();
   bool flushing = false;
 
-  /// Maps JS foreign calls to their computed native behavior.
-  final Map<Node, NativeBehavior> nativeBehaviors =
-      new Map<Node, NativeBehavior>();
-
   final Enqueuer world;
   final Compiler compiler;
   final bool enableLiveTypeAnalysis;
@@ -468,7 +460,7 @@
     if (!backend.canLibraryUseNative(element.library)) return false;
     // Native method?
     return reporter.withCurrentElement(element, () {
-      Node node = element.parseNode(resolution.parsing);
+      Node node = element.parseNode(resolution.parsingContext);
       if (node is! FunctionExpression) return false;
       FunctionExpression functionExpression = node;
       node = functionExpression.body;
@@ -495,8 +487,6 @@
     registerNativeBehavior(NativeBehavior.ofFieldStore(field, compiler), field);
   }
 
-  NativeBehavior getNativeBehaviorOf(Send node) => nativeBehaviors[node];
-
   processNativeBehavior(NativeBehavior behavior, cause) {
     // TODO(ahe): Is this really a global dependency?
     Registry registry = compiler.globalDependencies;
@@ -615,11 +605,12 @@
    *     JS('_DOMWindowImpl', 'window')
    *
    */
-  void registerJsCall(Send node, ForeignResolver resolver) {
+  NativeBehavior resolveJsCall(Send node, ForeignResolver resolver) {
     NativeBehavior behavior = NativeBehavior.ofJsCall(
-        node, reporter, compiler.parsing, compiler.coreTypes, resolver);
+        node, reporter, compiler.parsingContext, compiler.coreTypes, resolver);
+    // TODO(johnniwinther): Move registration to the world impact application.
     registerNativeBehavior(behavior, node);
-    nativeBehaviors[node] = behavior;
+    return behavior;
   }
 
   /**
@@ -631,11 +622,13 @@
    *     JS_EMBEDDED_GLOBAL('String', 'foo')
    *
    */
-  void registerJsEmbeddedGlobalCall(Send node, ForeignResolver resolver) {
+  NativeBehavior resolveJsEmbeddedGlobalCall(
+      Send node, ForeignResolver resolver) {
     NativeBehavior behavior = NativeBehavior.ofJsEmbeddedGlobalCall(
-        node, reporter, compiler.parsing, compiler.coreTypes, resolver);
+        node, reporter, compiler.parsingContext, compiler.coreTypes, resolver);
+    // TODO(johnniwinther): Move registration to the world impact application.
     registerNativeBehavior(behavior, node);
-    nativeBehaviors[node] = behavior;
+    return behavior;
   }
 
   /**
@@ -647,11 +640,12 @@
    *     JS_BUILTIN('String', 'int2string', 0)
    *
    */
-  void registerJsBuiltinCall(Send node, ForeignResolver resolver) {
+  NativeBehavior resolveJsBuiltinCall(Send node, ForeignResolver resolver) {
     NativeBehavior behavior = NativeBehavior.ofJsBuiltinCall(
-        node, reporter, compiler.parsing, compiler.coreTypes, resolver);
+        node, reporter, compiler.parsingContext, compiler.coreTypes, resolver);
+    // TODO(johnniwinther): Move registration to the world impact application.
     registerNativeBehavior(behavior, node);
-    nativeBehaviors[node] = behavior;
+    return behavior;
   }
 }
 
diff --git a/pkg/compiler/lib/src/native/native.dart b/pkg/compiler/lib/src/native/native.dart
index 805196a..9a81401 100644
--- a/pkg/compiler/lib/src/native/native.dart
+++ b/pkg/compiler/lib/src/native/native.dart
@@ -13,24 +13,30 @@
 export 'scanner.dart';
 export 'ssa.dart';
 
+const Iterable<String> _allowedDartSchemePaths = const <String>[
+  'async',
+  'html',
+  'html_common',
+  'indexed_db',
+  'js',
+  'svg',
+  '_native_typed_data',
+  'web_audio',
+  'web_gl',
+  'web_sql'
+];
+
 bool maybeEnableNative(Compiler compiler, LibraryElement library) {
-  String libraryName = library.canonicalUri.toString();
-  if (library.entryCompilationUnit.script.name
-          .contains('sdk/tests/compiler/dart2js_native') ||
-      library.entryCompilationUnit.script.name
-          .contains('sdk/tests/compiler/dart2js_extra') ||
-      libraryName == 'dart:async' ||
-      libraryName == 'dart:html' ||
-      libraryName == 'dart:html_common' ||
-      libraryName == 'dart:indexed_db' ||
-      libraryName == 'dart:js' ||
-      libraryName == 'dart:svg' ||
-      libraryName == 'dart:_native_typed_data' ||
-      libraryName == 'dart:web_audio' ||
-      libraryName == 'dart:web_gl' ||
-      libraryName == 'dart:web_sql' ||
-      compiler.options.allowNativeExtensions) {
-    return true;
+  bool allowedTestLibrary() {
+    String scriptName = library.entryCompilationUnit.script.name;
+    return scriptName.contains('sdk/tests/compiler/dart2js_native') ||
+        scriptName.contains('sdk/tests/compiler/dart2js_extra');
   }
-  return false;
+  bool allowedDartLibary() {
+    Uri uri = library.canonicalUri;
+    if (uri.scheme != 'dart') return false;
+    return _allowedDartSchemePaths.contains(uri.path);
+  }
+
+  return allowedTestLibrary() || allowedDartLibary();
 }
diff --git a/pkg/compiler/lib/src/native/scanner.dart b/pkg/compiler/lib/src/native/scanner.dart
index f402431..f22b866 100644
--- a/pkg/compiler/lib/src/native/scanner.dart
+++ b/pkg/compiler/lib/src/native/scanner.dart
@@ -3,17 +3,17 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import '../common.dart';
-import '../parser/listener.dart' show Listener;
 import '../parser/element_listener.dart' show ElementListener;
+import '../parser/listener.dart' show Listener;
 import '../tokens/token.dart' show BeginGroupToken, Token;
-import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN, STRING_TOKEN;
+import '../tokens/token_constants.dart' as Tokens show STRING_TOKEN;
 
 void checkAllowedLibrary(ElementListener listener, Token token) {
   if (listener.scannerOptions.canUseNative) return;
   listener.reportError(token, MessageKind.NATIVE_NOT_SUPPORTED);
 }
 
-Token handleNativeBlockToSkip(Listener listener, Token token) {
+Token handleNativeBlockToSkip(ElementListener listener, Token token) {
   checkAllowedLibrary(listener, token);
   token = token.next;
   if (identical(token.kind, Tokens.STRING_TOKEN)) {
diff --git a/pkg/compiler/lib/src/native/ssa.dart b/pkg/compiler/lib/src/native/ssa.dart
index 7ab20c5..f3134c3 100644
--- a/pkg/compiler/lib/src/native/ssa.dart
+++ b/pkg/compiler/lib/src/native/ssa.dart
@@ -9,7 +9,7 @@
 import '../elements/elements.dart';
 import '../js/js.dart' as js;
 import '../js_backend/js_backend.dart';
-import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter;
+import '../js_emitter/js_emitter.dart' show NativeEmitter;
 import '../ssa/builder.dart' show SsaBuilder;
 import '../ssa/nodes.dart' show HInstruction, HForeignCode, HReturn;
 import '../tree/tree.dart';
diff --git a/pkg/compiler/lib/src/parser/diet_parser_task.dart b/pkg/compiler/lib/src/parser/diet_parser_task.dart
index 6d9302e..4192143 100644
--- a/pkg/compiler/lib/src/parser/diet_parser_task.dart
+++ b/pkg/compiler/lib/src/parser/diet_parser_task.dart
@@ -5,6 +5,7 @@
 library dart2js.parser.diet.task;
 
 import '../common.dart';
+import '../common/backend_api.dart' show Backend;
 import '../common/tasks.dart' show CompilerTask;
 import '../compiler.dart' show Compiler;
 import '../elements/elements.dart' show CompilationUnitElement;
@@ -19,23 +20,28 @@
 class DietParserTask extends CompilerTask {
   final ParserOptions _parserOptions;
   final IdGenerator _idGenerator;
+  final Backend _backend;
+  final DiagnosticReporter _reporter;
 
-  DietParserTask(Compiler compiler, this._parserOptions, this._idGenerator)
+  DietParserTask(Compiler compiler, this._parserOptions, this._idGenerator,
+      this._backend, this._reporter)
       : super(compiler);
 
   final String name = 'Diet Parser';
 
   dietParse(CompilationUnitElement compilationUnit, Token tokens) {
     measure(() {
-      ScannerOptions scannerOptions =
-          new ScannerOptions.from(compiler, compilationUnit.library);
+      ScannerOptions scannerOptions = new ScannerOptions(
+          canUseNative: _backend.canLibraryUseNative(compilationUnit.library));
       ElementListener listener = new ElementListener(
-          scannerOptions, compiler.reporter, compilationUnit, _idGenerator);
+          scannerOptions, _reporter, compilationUnit, _idGenerator);
       PartialParser parser = new PartialParser(listener, _parserOptions);
       try {
         parser.parseUnit(tokens);
       } on ParserError catch (_) {
-        assert(invariant(compilationUnit, compiler.compilationFailed));
+        // TODO(johnniwinther): assert that the error was reported once there is
+        // a [hasErrorBeenReported] field in [DiagnosticReporter]
+        // The error should have already been reported by the parser.
       }
     });
   }
diff --git a/pkg/compiler/lib/src/parser/element_listener.dart b/pkg/compiler/lib/src/parser/element_listener.dart
index b089ae5..0cd21ac 100644
--- a/pkg/compiler/lib/src/parser/element_listener.dart
+++ b/pkg/compiler/lib/src/parser/element_listener.dart
@@ -51,9 +51,6 @@
   final bool canUseNative;
 
   const ScannerOptions({this.canUseNative: false});
-
-  ScannerOptions.from(Compiler compiler, LibraryElement libraryElement)
-      : canUseNative = compiler.backend.canLibraryUseNative(libraryElement);
 }
 
 /**
@@ -368,10 +365,10 @@
     pushNode(null);
   }
 
-  void endTypeVariable(Token token) {
+  void endTypeVariable(Token token, Token extendsOrSuper) {
     TypeAnnotation bound = popNode();
     Identifier name = popNode();
-    pushNode(new TypeVariable(name, bound));
+    pushNode(new TypeVariable(name, extendsOrSuper, bound));
     rejectBuiltInIdentifier(name);
   }
 
diff --git a/pkg/compiler/lib/src/parser/listener.dart b/pkg/compiler/lib/src/parser/listener.dart
index e1e4c3c..1294bf1 100644
--- a/pkg/compiler/lib/src/parser/listener.dart
+++ b/pkg/compiler/lib/src/parser/listener.dart
@@ -301,7 +301,7 @@
 
   void beginTypeVariable(Token token) {}
 
-  void endTypeVariable(Token token) {}
+  void endTypeVariable(Token token, Token extendsOrSuper) {}
 
   void beginTypeVariables(Token token) {}
 
diff --git a/pkg/compiler/lib/src/parser/member_listener.dart b/pkg/compiler/lib/src/parser/member_listener.dart
index a13024c..b50847e 100644
--- a/pkg/compiler/lib/src/parser/member_listener.dart
+++ b/pkg/compiler/lib/src/parser/member_listener.dart
@@ -5,13 +5,11 @@
 library dart2js.parser.member_listener;
 
 import '../common.dart';
-import '../elements/elements.dart'
-    show Element, ElementKind, Elements, MetadataAnnotation;
+import '../elements/elements.dart' show Element, ElementKind, Elements;
 import '../elements/modelx.dart'
     show ClassElementX, ElementX, FieldElementX, VariableList;
 import '../tokens/token.dart' show Token;
 import '../tree/tree.dart';
-
 import 'element_listener.dart' show ScannerOptions;
 import 'node_listener.dart' show NodeListener;
 import 'partial_elements.dart'
diff --git a/pkg/compiler/lib/src/parser/node_listener.dart b/pkg/compiler/lib/src/parser/node_listener.dart
index df288b6..9f6e18b 100644
--- a/pkg/compiler/lib/src/parser/node_listener.dart
+++ b/pkg/compiler/lib/src/parser/node_listener.dart
@@ -7,12 +7,10 @@
 import '../common.dart';
 import '../elements/elements.dart' show CompilationUnitElement;
 import '../native/native.dart' as native;
-import '../tokens/precedence_constants.dart' as Precedence
-    show BAD_INPUT_INFO, EOF_INFO, INDEX_INFO;
+import '../tokens/precedence_constants.dart' as Precedence show INDEX_INFO;
 import '../tokens/token.dart' show ErrorToken, StringToken, Token;
 import '../tree/tree.dart';
 import '../util/util.dart' show Link;
-
 import 'element_listener.dart' show ElementListener, ScannerOptions;
 import 'partial_elements.dart' show PartialFunctionElement;
 
@@ -566,6 +564,7 @@
 
   void handleFunctionTypedFormalParameter(Token endToken) {
     NodeList formals = popNode();
+    popNode(); // typeVariables
     Identifier name = popNode();
     TypeAnnotation returnType = popNode();
     pushNode(null); // Signal "no type" to endFormalParameter.
@@ -755,6 +754,7 @@
     Statement body = popNode();
     AsyncModifier asyncModifier = popNode();
     NodeList formals = popNode();
+    popNode(); // typeVariables
     pushNode(new FunctionExpression(
         null, formals, body, null, Modifiers.EMPTY, null, null, asyncModifier));
   }
diff --git a/pkg/compiler/lib/src/parser/parser.dart b/pkg/compiler/lib/src/parser/parser.dart
index a584afb..821fcad 100644
--- a/pkg/compiler/lib/src/parser/parser.dart
+++ b/pkg/compiler/lib/src/parser/parser.dart
@@ -15,7 +15,6 @@
         CASCADE_PRECEDENCE,
         EQUALITY_PRECEDENCE,
         GT_INFO,
-        GT_GT_INFO,
         IS_INFO,
         MINUS_MINUS_INFO,
         OPEN_PAREN_INFO,
@@ -105,9 +104,9 @@
   final bool enableGenericMethodSyntax;
 
   Parser(this.listener, ParserOptions parserOptions,
-      {this.asyncAwaitKeywordsEnabled: false}) :
-          parserOptions = parserOptions,
-          enableGenericMethodSyntax = parserOptions.enableGenericMethodSyntax;
+      {this.asyncAwaitKeywordsEnabled: false})
+      : parserOptions = parserOptions,
+        enableGenericMethodSyntax = parserOptions.enableGenericMethodSyntax;
 
   Token parseUnit(Token token) {
     listener.beginCompilationUnit(token);
@@ -461,6 +460,11 @@
     }
     token = parseIdentifier(token);
     if (optional('(', token)) {
+      listener.handleNoTypeVariables(token);
+      token = parseFormalParameters(token);
+      listener.handleFunctionTypedFormalParameter(token);
+    } else if (enableGenericMethodSyntax && optional('<', token)) {
+      token = parseTypeVariablesOpt(token);
       token = parseFormalParameters(token);
       listener.handleFunctionTypedFormalParameter(token);
     }
@@ -765,12 +769,15 @@
   Token parseTypeVariable(Token token) {
     listener.beginTypeVariable(token);
     token = parseIdentifier(token);
-    if (optional('extends', token)) {
+    Token extendsOrSuper = null;
+    if (optional('extends', token) ||
+        (enableGenericMethodSyntax && optional('super', token))) {
+      extendsOrSuper = token;
       token = parseType(token.next);
     } else {
       listener.handleNoType(token);
     }
-    listener.endTypeVariable(token);
+    listener.endTypeVariable(token, extendsOrSuper);
     return token;
   }
 
@@ -1843,15 +1850,37 @@
         // We are looking at "type identifier '('".
         BeginGroupToken beginParen = afterId;
         Token endParen = beginParen.endGroup;
+        // TODO(eernst): Check for NPE as described in issue 26252.
         Token afterParens = endParen.next;
         if (optional('{', afterParens) ||
             optional('=>', afterParens) ||
             optional('async', afterParens) ||
             optional('sync', afterParens)) {
           // We are looking at "type identifier '(' ... ')'" followed
-          // by '=>' or '{'.
+          // by '{', '=>', 'async', or 'sync'.
           return parseFunctionDeclaration(token);
         }
+      } else if (enableGenericMethodSyntax &&
+          identical(afterIdKind, LT_TOKEN)) {
+        // We are looking at "type identifier '<'".
+        BeginGroupToken beginAngle = afterId;
+        Token endAngle = beginAngle.endGroup;
+        if (endAngle != null &&
+            identical(endAngle.next.kind, OPEN_PAREN_TOKEN)) {
+          BeginGroupToken beginParen = endAngle.next;
+          Token endParen = beginParen.endGroup;
+          if (endParen != null) {
+            Token afterParens = endParen.next;
+            if (optional('{', afterParens) ||
+                optional('=>', afterParens) ||
+                optional('async', afterParens) ||
+                optional('sync', afterParens)) {
+              // We are looking at "type identifier '<' ... '>' '(' ... ')'"
+              // followed by '{', '=>', 'async', or 'sync'.
+              return parseFunctionDeclaration(token);
+            }
+          }
+        }
       }
       // Fall-through to expression statement.
     } else {
@@ -1859,6 +1888,7 @@
         return parseLabeledStatement(token);
       } else if (optional('(', token.next)) {
         BeginGroupToken begin = token.next;
+        // TODO(eernst): Check for NPE as described in issue 26252.
         String afterParens = begin.endGroup.next.stringValue;
         if (identical(afterParens, '{') ||
             identical(afterParens, '=>') ||
@@ -1866,6 +1896,24 @@
             identical(afterParens, 'sync')) {
           return parseFunctionDeclaration(token);
         }
+      } else if (enableGenericMethodSyntax && optional('<', token.next)) {
+        BeginGroupToken beginAngle = token.next;
+        Token endAngle = beginAngle.endGroup;
+        if (endAngle != null &&
+            identical(endAngle.next.kind, OPEN_PAREN_TOKEN)) {
+          BeginGroupToken beginParen = endAngle.next;
+          Token endParen = beginParen.endGroup;
+          if (endParen != null) {
+            String afterParens = endParen.next.stringValue;
+            if (identical(afterParens, '{') ||
+                identical(afterParens, '=>') ||
+                identical(afterParens, 'async') ||
+                identical(afterParens, 'sync')) {
+              return parseFunctionDeclaration(token);
+            }
+          }
+        }
+        // Fall through to expression statement.
       }
     }
     return parseExpressionStatement(token);
@@ -2133,11 +2181,14 @@
       }
     } else if (kind == OPEN_PAREN_TOKEN) {
       return parseParenthesizedExpressionOrFunctionLiteral(token);
-    } else if ((kind == LT_TOKEN) ||
-        (kind == OPEN_SQUARE_BRACKET_TOKEN) ||
-        (kind == OPEN_CURLY_BRACKET_TOKEN) ||
-        token.stringValue == '[]') {
-      return parseLiteralListOrMap(token);
+    } else if (kind == OPEN_SQUARE_BRACKET_TOKEN || token.stringValue == '[]') {
+      listener.handleNoTypeArguments(token);
+      return parseLiteralListSuffix(token, null);
+    } else if (kind == OPEN_CURLY_BRACKET_TOKEN) {
+      listener.handleNoTypeArguments(token);
+      return parseLiteralMapSuffix(token, null);
+    } else if (kind == LT_TOKEN) {
+      return parseLiteralListOrMapOrFunction(token, null);
     } else {
       return listener.expectedExpression(token);
     }
@@ -2145,6 +2196,7 @@
 
   Token parseParenthesizedExpressionOrFunctionLiteral(Token token) {
     BeginGroupToken beginGroup = token;
+    // TODO(eernst): Check for NPE as described in issue 26252.
     Token nextToken = beginGroup.endGroup.next;
     int kind = nextToken.kind;
     if (mayParseFunctionExpressions &&
@@ -2152,6 +2204,7 @@
             identical(kind, OPEN_CURLY_BRACKET_TOKEN) ||
             (identical(kind, KEYWORD_TOKEN) &&
                 (nextToken.value == 'async' || nextToken.value == 'sync')))) {
+      listener.handleNoTypeVariables(token);
       return parseUnnamedFunction(token);
     } else {
       bool old = mayParseFunctionExpressions;
@@ -2201,30 +2254,16 @@
     return token;
   }
 
-  Token parseLiteralListOrMap(Token token) {
-    Token constKeyword = null;
-    if (optional('const', token)) {
-      constKeyword = token;
-      token = token.next;
-    }
-    token = parseTypeArgumentsOpt(token);
+  /// '[' (expressionList ','?)? ']'.
+  ///
+  /// Provide [constKeyword] if preceded by 'const', null if not.
+  /// This is a suffix parser because it is assumed that type arguments have
+  /// been parsed, or `listener.handleNoTypeArguments(..)` has been executed.
+  Token parseLiteralListSuffix(Token token, Token constKeyword) {
+    assert(optional('[', token) || optional('[]', token));
     Token beginToken = token;
     int count = 0;
-    if (optional('{', token)) {
-      bool old = mayParseFunctionExpressions;
-      mayParseFunctionExpressions = true;
-      do {
-        if (optional('}', token.next)) {
-          token = token.next;
-          break;
-        }
-        token = parseMapLiteralEntry(token.next);
-        ++count;
-      } while (optional(',', token));
-      mayParseFunctionExpressions = old;
-      listener.handleLiteralMap(count, beginToken, constKeyword, token);
-      return expect('}', token);
-    } else if (optional('[', token)) {
+    if (optional('[', token)) {
       bool old = mayParseFunctionExpressions;
       mayParseFunctionExpressions = true;
       do {
@@ -2238,10 +2277,83 @@
       mayParseFunctionExpressions = old;
       listener.handleLiteralList(count, beginToken, constKeyword, token);
       return expect(']', token);
-    } else if (optional('[]', token)) {
-      listener.handleLiteralList(0, token, constKeyword, token);
-      return token.next;
+    }
+    // Looking at '[]'.
+    listener.handleLiteralList(0, token, constKeyword, token);
+    return token.next;
+  }
+
+  /// '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'.
+  ///
+  /// Provide token for [constKeyword] if preceded by 'const', null if not.
+  /// This is a suffix parser because it is assumed that type arguments have
+  /// been parsed, or `listener.handleNoTypeArguments(..)` has been executed.
+  Token parseLiteralMapSuffix(Token token, Token constKeyword) {
+    assert(optional('{', token));
+    Token beginToken = token;
+    int count = 0;
+    bool old = mayParseFunctionExpressions;
+    mayParseFunctionExpressions = true;
+    do {
+      if (optional('}', token.next)) {
+        token = token.next;
+        break;
+      }
+      token = parseMapLiteralEntry(token.next);
+      ++count;
+    } while (optional(',', token));
+    mayParseFunctionExpressions = old;
+    listener.handleLiteralMap(count, beginToken, constKeyword, token);
+    return expect('}', token);
+  }
+
+  /// formalParameterList functionBody.
+  ///
+  /// This is a suffix parser because it is assumed that type arguments have
+  /// been parsed, or `listener.handleNoTypeArguments(..)` has been executed.
+  Token parseLiteralFunctionSuffix(Token token) {
+    assert(optional('(', token));
+    BeginGroupToken beginGroup = token;
+    if (beginGroup.endGroup != null) {
+      Token nextToken = beginGroup.endGroup.next;
+      int kind = nextToken.kind;
+      if (identical(kind, FUNCTION_TOKEN) ||
+          identical(kind, OPEN_CURLY_BRACKET_TOKEN) ||
+          (identical(kind, KEYWORD_TOKEN) &&
+              (nextToken.value == 'async' || nextToken.value == 'sync'))) {
+        return parseUnnamedFunction(token);
+      }
+      // Fall through.
+    }
+    listener.unexpected(token);
+    return null;
+  }
+
+  /// genericListLiteral | genericMapLiteral | genericFunctionLiteral.
+  ///
+  /// Where
+  ///   genericListLiteral ::= typeArguments '[' (expressionList ','?)? ']'
+  ///   genericMapLiteral ::=
+  ///       typeArguments '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
+  ///   genericFunctionLiteral ::=
+  ///       typeParameters formalParameterList functionBody
+  /// Provide token for [constKeyword] if preceded by 'const', null if not.
+  Token parseLiteralListOrMapOrFunction(Token token, Token constKeyword) {
+    assert(optional('<', token));
+    BeginGroupToken begin = token;
+    if (enableGenericMethodSyntax &&
+        constKeyword == null &&
+        begin.endGroup != null &&
+        identical(begin.endGroup.next.kind, OPEN_PAREN_TOKEN)) {
+      token = parseTypeVariablesOpt(token);
+      return parseLiteralFunctionSuffix(token);
     } else {
+      token = parseTypeArgumentsOpt(token);
+      if (optional('{', token)) {
+        return parseLiteralMapSuffix(token, constKeyword);
+      } else if ((optional('[', token)) || (optional('[]', token))) {
+        return parseLiteralListSuffix(token, constKeyword);
+      }
       listener.unexpected(token);
       return null;
     }
@@ -2273,8 +2385,14 @@
   }
 
   bool isFunctionDeclaration(Token token) {
+    if (enableGenericMethodSyntax && optional('<', token)) {
+      BeginGroupToken begin = token;
+      if (begin.endGroup == null) return false;
+      token = begin.endGroup.next;
+    }
     if (optional('(', token)) {
       BeginGroupToken begin = token;
+      // TODO(eernst): Check for NPE as described in issue 26252.
       String afterParens = begin.endGroup.next.stringValue;
       if (identical(afterParens, '{') ||
           identical(afterParens, '=>') ||
@@ -2309,11 +2427,16 @@
     Token constKeyword = token;
     token = expect('const', token);
     final String value = token.stringValue;
-    if ((identical(value, '<')) ||
-        (identical(value, '[')) ||
-        (identical(value, '[]')) ||
-        (identical(value, '{'))) {
-      return parseLiteralListOrMap(constKeyword);
+    if ((identical(value, '[')) || (identical(value, '[]'))) {
+      listener.handleNoTypeArguments(token);
+      return parseLiteralListSuffix(token, constKeyword);
+    }
+    if (identical(value, '{')) {
+      listener.handleNoTypeArguments(token);
+      return parseLiteralMapSuffix(token, constKeyword);
+    }
+    if (identical(value, '<')) {
+      return parseLiteralListOrMapOrFunction(token, constKeyword);
     }
     token = parseConstructorReference(token);
     token = parseRequiredArguments(token);
diff --git a/pkg/compiler/lib/src/parser/parser_task.dart b/pkg/compiler/lib/src/parser/parser_task.dart
index 471ebf6..6470d1f 100644
--- a/pkg/compiler/lib/src/parser/parser_task.dart
+++ b/pkg/compiler/lib/src/parser/parser_task.dart
@@ -25,7 +25,7 @@
   String get name => 'Parser';
 
   Node parse(ElementX element) {
-    return measure(() => element.parseNode(compiler.parsing));
+    return measure(() => element.parseNode(compiler.parsingContext));
   }
 
   Node parseCompilationUnit(Token token) {
diff --git a/pkg/compiler/lib/src/parser/partial_elements.dart b/pkg/compiler/lib/src/parser/partial_elements.dart
index a99ba64..8e74bf3 100644
--- a/pkg/compiler/lib/src/parser/partial_elements.dart
+++ b/pkg/compiler/lib/src/parser/partial_elements.dart
@@ -5,18 +5,15 @@
 library dart2js.parser.partial_elements;
 
 import '../common.dart';
-import '../common/resolution.dart' show Parsing, Resolution;
+import '../common/resolution.dart' show ParsingContext, Resolution;
 import '../dart_types.dart' show DynamicType;
 import '../elements/elements.dart'
     show
         CompilationUnitElement,
-        ConstructorElement,
         Element,
         ElementKind,
         GetterElement,
-        LibraryElement,
         MetadataAnnotation,
-        MethodElement,
         SetterElement,
         STATE_NOT_STARTED,
         STATE_DONE;
@@ -27,7 +24,6 @@
         ConstructorElementX,
         DeclarationSite,
         ElementX,
-        FieldElementX,
         GetterElementX,
         MetadataAnnotationX,
         MethodElementX,
@@ -35,24 +31,14 @@
         TypedefElementX,
         VariableList;
 import '../elements/visitor.dart' show ElementVisitor;
-import '../tokens/token.dart'
-    show
-        BadInputToken,
-        BeginGroupToken,
-        ErrorToken,
-        KeywordToken,
-        StringToken,
-        Token,
-        UnmatchedToken,
-        UnterminatedToken;
+import '../tokens/token.dart' show Token;
 import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
 import '../tree/tree.dart';
-
 import 'class_element_parser.dart' show ClassElementParser;
-import 'parser.dart' show Parser;
 import 'listener.dart' show ParserError;
 import 'member_listener.dart' show MemberListener;
 import 'node_listener.dart' show NodeListener;
+import 'parser.dart' show Parser;
 
 abstract class PartialElement implements DeclarationSite {
   Token beginToken;
@@ -97,7 +83,7 @@
     return cachedNode;
   }
 
-  FunctionExpression parseNode(Parsing parsing) {
+  FunctionExpression parseNode(ParsingContext parsing) {
     if (cachedNode != null) return cachedNode;
     parseFunction(Parser p) {
       if (isClassMember && modifiers.isFactory) {
@@ -240,7 +226,7 @@
     super.hasParseError = hasParseError;
   }
 
-  VariableDefinitions parseNode(Element element, Parsing parsing) {
+  VariableDefinitions parseNode(Element element, ParsingContext parsing) {
     if (definitions != null) return definitions;
     DiagnosticReporter reporter = parsing.reporter;
     reporter.withCurrentElement(element, () {
@@ -265,7 +251,7 @@
   computeType(Element element, Resolution resolution) {
     if (type != null) return type;
     // TODO(johnniwinther): Compute this in the resolver.
-    VariableDefinitions node = parseNode(element, resolution.parsing);
+    VariableDefinitions node = parseNode(element, resolution.parsingContext);
     if (node.type != null) {
       type = resolution.reporter.withCurrentElement(element, () {
         return resolution.resolveTypeAnnotation(element, node.type);
@@ -288,7 +274,7 @@
 
   Token get token => beginToken;
 
-  Node parseNode(Parsing parsing) {
+  Node parseNode(ParsingContext parsing) {
     if (cachedNode != null) return cachedNode;
     cachedNode = parse(parsing, this, declarationSite,
         (p) => p.parseTopLevelDeclaration(token));
@@ -329,7 +315,7 @@
     throw new UnsupportedError("endToken=");
   }
 
-  Node parseNode(Parsing parsing) {
+  Node parseNode(ParsingContext parsing) {
     if (cachedNode != null) return cachedNode;
     var metadata = parse(parsing, annotatedElement, declarationSite,
         (p) => p.parseMetadata(beginToken));
@@ -380,7 +366,7 @@
     return cachedNode;
   }
 
-  ClassNode parseNode(Parsing parsing) {
+  ClassNode parseNode(ParsingContext parsing) {
     if (cachedNode != null) return cachedNode;
     DiagnosticReporter reporter = parsing.reporter;
     reporter.withCurrentElement(this, () {
@@ -440,7 +426,7 @@
   }
 }
 
-Node parse(Parsing parsing, ElementX element, PartialElement partial,
+Node parse(ParsingContext parsing, ElementX element, PartialElement partial,
     doParse(Parser parser)) {
   DiagnosticReporter reporter = parsing.reporter;
   return parsing.measure(() {
diff --git a/pkg/compiler/lib/src/patch_parser.dart b/pkg/compiler/lib/src/patch_parser.dart
index 0e9943d..9baaeb3 100644
--- a/pkg/compiler/lib/src/patch_parser.dart
+++ b/pkg/compiler/lib/src/patch_parser.dart
@@ -116,10 +116,10 @@
 
 import 'dart:async';
 
-import 'constants/values.dart' show ConstantValue;
+import 'common/tasks.dart' show CompilerTask;
 import 'common.dart';
 import 'compiler.dart' show Compiler;
-import 'common/tasks.dart' show CompilerTask;
+import 'constants/values.dart' show ConstantValue;
 import 'dart_types.dart' show DartType;
 import 'elements/elements.dart';
 import 'elements/modelx.dart'
@@ -128,18 +128,17 @@
         ClassElementX,
         GetterElementX,
         LibraryElementX,
-        MetadataAnnotationX,
         SetterElementX;
 import 'id_generator.dart';
 import 'js_backend/js_backend.dart' show JavaScriptBackend;
 import 'library_loader.dart' show LibraryLoader;
 import 'options.dart' show ParserOptions;
-import 'parser/listener.dart' show Listener, ParserError;
 import 'parser/element_listener.dart' show ElementListener;
+import 'parser/listener.dart' show Listener, ParserError;
 import 'parser/member_listener.dart' show MemberListener;
+import 'parser/parser.dart' show Parser;
 import 'parser/partial_elements.dart' show PartialClassElement;
 import 'parser/partial_parser.dart' show PartialParser;
-import 'parser/parser.dart' show Parser;
 import 'scanner/scanner.dart' show Scanner;
 import 'script.dart';
 import 'tokens/token.dart' show StringToken, Token;
@@ -177,8 +176,8 @@
       // TODO(johnniwinther): Test that parts and exports are handled correctly.
       Script script = compilationUnit.script;
       Token tokens = new Scanner(script.file).tokenize();
-      Listener patchListener =
-          new PatchElementListener(compiler, compilationUnit, compiler);
+      Listener patchListener = new PatchElementListener(
+          compiler, compilationUnit, compiler.idGenerator);
       try {
         new PartialParser(patchListener, parserOptions).parseUnit(tokens);
       } on ParserError catch (e) {
@@ -217,7 +216,7 @@
 
   PatchMemberListener(Compiler compiler, ClassElement enclosingClass)
       : this.compiler = compiler,
-        super(compiler.parsing.getScannerOptionsFor(enclosingClass),
+        super(compiler.parsingContext.getScannerOptionsFor(enclosingClass),
             compiler.reporter, enclosingClass);
 
   @override
@@ -262,7 +261,7 @@
   PatchElementListener(Compiler compiler, CompilationUnitElement patchElement,
       IdGenerator idGenerator)
       : this.compiler = compiler,
-        super(compiler.parsing.getScannerOptionsFor(patchElement),
+        super(compiler.parsingContext.getScannerOptionsFor(patchElement),
             compiler.reporter, patchElement, idGenerator);
 
   @override
diff --git a/pkg/compiler/lib/src/resolution/class_hierarchy.dart b/pkg/compiler/lib/src/resolution/class_hierarchy.dart
index 25893e2..adaa177 100644
--- a/pkg/compiler/lib/src/resolution/class_hierarchy.dart
+++ b/pkg/compiler/lib/src/resolution/class_hierarchy.dart
@@ -211,7 +211,11 @@
       FunctionElement constructor =
           new SynthesizedConstructorElementX.forDefault(superMember, element);
       if (superMember.isMalformed) {
-        compiler.elementsWithCompileTimeErrors.add(constructor);
+        ErroneousElement erroneousElement = superMember;
+        compiler.registerCompiletimeError(constructor,
+            reporter.createMessage(node,
+                erroneousElement.messageKind,
+                erroneousElement.messageArguments));
       }
       element.setDefaultConstructor(constructor, reporter);
     }
@@ -299,8 +303,11 @@
     String superName = supertype.name;
     String mixinName = mixinType.name;
     MixinApplicationElementX mixinApplication =
-        new UnnamedMixinApplicationElementX("${superName}+${mixinName}",
-            element.compilationUnit, compiler.getNextFreeId(), node);
+        new UnnamedMixinApplicationElementX(
+            "${superName}+${mixinName}",
+            element.compilationUnit,
+            compiler.idGenerator.getNextFreeId(),
+            node);
     // Create synthetic type variables for the mixin application.
     List<DartType> typeVariables = <DartType>[];
     int index = 0;
@@ -352,7 +359,7 @@
 
   void doApplyMixinTo(MixinApplicationElementX mixinApplication,
       DartType supertype, DartType mixinType) {
-    Node node = mixinApplication.parseNode(resolution.parsing);
+    Node node = mixinApplication.parseNode(resolution.parsingContext);
 
     if (mixinApplication.supertype != null) {
       // [supertype] is not null if there was a cycle.
diff --git a/pkg/compiler/lib/src/resolution/class_members.dart b/pkg/compiler/lib/src/resolution/class_members.dart
index eb993bd..6a06749 100644
--- a/pkg/compiler/lib/src/resolution/class_members.dart
+++ b/pkg/compiler/lib/src/resolution/class_members.dart
@@ -18,8 +18,7 @@
         MemberElement,
         MemberSignature,
         MixinApplicationElement,
-        Name,
-        PublicName;
+        Name;
 import '../util/util.dart';
 
 part 'member_impl.dart';
diff --git a/pkg/compiler/lib/src/resolution/constructors.dart b/pkg/compiler/lib/src/resolution/constructors.dart
index 9e40cff..0f9f099 100644
--- a/pkg/compiler/lib/src/resolution/constructors.dart
+++ b/pkg/compiler/lib/src/resolution/constructors.dart
@@ -77,7 +77,7 @@
     if (initialized.containsKey(field)) {
       reportDuplicateInitializerError(field, init, initialized[field]);
     } else if (field.isFinal) {
-      field.parseNode(visitor.resolution.parsing);
+      field.parseNode(visitor.resolution.parsingContext);
       Expression initializer = field.initializer;
       if (initializer != null) {
         reportDuplicateInitializerError(
@@ -171,7 +171,6 @@
     ConstructorElement foundConstructor =
         findConstructor(constructor.library, lookupTarget, constructorName);
 
-    final bool isImplicitSuperCall = false;
     final String className = lookupTarget.name;
     CallStructure callStructure = argumentsResult.callStructure;
     ConstructorElement calledConstructor = verifyThatConstructorMatchesCall(
diff --git a/pkg/compiler/lib/src/resolution/enum_creator.dart b/pkg/compiler/lib/src/resolution/enum_creator.dart
index 93fb9ec..6b0acfa 100644
--- a/pkg/compiler/lib/src/resolution/enum_creator.dart
+++ b/pkg/compiler/lib/src/resolution/enum_creator.dart
@@ -171,6 +171,29 @@
   }
 }
 
+/// This class generates the model for an enum class.
+///
+/// For instance
+///
+///     enum A { b, c, }
+///
+/// is modelled as
+///
+///     class A {
+///       final int index;
+///
+///       const A(this.index);
+///
+///       String toString() {
+///         return const <int, A>{0: 'A.b', 1: 'A.c'}[index];
+///       }
+///
+///       static const A b = const A(0);
+///       static const A c = const A(1);
+///
+///       static const List<A> values = const <A>[b, c];
+///     }
+///
 // TODO(johnniwinther): Avoid creating synthesized ASTs for enums when SSA is
 // removed.
 class EnumCreator {
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index bcd4495..e349185 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -23,31 +23,28 @@
         JumpTargetX,
         LocalFunctionElementX,
         LocalParameterElementX,
-        LocalVariableElementX,
         MethodElementX,
         ParameterElementX,
         VariableElementX,
         VariableList;
 import '../tokens/token.dart' show isUserDefinableOperator;
 import '../tree/tree.dart';
-import '../util/util.dart' show Link;
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
-
+import '../util/util.dart' show Link;
 import 'access_semantics.dart';
 import 'class_members.dart' show MembersCreator;
-import 'operators.dart';
-import 'send_structure.dart';
-
 import 'constructors.dart'
     show ConstructorResolver, ConstructorResult, ConstructorResultKind;
 import 'label_scope.dart' show StatementScope;
+import 'operators.dart';
 import 'registry.dart' show ResolutionRegistry;
 import 'resolution.dart' show ResolverTask;
 import 'resolution_common.dart' show MappingVisitor;
 import 'resolution_result.dart';
 import 'scope.dart' show BlockScope, MethodScope, Scope;
+import 'send_structure.dart';
 import 'signatures.dart' show SignatureResolver;
 import 'variables.dart' show VariableDefinitionsVisitor;
 
@@ -391,7 +388,7 @@
   }
 
   FunctionElement resolveConstructorRedirection(FunctionElementX constructor) {
-    FunctionExpression node = constructor.parseNode(resolution.parsing);
+    FunctionExpression node = constructor.parseNode(resolution.parsingContext);
 
     // A synthetic constructor does not have a node.
     if (node == null) return null;
@@ -3343,7 +3340,6 @@
   /// `a++` or `a += b` where [semantics] describe `a`.
   ResolutionResult handleUpdate(
       SendSet node, Name name, AccessSemantics semantics) {
-    SendStructure sendStructure;
     String operatorText = node.assignmentOperator.source;
     Selector getterSelector = new Selector.getter(name);
     Selector setterSelector = new Selector.setter(name);
@@ -3568,7 +3564,6 @@
     ConstructorElement redirectionTarget = result.element;
     constructor.immediateRedirectionTarget = redirectionTarget;
 
-    Node constructorReference = node.constructorReference;
     if (result.isDeferred) {
       constructor.redirectionDeferredPrefix = result.prefix;
     }
@@ -3772,7 +3767,6 @@
 
     DartType type = result.type;
     ConstructorAccessKind kind;
-    NewStructure newStructure;
     bool isInvalid = false;
     switch (result.kind) {
       case ConstructorResultKind.GENERATIVE:
diff --git a/pkg/compiler/lib/src/resolution/operators.dart b/pkg/compiler/lib/src/resolution/operators.dart
index 06fd468..499192f 100644
--- a/pkg/compiler/lib/src/resolution/operators.dart
+++ b/pkg/compiler/lib/src/resolution/operators.dart
@@ -430,19 +430,32 @@
 
   static AssignmentOperator fromKind(AssignmentOperatorKind kind) {
     switch (kind) {
-      case AssignmentOperatorKind.ASSIGN: return ASSIGN;
-      case AssignmentOperatorKind.IF_NULL: return IF_NULL;
-      case AssignmentOperatorKind.ADD: return ADD;
-      case AssignmentOperatorKind.SUB: return SUB;
-      case AssignmentOperatorKind.MUL: return MUL;
-      case AssignmentOperatorKind.DIV: return DIV;
-      case AssignmentOperatorKind.IDIV: return IDIV;
-      case AssignmentOperatorKind.MOD: return MOD;
-      case AssignmentOperatorKind.SHL: return SHL;
-      case AssignmentOperatorKind.SHR: return SHR;
-      case AssignmentOperatorKind.AND: return AND;
-      case AssignmentOperatorKind.OR: return OR;
-      case AssignmentOperatorKind.XOR: return XOR;
+      case AssignmentOperatorKind.ASSIGN:
+        return ASSIGN;
+      case AssignmentOperatorKind.IF_NULL:
+        return IF_NULL;
+      case AssignmentOperatorKind.ADD:
+        return ADD;
+      case AssignmentOperatorKind.SUB:
+        return SUB;
+      case AssignmentOperatorKind.MUL:
+        return MUL;
+      case AssignmentOperatorKind.DIV:
+        return DIV;
+      case AssignmentOperatorKind.IDIV:
+        return IDIV;
+      case AssignmentOperatorKind.MOD:
+        return MOD;
+      case AssignmentOperatorKind.SHL:
+        return SHL;
+      case AssignmentOperatorKind.SHR:
+        return SHR;
+      case AssignmentOperatorKind.AND:
+        return AND;
+      case AssignmentOperatorKind.OR:
+        return OR;
+      case AssignmentOperatorKind.XOR:
+        return XOR;
     }
   }
 }
@@ -481,8 +494,10 @@
 
   static IncDecOperator fromKind(IncDecOperatorKind kind) {
     switch (kind) {
-      case IncDecOperatorKind.INC: return INC;
-      case IncDecOperatorKind.DEC: return DEC;
+      case IncDecOperatorKind.INC:
+        return INC;
+      case IncDecOperatorKind.DEC:
+        return DEC;
     }
   }
 }
diff --git a/pkg/compiler/lib/src/resolution/registry.dart b/pkg/compiler/lib/src/resolution/registry.dart
index ed6db6c..0301e8c 100644
--- a/pkg/compiler/lib/src/resolution/registry.dart
+++ b/pkg/compiler/lib/src/resolution/registry.dart
@@ -20,7 +20,7 @@
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
-import '../universe/world_impact.dart' show WorldImpactBuilder;
+import '../universe/world_impact.dart' show WorldImpact, WorldImpactBuilder;
 import '../util/enumset.dart' show EnumSet;
 import '../world.dart' show World;
 
@@ -104,7 +104,39 @@
         : const <ConstantExpression>[];
   }
 
-  String toString() => '_ResolutionWorldImpact($name)';
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.write('_ResolutionWorldImpact($name)');
+    WorldImpact.printOn(sb, this);
+    if (_features != null) {
+      sb.write('\n features:');
+      for (Feature feature in _features.iterable(Feature.values)) {
+        sb.write('\n  $feature');
+      }
+    }
+    if (_mapLiterals != null) {
+      sb.write('\n map-literals:');
+      for (MapLiteralUse use in _mapLiterals) {
+        sb.write('\n  $use');
+      }
+    }
+    if (_listLiterals != null) {
+      sb.write('\n list-literals:');
+      for (ListLiteralUse use in _listLiterals) {
+        sb.write('\n  $use');
+      }
+    }
+    if (_constantLiterals != null) {
+      sb.write('\n const-literals:');
+      for (ConstantExpression constant in _constantLiterals) {
+        sb.write('\n  ${constant.getText()}');
+      }
+    }
+    if (_constSymbolNames != null) {
+      sb.write('\n const-symbol-names: $_constSymbolNames');
+    }
+    return sb.toString();
+  }
 }
 
 /// [ResolutionRegistry] collects all resolution information. It stores node
@@ -324,8 +356,11 @@
 
   void registerForeignCall(Node node, Element element,
       CallStructure callStructure, ResolverVisitor visitor) {
-    backend.registerForeignCall(node, element, callStructure,
+    var nativeData = backend.resolveForeignCall(node, element, callStructure,
         new ForeignResolutionResolver(visitor, this));
+    if (nativeData != null) {
+      mapping.registerNativeData(node, nativeData);
+    }
   }
 
   void registerDynamicUse(DynamicUse dynamicUse) {
diff --git a/pkg/compiler/lib/src/resolution/resolution.dart b/pkg/compiler/lib/src/resolution/resolution.dart
index 7caced4..58d038b 100644
--- a/pkg/compiler/lib/src/resolution/resolution.dart
+++ b/pkg/compiler/lib/src/resolution/resolution.dart
@@ -9,10 +9,10 @@
 import '../common.dart';
 import '../common/names.dart' show Identifiers;
 import '../common/resolution.dart'
-    show Feature, Parsing, Resolution, ResolutionImpact;
-import '../common/tasks.dart' show CompilerTask, DeferredAction;
-import '../compiler.dart' show Compiler;
+    show Feature, ParsingContext, Resolution, ResolutionImpact;
+import '../common/tasks.dart' show CompilerTask;
 import '../compile_time_constants.dart' show ConstantCompiler;
+import '../compiler.dart' show Compiler;
 import '../constants/expressions.dart'
     show
         ConstantExpression,
@@ -47,8 +47,7 @@
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/use.dart' show StaticUse, TypeUse;
 import '../universe/world_impact.dart' show WorldImpact;
-import '../util/util.dart' show Link, LinkBuilder, Setlet;
-
+import '../util/util.dart' show Link, Setlet;
 import 'class_hierarchy.dart';
 import 'class_members.dart' show MembersCreator;
 import 'constructors.dart';
@@ -67,7 +66,7 @@
 
   Resolution get resolution => compiler.resolution;
 
-  Parsing get parsing => compiler.parsing;
+  ParsingContext get parsingContext => compiler.parsingContext;
 
   CoreClasses get coreClasses => compiler.coreClasses;
 
@@ -312,7 +311,7 @@
           return const ResolutionImpact();
         }
       } else {
-        element.parseNode(resolution.parsing);
+        element.parseNode(resolution.parsingContext);
         element.computeType(resolution);
         FunctionElementX implementation = element;
         if (element.isExternal) {
@@ -337,7 +336,7 @@
   }
 
   WorldImpact resolveField(FieldElementX element) {
-    VariableDefinitions tree = element.parseNode(parsing);
+    VariableDefinitions tree = element.parseNode(parsingContext);
     if (element.modifiers.isStatic && element.isTopLevel) {
       reporter.reportErrorMessage(element.modifiers.getStatic(),
           MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC);
@@ -509,7 +508,7 @@
       reporter.withCurrentElement(cls, () {
         // TODO(ahe): Cache the node in cls.
         cls
-            .parseNode(parsing)
+            .parseNode(parsingContext)
             .accept(new ClassSupertypeResolver(compiler, cls));
         if (cls.supertypeLoadState != STATE_DONE) {
           cls.supertypeLoadState = STATE_DONE;
@@ -598,7 +597,7 @@
           () => measure(() {
                 assert(element.resolutionState == STATE_NOT_STARTED);
                 element.resolutionState = STATE_STARTED;
-                Node tree = element.parseNode(parsing);
+                Node tree = element.parseNode(parsingContext);
                 loadSupertypes(element, tree);
 
                 ClassResolverVisitor visitor =
@@ -726,18 +725,19 @@
         // TODO(johnniwinther): Obtain the [TreeElements] for [member]
         // differently.
         if (compiler.enqueuer.resolution.hasBeenProcessed(member)) {
-          checkMixinSuperUses(
-              member.resolvedAst.elements, mixinApplication, mixin);
+          if (member.resolvedAst.kind == ResolvedAstKind.PARSED) {
+            checkMixinSuperUses(
+                member.resolvedAst.elements, mixinApplication, mixin);
+          }
         }
       }
     });
   }
 
-  void checkMixinSuperUses(TreeElements resolutionTree,
+  void checkMixinSuperUses(TreeElements elements,
       MixinApplicationElement mixinApplication, ClassElement mixin) {
     // TODO(johnniwinther): Avoid the use of [TreeElements] here.
-    if (resolutionTree == null) return;
-    Iterable<SourceSpan> superUses = resolutionTree.superUses;
+    Iterable<SourceSpan> superUses = elements.superUses;
     if (superUses.isEmpty) return;
     DiagnosticMessage error = reporter.createMessage(mixinApplication,
         MessageKind.ILLEGAL_MIXIN_WITH_SUPER, {'className': mixin.name});
@@ -965,13 +965,13 @@
   FunctionSignature resolveSignature(FunctionElementX element) {
     MessageKind defaultValuesError = null;
     if (element.isFactoryConstructor) {
-      FunctionExpression body = element.parseNode(parsing);
+      FunctionExpression body = element.parseNode(parsingContext);
       if (body.isRedirectingFactory) {
         defaultValuesError = MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT;
       }
     }
     return reporter.withCurrentElement(element, () {
-      FunctionExpression node = element.parseNode(parsing);
+      FunctionExpression node = element.parseNode(parsingContext);
       return measure(() => SignatureResolver.analyze(
           compiler,
           node.parameters,
@@ -993,7 +993,7 @@
         return measure(() {
           assert(element.resolutionState == STATE_NOT_STARTED);
           element.resolutionState = STATE_STARTED;
-          Typedef node = element.parseNode(parsing);
+          Typedef node = element.parseNode(parsingContext);
           TypedefResolverVisitor visitor =
               new TypedefResolverVisitor(compiler, element, registry);
           visitor.visit(node);
@@ -1011,7 +1011,7 @@
               assert(annotation.resolutionState == STATE_NOT_STARTED);
               annotation.resolutionState = STATE_STARTED;
 
-              Node node = annotation.parseNode(parsing);
+              Node node = annotation.parseNode(parsingContext);
               Element annotatedElement = annotation.annotatedElement;
               AnalyzableElement context = annotatedElement.analyzableElement;
               ClassElement classElement = annotatedElement.enclosingClass;
diff --git a/pkg/compiler/lib/src/resolution/signatures.dart b/pkg/compiler/lib/src/resolution/signatures.dart
index 7b166d9..36ea970 100644
--- a/pkg/compiler/lib/src/resolution/signatures.dart
+++ b/pkg/compiler/lib/src/resolution/signatures.dart
@@ -13,14 +13,12 @@
         ErroneousFieldElementX,
         ErroneousInitializingFormalElementX,
         FormalElementX,
-        FunctionElementX,
         FunctionSignatureX,
         InitializingFormalElementX,
         LocalParameterElementX;
 import '../tree/tree.dart';
 import '../universe/use.dart' show TypeUse;
 import '../util/util.dart' show Link, LinkBuilder;
-
 import 'members.dart' show ResolverVisitor;
 import 'registry.dart' show ResolutionRegistry;
 import 'resolution_common.dart' show MappingVisitor;
diff --git a/pkg/compiler/lib/src/resolution/tree_elements.dart b/pkg/compiler/lib/src/resolution/tree_elements.dart
index 1d1ddce..9c60745 100644
--- a/pkg/compiler/lib/src/resolution/tree_elements.dart
+++ b/pkg/compiler/lib/src/resolution/tree_elements.dart
@@ -100,6 +100,9 @@
 
   /// `true` if the [analyzedElement]'s source code contains a [TryStatement].
   bool get containsTryStatement;
+
+  /// Returns native data stored with [node].
+  getNativeData(Node node);
 }
 
 class TreeElementMapping extends TreeElements {
@@ -133,6 +136,9 @@
   /// Map from labeled goto statements to the labels they target.
   Map<GotoStatement, LabelDefinition> _targetLabels;
 
+  /// Map from nodes to native data.
+  Map<Node, dynamic> _nativeData;
+
   final int hashCode = ++_hashCodeCounter;
   static int _hashCodeCounter = 0;
 
@@ -156,8 +162,10 @@
     setTreeElement(node, element);
   }
 
+  @override
   operator [](Node node) => getTreeElement(node);
 
+  @override
   SendStructure getSendStructure(Send node) {
     if (_sendStructureMap == null) return null;
     return _sendStructureMap[node];
@@ -170,6 +178,7 @@
     _sendStructureMap[node] = sendStructure;
   }
 
+  @override
   NewStructure getNewStructure(NewExpression node) {
     if (_newStructureMap == null) return null;
     return _newStructureMap[node];
@@ -189,8 +198,10 @@
     _types[node] = type;
   }
 
+  @override
   DartType getType(Node node) => _types != null ? _types[node] : null;
 
+  @override
   Iterable<SourceSpan> get superUses {
     return _superUses != null ? _superUses : const <SourceSpan>[];
   }
@@ -217,6 +228,7 @@
     _setSelector(node, selector);
   }
 
+  @override
   Selector getSelector(Node node) => _getSelector(node);
 
   int getSelectorCount() => _selectors == null ? 0 : _selectors.length;
@@ -225,6 +237,7 @@
     _setSelector(node.selector, selector);
   }
 
+  @override
   Selector getGetterSelectorInComplexSendSet(SendSet node) {
     return _getSelector(node.selector);
   }
@@ -233,14 +246,17 @@
     _setSelector(node.assignmentOperator, selector);
   }
 
+  @override
   Selector getOperatorSelectorInComplexSendSet(SendSet node) {
     return _getSelector(node.assignmentOperator);
   }
 
+  @override
   Element getForInVariable(ForIn node) {
     return this[node];
   }
 
+  @override
   void setConstant(Node node, ConstantExpression constant) {
     if (_constants == null) {
       _constants = new Maplet<Node, ConstantExpression>();
@@ -248,18 +264,22 @@
     _constants[node] = constant;
   }
 
+  @override
   ConstantExpression getConstant(Node node) {
     return _constants != null ? _constants[node] : null;
   }
 
+  @override
   bool isTypeLiteral(Send node) {
     return getType(node) != null;
   }
 
+  @override
   DartType getTypeLiteralType(Send node) {
     return getType(node);
   }
 
+  @override
   List<Node> getPotentialMutations(VariableElement element) {
     if (_potentiallyMutated == null) return const <Node>[];
     List<Node> mutations = _potentiallyMutated[element];
@@ -274,6 +294,7 @@
     _potentiallyMutated.putIfAbsent(element, () => <Node>[]).add(mutationNode);
   }
 
+  @override
   List<Node> getPotentialMutationsIn(Node node, VariableElement element) {
     if (_potentiallyMutatedIn == null) return const <Node>[];
     Map<VariableElement, List<Node>> mutationsIn = _potentiallyMutatedIn[node];
@@ -295,6 +316,7 @@
     mutationMap.putIfAbsent(element, () => <Node>[]).add(mutationNode);
   }
 
+  @override
   List<Node> getPotentialMutationsInClosure(VariableElement element) {
     if (_potentiallyMutatedInClosure == null) return const <Node>[];
     List<Node> mutations = _potentiallyMutatedInClosure[element];
@@ -312,6 +334,7 @@
         .add(mutationNode);
   }
 
+  @override
   List<Node> getAccessesByClosureIn(Node node, VariableElement element) {
     if (_accessedByClosureIn == null) return const <Node>[];
     Map<VariableElement, List<Node>> accessesIn = _accessedByClosureIn[node];
@@ -334,16 +357,19 @@
 
   String toString() => 'TreeElementMapping($analyzedElement)';
 
+  @override
   void forEachConstantNode(f(Node n, ConstantExpression c)) {
     if (_constants != null) {
       _constants.forEach(f);
     }
   }
 
+  @override
   FunctionElement getFunctionDefinition(FunctionExpression node) {
     return this[node];
   }
 
+  @override
   ConstructorElement getRedirectingTargetConstructor(
       RedirectingFactoryBody node) {
     return this[node];
@@ -365,6 +391,7 @@
     }
   }
 
+  @override
   JumpTarget getTargetDefinition(Node node) {
     return _definedTargets != null ? _definedTargets[node] : null;
   }
@@ -376,6 +403,7 @@
     _usedTargets[node] = target;
   }
 
+  @override
   JumpTarget getTargetOf(GotoStatement node) {
     return _usedTargets != null ? _usedTargets[node] : null;
   }
@@ -396,6 +424,7 @@
     }
   }
 
+  @override
   LabelDefinition getLabelDefinition(Label label) {
     return _definedLabels != null ? _definedLabels[label] : null;
   }
@@ -408,6 +437,7 @@
     _targetLabels[node] = label;
   }
 
+  @override
   LabelDefinition getTargetLabel(GotoStatement node) {
     assert(node.target != null);
     return _targetLabels != null ? _targetLabels[node] : null;
@@ -424,24 +454,30 @@
     _typeMasks[node] = mask;
   }
 
+  @override
   void setTypeMask(Node node, TypeMask mask) {
     _setTypeMask(node, mask);
   }
 
+  @override
   TypeMask getTypeMask(Node node) => _getTypeMask(node);
 
+  @override
   void setGetterTypeMaskInComplexSendSet(SendSet node, TypeMask mask) {
     _setTypeMask(node.selector, mask);
   }
 
+  @override
   TypeMask getGetterTypeMaskInComplexSendSet(SendSet node) {
     return _getTypeMask(node.selector);
   }
 
+  @override
   void setOperatorTypeMaskInComplexSendSet(SendSet node, TypeMask mask) {
     _setTypeMask(node.assignmentOperator, mask);
   }
 
+  @override
   TypeMask getOperatorTypeMaskInComplexSendSet(SendSet node) {
     return _getTypeMask(node.assignmentOperator);
   }
@@ -450,27 +486,45 @@
   // we're using three selectors, we need to use children of the node,
   // and we arbitrarily choose which ones.
 
+  @override
   void setIteratorTypeMask(ForIn node, TypeMask mask) {
     _setTypeMask(node, mask);
   }
 
+  @override
   TypeMask getIteratorTypeMask(ForIn node) {
     return _getTypeMask(node);
   }
 
+  @override
   void setMoveNextTypeMask(ForIn node, TypeMask mask) {
     _setTypeMask(node.forToken, mask);
   }
 
+  @override
   TypeMask getMoveNextTypeMask(ForIn node) {
     return _getTypeMask(node.forToken);
   }
 
+  @override
   void setCurrentTypeMask(ForIn node, TypeMask mask) {
     _setTypeMask(node.inToken, mask);
   }
 
+  @override
   TypeMask getCurrentTypeMask(ForIn node) {
     return _getTypeMask(node.inToken);
   }
+
+  void registerNativeData(Node node, dynamic nativeData) {
+    if (_nativeData == null) {
+      _nativeData = <Node, dynamic>{};
+    }
+    _nativeData[node] = nativeData;
+  }
+
+  @override
+  dynamic getNativeData(Node node) {
+    return _nativeData != null ? _nativeData[node] : null;
+  }
 }
diff --git a/pkg/compiler/lib/src/resolved_uri_translator.dart b/pkg/compiler/lib/src/resolved_uri_translator.dart
new file mode 100644
index 0000000..41a96b3
--- /dev/null
+++ b/pkg/compiler/lib/src/resolved_uri_translator.dart
@@ -0,0 +1,161 @@
+// 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 'common.dart';
+import 'elements/elements.dart' show LibraryElement;
+import 'util/emptyset.dart';
+
+/// API used by the library loader to translate internal SDK URIs into file
+/// system readable URIs.
+abstract class ResolvedUriTranslator {
+  factory ResolvedUriTranslator(
+          Map<String, Uri> sdkLibraries, DiagnosticReporter reporter) =
+      _ResolvedUriTranslator;
+
+  /// The set of platform libraries reported as unsupported.
+  ///
+  /// For instance when importing 'dart:io' without '--categories=Server'.
+  Set<Uri> get disallowedLibraryUris;
+
+  /// Whether or not a mockable library has been translated.
+  bool get mockableLibraryUsed;
+
+  /// A mapping from dart: library names to their location.
+  Map<String, Uri> get sdkLibraries;
+
+  /// Translates the resolved [uri] into a readable URI.
+  ///
+  /// The [importingLibrary] holds the library importing [uri] or `null` if
+  /// [uri] is loaded as the main library. The [importingLibrary] is used to
+  /// grant access to internal libraries from platform libraries and patch
+  /// libraries.
+  ///
+  /// If the [uri] is not accessible from [importingLibrary], this method is
+  /// responsible for reporting errors.
+  ///
+  /// See [LibraryLoader] for terminology on URIs.
+  Uri translate(LibraryElement importingLibrary, Uri uri,
+      [Spannable spannable]);
+}
+
+/// A translator that forwards all methods to an internal
+/// [ResolvedUriTranslator].
+///
+/// The translator to forward to may be set after the instance is constructed.
+/// This is useful for the compiler because some tasks that are instantiated at
+/// compiler construction time need a [ResolvedUriTranslator], but the data
+/// required to instantiate it cannot be obtained at construction time. So a
+/// [ForwardingResolvedUriTranslator] may be passed instead, and the translator
+/// to forward to can be set once the required data has been retrieved.
+class ForwardingResolvedUriTranslator implements ResolvedUriTranslator {
+  ResolvedUriTranslator resolvedUriTranslator;
+
+  /// Returns `true` if [resolvedUriTranslator] is not `null`.
+  bool get isSet => resolvedUriTranslator != null;
+
+  /// The opposite of [isSet].
+  bool get isNotSet => resolvedUriTranslator == null;
+
+  @override
+  Uri translate(LibraryElement importingLibrary, Uri resolvedUri,
+          [Spannable spannable]) =>
+      resolvedUriTranslator.translate(importingLibrary, resolvedUri, spannable);
+
+  @override
+  Set<Uri> get disallowedLibraryUris =>
+      resolvedUriTranslator?.disallowedLibraryUris ??
+      const ImmutableEmptySet<Uri>();
+
+  @override
+  bool get mockableLibraryUsed => resolvedUriTranslator.mockableLibraryUsed;
+
+  @override
+  Map<String, Uri> get sdkLibraries => resolvedUriTranslator.sdkLibraries;
+}
+
+class _ResolvedUriTranslator implements ResolvedUriTranslator {
+  final Map<String, Uri> _sdkLibraries;
+  final DiagnosticReporter _reporter;
+
+  Set<Uri> disallowedLibraryUris = new Set<Uri>();
+  bool mockableLibraryUsed = false;
+
+  _ResolvedUriTranslator(this._sdkLibraries, this._reporter);
+
+  Map<String, Uri> get sdkLibraries => _sdkLibraries;
+
+  @override
+  Uri translate(LibraryElement importingLibrary, Uri uri,
+      [Spannable spannable]) {
+    if (uri.scheme == 'dart') {
+      return translateDartUri(importingLibrary, uri, spannable);
+    }
+    return uri;
+  }
+
+  /// Translates "resolvedUri" with scheme "dart" to a [uri] resolved relative
+  /// to `options.platformConfigUri` according to the information in the file at
+  /// `options.platformConfigUri`.
+  ///
+  /// Returns `null` and emits an error if the library could not be found or
+  /// imported into [importingLibrary].
+  ///
+  /// Internal libraries (whose name starts with '_') can be only resolved if
+  /// [importingLibrary] is a platform or patch library.
+  Uri translateDartUri(
+      LibraryElement importingLibrary, Uri resolvedUri, Spannable spannable) {
+    Uri location = lookupLibraryUri(resolvedUri.path);
+
+    if (location == null) {
+      _reporter.reportErrorMessage(spannable, MessageKind.LIBRARY_NOT_FOUND,
+          {'resolvedUri': resolvedUri});
+      return null;
+    }
+
+    if (resolvedUri.path.startsWith('_')) {
+      bool allowInternalLibraryAccess = importingLibrary != null &&
+          (importingLibrary.isPlatformLibrary ||
+              importingLibrary.isPatch ||
+              importingLibrary.canonicalUri.path
+                  .contains('sdk/tests/compiler/dart2js_native'));
+
+      if (!allowInternalLibraryAccess) {
+        if (importingLibrary != null) {
+          _reporter.reportErrorMessage(
+              spannable, MessageKind.INTERNAL_LIBRARY_FROM, {
+            'resolvedUri': resolvedUri,
+            'importingUri': importingLibrary.canonicalUri
+          });
+        } else {
+          _reporter.reportErrorMessage(spannable, MessageKind.INTERNAL_LIBRARY,
+              {'resolvedUri': resolvedUri});
+          registerDisallowedLibraryUse(resolvedUri);
+        }
+        return null;
+      }
+    }
+
+    if (location.scheme == "unsupported") {
+      _reporter.reportErrorMessage(spannable, MessageKind.LIBRARY_NOT_SUPPORTED,
+          {'resolvedUri': resolvedUri});
+      registerDisallowedLibraryUse(resolvedUri);
+      return null;
+    }
+
+    if (resolvedUri.path == 'html' || resolvedUri.path == 'io') {
+      // TODO(ahe): Get rid of mockableLibraryUsed when test.dart
+      // supports this use case better.
+      mockableLibraryUsed = true;
+    }
+    return location;
+  }
+
+  void registerDisallowedLibraryUse(Uri uri) {
+    disallowedLibraryUris.add(uri);
+  }
+
+  Uri lookupLibraryUri(String libraryName) {
+    return _sdkLibraries[libraryName];
+  }
+}
diff --git a/pkg/compiler/lib/src/scanner/array_based_scanner.dart b/pkg/compiler/lib/src/scanner/array_based_scanner.dart
index 27540a4..2496daa 100644
--- a/pkg/compiler/lib/src/scanner/array_based_scanner.dart
+++ b/pkg/compiler/lib/src/scanner/array_based_scanner.dart
@@ -63,8 +63,8 @@
    */
   void appendKeywordToken(Keyword keyword) {
     String syntax = keyword.syntax;
-    // Type parameters and arguments cannot contain 'this' or 'super'.
-    if (identical(syntax, 'this') || identical(syntax, 'super')) {
+    // Type parameters and arguments cannot contain 'this'.
+    if (identical(syntax, 'this')) {
       discardOpenLt();
     }
     tail.next = new KeywordToken(keyword, tokenStart);
diff --git a/pkg/compiler/lib/src/serialization/constant_serialization.dart b/pkg/compiler/lib/src/serialization/constant_serialization.dart
index fae8818..afaa3b4 100644
--- a/pkg/compiler/lib/src/serialization/constant_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/constant_serialization.dart
@@ -232,11 +232,13 @@
             decoder.getConstant(Key.NAME),
             decoder.getConstant(Key.DEFAULT, isOptional: true));
       case ConstantExpressionKind.LIST:
-        return new ListConstantExpression(
-            decoder.getType(Key.TYPE), decoder.getConstants(Key.VALUES));
+        return new ListConstantExpression(decoder.getType(Key.TYPE),
+            decoder.getConstants(Key.VALUES, isOptional: true));
       case ConstantExpressionKind.MAP:
-        return new MapConstantExpression(decoder.getType(Key.TYPE),
-            decoder.getConstants(Key.KEYS), decoder.getConstants(Key.VALUES));
+        return new MapConstantExpression(
+            decoder.getType(Key.TYPE),
+            decoder.getConstants(Key.KEYS, isOptional: true),
+            decoder.getConstants(Key.VALUES, isOptional: true));
       case ConstantExpressionKind.NULL:
         return new NullConstantExpression();
       case ConstantExpressionKind.STRING:
@@ -249,7 +251,7 @@
         return new StringLengthConstantExpression(
             decoder.getConstant(Key.EXPRESSION));
       case ConstantExpressionKind.SYMBOL:
-        break;
+        return new SymbolConstantExpression(decoder.getString(Key.NAME));
       case ConstantExpressionKind.TYPE:
         return new TypeConstantExpression(decoder.getType(Key.TYPE));
       case ConstantExpressionKind.UNARY:
diff --git a/pkg/compiler/lib/src/serialization/element_serialization.dart b/pkg/compiler/lib/src/serialization/element_serialization.dart
index 78228ca..e3d1526 100644
--- a/pkg/compiler/lib/src/serialization/element_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/element_serialization.dart
@@ -23,6 +23,7 @@
   NAMED_MIXIN_APPLICATION,
   GENERATIVE_CONSTRUCTOR,
   FACTORY_CONSTRUCTOR,
+  FORWARDING_CONSTRUCTOR,
   TOPLEVEL_FIELD,
   STATIC_FIELD,
   INSTANCE_FIELD,
@@ -105,8 +106,8 @@
     if (element.sourcePosition != null) {
       SourceSpan position = element.sourcePosition;
       encoder.setInt(Key.OFFSET, position.begin);
+      // TODO(johnniwinther): What is the base URI in the case?
       if (position.uri != element.compilationUnit.script.resourceUri) {
-        // TODO(johnniwinther): What is the base URI in the case?
         encoder.setUri(Key.URI, element.library.canonicalUri, position.uri);
       }
       int length = position.end - position.begin;
@@ -116,6 +117,21 @@
     }
   }
 
+  /// Serialize the parent relation for [element] into [encoder], i.e library,
+  /// enclosing class, and compilation unit references.
+  static void serializeParentRelation(Element element, ObjectEncoder encoder) {
+    if (element.enclosingClass != null) {
+      encoder.setElement(Key.CLASS, element.enclosingClass);
+      if (element.enclosingClass.declaration.compilationUnit !=
+          element.compilationUnit) {
+        encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
+      }
+    } else {
+      encoder.setElement(Key.LIBRARY, element.library);
+      encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
+    }
+  }
+
   /// Serialize the parameters of [element] into [encoder].
   static void serializeParameters(
       FunctionElement element, ObjectEncoder encoder) {
@@ -324,7 +340,11 @@
 
   SerializedElementKind getSerializedKind(Element element) {
     if (element.isGenerativeConstructor) {
-      return SerializedElementKind.GENERATIVE_CONSTRUCTOR;
+      if (element.enclosingClass.isNamedMixinApplication) {
+        return SerializedElementKind.FORWARDING_CONSTRUCTOR;
+      } else {
+        return SerializedElementKind.GENERATIVE_CONSTRUCTOR;
+      }
     } else if (element.isFactoryConstructor) {
       return SerializedElementKind.FACTORY_CONSTRUCTOR;
     }
@@ -333,19 +353,23 @@
 
   void serialize(ConstructorElement element, ObjectEncoder encoder,
       SerializedElementKind kind) {
-    encoder.setElement(Key.CLASS, element.enclosingClass);
-    encoder.setType(Key.TYPE, element.type);
-    encoder.setString(Key.NAME, element.name);
-    SerializerUtil.serializePosition(element, encoder);
-    SerializerUtil.serializeParameters(element, encoder);
-    encoder.setBool(Key.IS_CONST, element.isConst);
-    encoder.setBool(Key.IS_EXTERNAL, element.isExternal);
-    if (element.isExternal) return;
-    if (element.isConst && !element.isFromEnvironmentConstructor) {
-      ConstantConstructor constantConstructor = element.constantConstructor;
-      ObjectEncoder constantEncoder = encoder.createObject(Key.CONSTRUCTOR);
-      const ConstantConstructorSerializer()
-          .visit(constantConstructor, constantEncoder);
+    SerializerUtil.serializeParentRelation(element, encoder);
+    if (kind == SerializedElementKind.FORWARDING_CONSTRUCTOR) {
+      encoder.setElement(Key.ELEMENT, element.definingConstructor);
+    } else {
+      encoder.setType(Key.TYPE, element.type);
+      encoder.setString(Key.NAME, element.name);
+      SerializerUtil.serializePosition(element, encoder);
+      SerializerUtil.serializeParameters(element, encoder);
+      encoder.setBool(Key.IS_CONST, element.isConst);
+      encoder.setBool(Key.IS_EXTERNAL, element.isExternal);
+      if (element.isExternal) return;
+      if (element.isConst && !element.isFromEnvironmentConstructor) {
+        ConstantConstructor constantConstructor = element.constantConstructor;
+        ObjectEncoder constantEncoder = encoder.createObject(Key.CONSTRUCTOR);
+        const ConstantConstructorSerializer()
+            .visit(constantConstructor, constantEncoder);
+      }
     }
   }
 }
@@ -378,12 +402,7 @@
       ConstantExpression constant = element.constant;
       encoder.setConstant(Key.CONSTANT, constant);
     }
-    if (kind != SerializedElementKind.TOPLEVEL_FIELD) {
-      encoder.setElement(Key.CLASS, element.enclosingClass);
-    } else {
-      encoder.setElement(Key.LIBRARY, element.library);
-      encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
-    }
+    SerializerUtil.serializeParentRelation(element, encoder);
     if (element is EnumConstantElement) {
       EnumConstantElement enumConstant = element;
       encoder.setInt(Key.INDEX, enumConstant.index);
@@ -430,13 +449,9 @@
     encoder.setType(Key.TYPE, element.type);
     if (element.isFunction) {
       encoder.setBool(Key.IS_OPERATOR, element.isOperator);
+      encoder.setEnum(Key.ASYNC_MARKER, element.asyncMarker);
     }
-    if (element.enclosingClass != null) {
-      encoder.setElement(Key.CLASS, element.enclosingClass);
-    } else {
-      encoder.setElement(Key.LIBRARY, element.library);
-      encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
-    }
+    SerializerUtil.serializeParentRelation(element, encoder);
     encoder.setBool(Key.IS_EXTERNAL, element.isExternal);
     if (element.isLocal) {
       LocalFunctionElement localFunction = element;
@@ -508,6 +523,7 @@
     encoder.setType(Key.TYPE, element.type);
     encoder.setBool(Key.IS_OPTIONAL, element.isOptional);
     encoder.setBool(Key.IS_NAMED, element.isNamed);
+    encoder.setBool(Key.IS_FINAL, element.isFinal);
     if (element.isOptional) {
       encoder.setConstant(Key.CONSTANT, element.constant);
     }
@@ -644,6 +660,9 @@
         return new GenerativeConstructorElementZ(decoder);
       case SerializedElementKind.FACTORY_CONSTRUCTOR:
         return new FactoryConstructorElementZ(decoder);
+      case SerializedElementKind.FORWARDING_CONSTRUCTOR:
+        return new ForwardingConstructorElementZ(
+            decoder.getElement(Key.CLASS), decoder.getElement(Key.ELEMENT));
       case SerializedElementKind.TOPLEVEL_FUNCTION:
         return new TopLevelFunctionElementZ(decoder);
       case SerializedElementKind.STATIC_FUNCTION:
@@ -669,7 +688,7 @@
       case SerializedElementKind.TYPEVARIABLE:
         return new TypeVariableElementZ(decoder);
       case SerializedElementKind.PARAMETER:
-        return new ParameterElementZ(decoder);
+        return new LocalParameterElementZ(decoder);
       case SerializedElementKind.INITIALIZING_FORMAL:
         return new InitializingFormalElementZ(decoder);
       case SerializedElementKind.IMPORT:
diff --git a/pkg/compiler/lib/src/serialization/equivalence.dart b/pkg/compiler/lib/src/serialization/equivalence.dart
index d68ce3e..acf3e71 100644
--- a/pkg/compiler/lib/src/serialization/equivalence.dart
+++ b/pkg/compiler/lib/src/serialization/equivalence.dart
@@ -11,6 +11,9 @@
 import '../dart_types.dart';
 import '../elements/elements.dart';
 import '../elements/visitor.dart';
+import '../js_backend/backend_serialization.dart'
+    show JavaScriptBackendSerializer;
+import '../native/native.dart' show NativeBehavior;
 import '../resolution/access_semantics.dart';
 import '../resolution/send_structure.dart';
 import '../resolution/tree_elements.dart';
@@ -359,6 +362,8 @@
       CompilationUnitElement element1, CompilationUnitElement element2) {
     return strategy.test(
             element1, element2, 'name', element1.name, element2.name) &&
+        strategy.test(element1, element2, 'script.resourceUri',
+            element1.script.resourceUri, element2.script.resourceUri) &&
         visit(element1.library, element2.library);
   }
 
@@ -751,10 +756,20 @@
 bool testResolvedAstEquivalence(
     ResolvedAst resolvedAst1, ResolvedAst resolvedAst2,
     [TestStrategy strategy = const TestStrategy()]) {
+  if (!strategy.test(resolvedAst1, resolvedAst1, 'kind', resolvedAst1.kind,
+      resolvedAst2.kind)) {
+    return false;
+  }
+  if (resolvedAst1.kind != ResolvedAstKind.PARSED) {
+    // Nothing more to check.
+    return true;
+  }
   return strategy.testElements(resolvedAst1, resolvedAst2, 'element',
           resolvedAst1.element, resolvedAst2.element) &&
       new NodeEquivalenceVisitor(strategy).testNodes(resolvedAst1, resolvedAst2,
           'node', resolvedAst1.node, resolvedAst2.node) &&
+      new NodeEquivalenceVisitor(strategy).testNodes(resolvedAst1, resolvedAst2,
+          'body', resolvedAst1.body, resolvedAst2.body) &&
       testTreeElementsEquivalence(resolvedAst1, resolvedAst2, strategy);
 }
 
@@ -790,6 +805,83 @@
       this.indices1, this.indices2, this.elements1, this.elements2,
       [this.strategy = const TestStrategy()]);
 
+  bool testJumpTargets(
+      Node node1, Node node2, String property, JumpTarget a, JumpTarget b) {
+    if (identical(a, b)) return true;
+    if (a == null || b == null) return false;
+    return strategy.testElements(a, b, 'executableContext', a.executableContext,
+            b.executableContext) &&
+        strategy.test(a, b, 'nestingLevel', a.nestingLevel, b.nestingLevel) &&
+        strategy.test(a, b, 'statement', indices1.nodeIndices[a.statement],
+            indices2.nodeIndices[b.statement]) &&
+        strategy.test(
+            a, b, 'isBreakTarget', a.isBreakTarget, b.isBreakTarget) &&
+        strategy.test(
+            a, b, 'isContinueTarget', a.isContinueTarget, b.isContinueTarget) &&
+        strategy.testLists(a, b, 'labels', a.labels.toList(), b.labels.toList(),
+            (a, b) {
+          return indices1.nodeIndices[a.label] == indices2.nodeIndices[b.label];
+        });
+  }
+
+  bool testLabelDefinitions(Node node1, Node node2, String property,
+      LabelDefinition a, LabelDefinition b) {
+    if (identical(a, b)) return true;
+    if (a == null || b == null) return false;
+    return strategy.test(a, b, 'label', indices1.nodeIndices[a.label],
+            indices2.nodeIndices[b.label]) &&
+        strategy.test(a, b, 'labelName', a.labelName, b.labelName) &&
+        strategy.test(a, b, 'target', indices1.nodeIndices[a.target.statement],
+            indices2.nodeIndices[b.target.statement]) &&
+        strategy.test(
+            a, b, 'isBreakTarget', a.isBreakTarget, b.isBreakTarget) &&
+        strategy.test(
+            a, b, 'isContinueTarget', a.isContinueTarget, b.isContinueTarget);
+  }
+
+  bool testNativeData(Node node1, Node node2, String property, a, b) {
+    if (identical(a, b)) return true;
+    if (a == null || b == null) return false;
+    if (a is NativeBehavior && b is NativeBehavior) {
+      return strategy.test(a, b, 'codeTemplateText', a.codeTemplateText,
+              b.codeTemplateText) &&
+          strategy.test(a, b, 'isAllocation', a.isAllocation, b.isAllocation) &&
+          strategy.test(a, b, 'sideEffects', a.sideEffects, b.sideEffects) &&
+          strategy.test(
+              a, b, 'throwBehavior', a.throwBehavior, b.throwBehavior) &&
+          strategy.testTypeLists(
+              a,
+              b,
+              'dartTypesReturned',
+              JavaScriptBackendSerializer.filterDartTypes(a.typesReturned),
+              JavaScriptBackendSerializer.filterDartTypes(b.typesReturned)) &&
+          strategy.testLists(
+              a,
+              b,
+              'specialTypesReturned',
+              JavaScriptBackendSerializer.filterSpecialTypes(a.typesReturned),
+              JavaScriptBackendSerializer
+                  .filterSpecialTypes(b.typesReturned)) &&
+          strategy.testTypeLists(
+              a,
+              b,
+              'dartTypesInstantiated',
+              JavaScriptBackendSerializer.filterDartTypes(a.typesInstantiated),
+              JavaScriptBackendSerializer
+                  .filterDartTypes(b.typesInstantiated)) &&
+          strategy.testLists(
+              a,
+              b,
+              'specialTypesInstantiated',
+              JavaScriptBackendSerializer
+                  .filterSpecialTypes(a.typesInstantiated),
+              JavaScriptBackendSerializer
+                  .filterSpecialTypes(b.typesInstantiated)) &&
+          strategy.test(a, b, 'useGvn', a.useGvn, b.useGvn);
+    }
+    return true;
+  }
+
   visitNode(Node node1) {
     if (!success) return;
     int index = indices1.nodeIndices[node1];
@@ -808,7 +900,15 @@
         strategy.testConstants(node1, node2, 'getConstant($index)',
             elements1.getConstant(node1), elements2.getConstant(node2)) &&
         strategy.testTypes(node1, node2, 'typesCache[$index]',
-            elements1.typesCache[node1], elements2.typesCache[node2]);
+            elements1.typesCache[node1], elements2.typesCache[node2]) &&
+        testJumpTargets(
+            node1,
+            node2,
+            'getTargetDefinition($index)',
+            elements1.getTargetDefinition(node1),
+            elements2.getTargetDefinition(node2)) &&
+        testNativeData(node1, node2, 'getNativeData($index)',
+            elements1.getNativeData(node1), elements2.getNativeData(node2));
 
     node1.visitChildren(this);
   }
@@ -915,6 +1015,36 @@
         elements1.getRedirectingTargetConstructor(node1),
         elements2.getRedirectingTargetConstructor(node2));
   }
+
+  @override
+  visitGotoStatement(GotoStatement node1) {
+    visitStatement(node1);
+    if (!success) return;
+    int index = indices1.nodeIndices[node1];
+    GotoStatement node2 = indices2.nodeList[index];
+    success = testJumpTargets(node1, node2, 'getTargetOf($index)',
+        elements1.getTargetOf(node1), elements2.getTargetOf(node2));
+    if (!success) return;
+    if (node1.target == null && node2.target == null) {
+      return;
+    }
+    success = testLabelDefinitions(node1, node2, 'getTarget($index)',
+        elements1.getTargetLabel(node1), elements2.getTargetLabel(node2));
+  }
+
+  @override
+  visitLabel(Label node1) {
+    visitNode(node1);
+    if (!success) return;
+    int index = indices1.nodeIndices[node1];
+    Label node2 = indices2.nodeList[index];
+    success = testLabelDefinitions(
+        node1,
+        node2,
+        'getLabelDefinition($index)',
+        elements1.getLabelDefinition(node1),
+        elements2.getLabelDefinition(node2));
+  }
 }
 
 class NodeEquivalenceVisitor implements Visitor1<bool, Node> {
@@ -1151,7 +1281,7 @@
             node1, node2, 'condition', node1.condition, node2.condition) &&
         testNodes(
             node1, node2, 'expression', node1.expression, node2.expression) &&
-        testNodes(node1, node2, 'body', node1.expression, node2.body) &&
+        testNodes(node1, node2, 'body', node1.body, node2.body) &&
         testNodes(node1, node2, 'declaredIdentifier', node1.declaredIdentifier,
             node2.declaredIdentifier);
   }
diff --git a/pkg/compiler/lib/src/serialization/impact_serialization.dart b/pkg/compiler/lib/src/serialization/impact_serialization.dart
index af3cf5d..7e74259 100644
--- a/pkg/compiler/lib/src/serialization/impact_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/impact_serialization.dart
@@ -4,16 +4,15 @@
 
 library dart2js.serialization.impact;
 
-import '../dart_types.dart';
+import '../common.dart';
 import '../common/resolution.dart';
 import '../constants/expressions.dart';
+import '../dart_types.dart';
 import '../elements/elements.dart';
-import '../universe/call_structure.dart';
 import '../universe/selector.dart';
-import '../universe/world_impact.dart';
 import '../universe/use.dart';
+import '../universe/world_impact.dart';
 import '../util/enumset.dart';
-
 import 'keys.dart';
 import 'serialization.dart';
 import 'serialization_util.dart';
@@ -21,12 +20,13 @@
 /// Visitor that serializes a [ResolutionImpact] object using an
 /// [ObjectEncoder].
 class ImpactSerializer implements WorldImpactVisitor {
+  final Element element;
   final ObjectEncoder objectEncoder;
   final ListEncoder staticUses;
   final ListEncoder dynamicUses;
   final ListEncoder typeUses;
 
-  ImpactSerializer(ObjectEncoder objectEncoder)
+  ImpactSerializer(this.element, ObjectEncoder objectEncoder)
       : this.objectEncoder = objectEncoder,
         staticUses = objectEncoder.createList(Key.STATIC_USES),
         dynamicUses = objectEncoder.createList(Key.DYNAMIC_USES),
@@ -66,14 +66,10 @@
 
   @override
   void visitStaticUse(StaticUse staticUse) {
-    if (staticUse.element.isGenerativeConstructor &&
-        staticUse.element.enclosingClass.isUnnamedMixinApplication) {
-      // TODO(johnniwinther): Handle static use of forwarding constructors.
-      return;
-    }
     ObjectEncoder object = staticUses.createObject();
     object.setEnum(Key.KIND, staticUse.kind);
-    object.setElement(Key.ELEMENT, staticUse.element);
+    serializeElementReference(
+        element, Key.ELEMENT, Key.NAME, object, staticUse.element);
   }
 
   @override
@@ -97,29 +93,35 @@
   final Iterable<TypeUse> typeUses;
 
   DeserializedResolutionImpact(
-      {this.constSymbolNames,
-      this.constantLiterals,
-      this.dynamicUses,
+      {this.constSymbolNames: const <String>[],
+      this.constantLiterals: const <ConstantExpression>[],
+      this.dynamicUses: const <DynamicUse>[],
       EnumSet<Feature> features,
-      this.listLiterals,
-      this.mapLiterals,
-      this.staticUses,
-      this.typeUses})
+      this.listLiterals: const <ListLiteralUse>[],
+      this.mapLiterals: const <MapLiteralUse>[],
+      this.staticUses: const <StaticUse>[],
+      this.typeUses: const <TypeUse>[]})
       : this._features = features;
 
-  Iterable<Feature> get features => _features.iterable(Feature.values);
+  Iterable<Feature> get features {
+    return _features != null
+        ? _features.iterable(Feature.values)
+        : const <Feature>[];
+  }
 }
 
 class ImpactDeserializer {
   /// Deserializes a [WorldImpact] from [objectDecoder].
-  static ResolutionImpact deserializeImpact(ObjectDecoder objectDecoder) {
+  static ResolutionImpact deserializeImpact(
+      Element element, ObjectDecoder objectDecoder) {
     ListDecoder staticUseDecoder = objectDecoder.getList(Key.STATIC_USES);
     List<StaticUse> staticUses = <StaticUse>[];
     for (int index = 0; index < staticUseDecoder.length; index++) {
       ObjectDecoder object = staticUseDecoder.getObject(index);
       StaticUseKind kind = object.getEnum(Key.KIND, StaticUseKind.values);
-      Element element = object.getElement(Key.ELEMENT);
-      staticUses.add(new StaticUse.internal(element, kind));
+      Element usedElement =
+          deserializeElementReference(element, Key.ELEMENT, Key.NAME, object);
+      staticUses.add(new StaticUse.internal(usedElement, kind));
     }
 
     ListDecoder dynamicUseDecoder = objectDecoder.getList(Key.DYNAMIC_USES);
diff --git a/pkg/compiler/lib/src/serialization/keys.dart b/pkg/compiler/lib/src/serialization/keys.dart
index d74c820..c7599b2 100644
--- a/pkg/compiler/lib/src/serialization/keys.dart
+++ b/pkg/compiler/lib/src/serialization/keys.dart
@@ -8,6 +8,8 @@
 class Key {
   static const Key ALIAS = const Key('alias');
   static const Key ARGUMENTS = const Key('arguments');
+  static const Key ASYNC_MARKER = const Key('asyncMarker');
+  static const Key BODY = const Key('body');
   static const Key BOUND = const Key('bound');
   static const Key CACHED_TYPE = const Key('cachedType');
   static const Key CALL_STRUCTURE = const Key('callStructure');
@@ -45,7 +47,9 @@
   static const Key INTERFACES = const Key('interfaces');
   static const Key INDEX = const Key('index');
   static const Key IS_ABSTRACT = const Key('isAbstract');
+  static const Key IS_BREAK_TARGET = const Key('isBreakTarget');
   static const Key IS_CONST = const Key('isConst');
+  static const Key IS_CONTINUE_TARGET = const Key('isContinueTarget');
   static const Key IS_DEFERRED = const Key('isDeferred');
   static const Key IS_EMPTY = const Key('isEmpty');
   static const Key IS_EXTERNAL = const Key('isExternal');
@@ -57,8 +61,14 @@
   static const Key IS_SETTER = const Key('isSetter');
   static const Key IS_UNNAMED_MIXIN_APPLICATION =
       const Key('isUnnamedMixinApplication');
+  static const Key JUMP_TARGET = const Key('jumpTarget');
+  static const Key JUMP_TARGETS = const Key('jumpTargets');
+  static const Key JUMP_TARGET_DEFINITION = const Key('jumpTargetDefinition');
   static const Key KEYS = const Key('keys');
   static const Key KIND = const Key('kind');
+  static const Key LABEL_DEFINITION = const Key('labelDefinition');
+  static const Key LABEL_DEFINITIONS = const Key('labelDefinitions');
+  static const Key LABELS = const Key('labels');
   static const Key LEFT = const Key('left');
   static const Key LENGTH = const Key('length');
   static const Key LIBRARY = const Key('library');
@@ -74,7 +84,10 @@
   static const Key NAMED_ARGUMENTS = const Key('named-arguments');
   static const Key NAMED_PARAMETERS = const Key('named-parameters');
   static const Key NAMED_PARAMETER_TYPES = const Key('named-parameter-types');
+  static const Key NATIVE = const Key('native');
+  static const Key NESTING_LEVEL = const Key('nestingLevel');
   static const Key NEW_STRUCTURE = const Key('newStructure');
+  static const Key NODE = const Key('node');
   static const Key OFFSET = const Key('offset');
   static const Key OPERATOR = const Key('operator');
   static const Key OPTIONAL_PARAMETER_TYPES =
@@ -94,6 +107,7 @@
   static const Key SUPERTYPES = const Key('supertypes');
   static const Key SYMBOLS = const Key('symbols');
   static const Key TAGS = const Key('tags');
+  static const Key TARGET_LABEL = const Key('targetLabel');
   static const Key TRUE = const Key('true');
   static const Key TYPE = const Key('type');
   static const Key TYPES = const Key('types');
diff --git a/pkg/compiler/lib/src/serialization/modelz.dart b/pkg/compiler/lib/src/serialization/modelz.dart
index e06cb03..5122259 100644
--- a/pkg/compiler/lib/src/serialization/modelz.dart
+++ b/pkg/compiler/lib/src/serialization/modelz.dart
@@ -13,23 +13,21 @@
 import '../common/resolution.dart' show Resolution;
 import '../constants/constructors.dart';
 import '../constants/expressions.dart';
-import '../core_types.dart';
 import '../dart_types.dart';
+import '../elements/common.dart';
 import '../elements/elements.dart';
 import '../elements/modelx.dart' show FunctionSignatureX;
-import '../elements/common.dart';
 import '../elements/visitor.dart';
 import '../io/source_file.dart';
 import '../ordered_typeset.dart';
 import '../resolution/class_members.dart' as class_members;
-import '../resolution/tree_elements.dart' show TreeElements;
 import '../resolution/scope.dart' show Scope;
+import '../resolution/tree_elements.dart' show TreeElements;
 import '../script.dart';
 import '../serialization/constant_serialization.dart';
 import '../tokens/token.dart' show Token;
 import '../tree/tree.dart';
 import '../util/util.dart' show Link, LinkBuilder;
-
 import 'keys.dart';
 import 'serialization.dart';
 
@@ -82,13 +80,10 @@
   bool get isAbstract => false;
 
   @override
-  bool get isAssignable => _unsupported('isAssignable');
-
-  @override
   bool get isClassMember => false;
 
   @override
-  bool get isClosure => _unsupported('isClosure');
+  bool get isClosure => false;
 
   @override
   bool get isConst => _unsupported('isConst');
@@ -126,11 +121,6 @@
   Iterable<MetadataAnnotation> get metadata => const <MetadataAnnotation>[];
 
   @override
-  Element get outermostEnclosingMemberOrTopLevel {
-    return _unsupported('outermostEnclosingMemberOrTopLevel');
-  }
-
-  @override
   Token get position => _unsupported('position');
 }
 
@@ -261,8 +251,10 @@
 }
 
 abstract class AstElementMixin implements AstElement, ElementZ {
+  // TODO(johnniwinther): This is needed for the token invariant assertion. Find
+  // another way to bypass the test for modelz.
   @override
-  bool get hasNode => _unsupported('hasNode');
+  bool get hasNode => false;
 
   @override
   bool get hasResolvedAst => _unsupported('hasResolvedAst');
@@ -484,6 +476,7 @@
 
 class ScriptZ implements Script {
   final Uri resourceUri;
+  SourceFile _file;
 
   ScriptZ(this.resourceUri);
 
@@ -493,13 +486,27 @@
   }
 
   @override
-  SourceFile get file => throw new UnsupportedError('ScriptZ.file');
+  SourceFile get file {
+    if (_file == null) {
+      throw new UnsupportedError('ScriptZ.file');
+    }
+    return _file;
+  }
+
+  void set file(SourceFile value) {
+    _file = value;
+  }
 
   @override
   bool get isSynthesized => throw new UnsupportedError('ScriptZ.isSynthesized');
 
   @override
-  String get name => resourceUri.toString();
+  String get name {
+    if (_file != null) {
+      return _file.filename;
+    }
+    return resourceUri.toString();
+  }
 
   // TODO(johnniwinther): Support the distinction between [readableUri] and
   // [resourceUri]; needed for platform libraries.
@@ -507,7 +514,12 @@
   Uri get readableUri => resourceUri;
 
   @override
-  String get text => throw new UnsupportedError('ScriptZ.text');
+  String get text {
+    if (_file != null) {
+      return _file.slowText();
+    }
+    throw new UnsupportedError('ScriptZ.text');
+  }
 }
 
 class CompilationUnitElementZ extends DeserializedElementZ
@@ -588,6 +600,7 @@
 
 abstract class ClassMemberMixin implements DeserializedElementZ {
   ClassElement _class;
+  CompilationUnitElement _compilationUnit;
 
   @override
   Element get enclosingElement => enclosingClass;
@@ -607,7 +620,16 @@
   LibraryElement get library => enclosingClass.library;
 
   @override
-  CompilationUnitElement get compilationUnit => enclosingClass.compilationUnit;
+  CompilationUnitElement get compilationUnit {
+    if (_compilationUnit == null) {
+      _compilationUnit =
+          _decoder.getElement(Key.COMPILATION_UNIT, isOptional: true);
+      if (_compilationUnit == null) {
+        _compilationUnit = enclosingClass.compilationUnit;
+      }
+    }
+    return _compilationUnit;
+  }
 }
 
 abstract class InstanceMemberMixin implements DeserializedElementZ {
@@ -662,30 +684,34 @@
       bool optionalParametersAreNamed = false;
       List<DartType> parameterTypes = <DartType>[];
       List<DartType> optionalParameterTypes = <DartType>[];
-      List<String> namedParameters = <String>[];
-      List<DartType> namedParameterTypes = <DartType>[];
       for (ParameterElement parameter in parameters) {
         if (parameter.isOptional) {
           optionalParameterCount++;
-          requiredParameters.add(parameter);
+          optionalParameters.add(parameter);
           orderedOptionalParameters.add(parameter);
           if (parameter.isNamed) {
             optionalParametersAreNamed = true;
-            namedParameters.add(parameter.name);
-            namedParameterTypes.add(parameter.type);
           } else {
             optionalParameterTypes.add(parameter.type);
           }
         } else {
           requiredParameterCount++;
-          optionalParameters.add(parameter);
+          requiredParameters.add(parameter);
           parameterTypes.add(parameter.type);
         }
       }
+      List<String> namedParameters = const <String>[];
+      List<DartType> namedParameterTypes = const <DartType>[];
       if (optionalParametersAreNamed) {
+        namedParameters = <String>[];
+        namedParameterTypes = <DartType>[];
         orderedOptionalParameters.sort((Element a, Element b) {
           return a.name.compareTo(b.name);
         });
+        for (ParameterElement parameter in orderedOptionalParameters) {
+          namedParameters.add(parameter.name);
+          namedParameterTypes.add(parameter.type);
+        }
       }
 
       FunctionType type = new FunctionType(
@@ -889,33 +915,16 @@
 
 abstract class MixinApplicationElementMixin
     implements ElementZ, MixinApplicationElement {
-  Link<ConstructorElement> _constructors;
-
   @override
-  bool get isMixinApplication => false;
+  bool get isMixinApplication => true;
 
   @override
   ClassElement get mixin => mixinType.element;
-
-  Link<ConstructorElement> get constructors {
-    if (_constructors == null) {
-      LinkBuilder<ConstructorElement> builder =
-          new LinkBuilder<ConstructorElement>();
-      for (ConstructorElement definingConstructor in superclass.constructors) {
-        if (definingConstructor.isGenerativeConstructor &&
-            definingConstructor.memberName.isAccessibleFrom(library)) {
-          builder.addLast(
-              new ForwardingConstructorElementZ(this, definingConstructor));
-        }
-      }
-      _constructors = builder.toLink();
-    }
-    return _constructors;
-  }
 }
 
 class NamedMixinApplicationElementZ extends ClassElementZ
-    with MixinApplicationElementCommon, MixinApplicationElementMixin {
+    with MixinApplicationElementMixin {
+  Link<Element> _constructors;
   InterfaceType _mixinType;
 
   NamedMixinApplicationElementZ(ObjectDecoder decoder) : super(decoder);
@@ -939,6 +948,7 @@
   final InterfaceType supertype;
   final Link<DartType> interfaces;
   OrderedTypeSet _allSupertypesAndSelf;
+  Link<ConstructorElement> _constructors;
 
   UnnamedMixinApplicationElementZ(
       ClassElement subclass, InterfaceType supertype, InterfaceType mixin)
@@ -953,6 +963,22 @@
   @override
   bool get isUnnamedMixinApplication => true;
 
+  Link<ConstructorElement> get constructors {
+    if (_constructors == null) {
+      LinkBuilder<ConstructorElement> builder =
+          new LinkBuilder<ConstructorElement>();
+      for (ConstructorElement definingConstructor in superclass.constructors) {
+        if (definingConstructor.isGenerativeConstructor &&
+            definingConstructor.memberName.isAccessibleFrom(library)) {
+          builder.addLast(
+              new ForwardingConstructorElementZ(this, definingConstructor));
+        }
+      }
+      _constructors = builder.toLink();
+    }
+    return _constructors;
+  }
+
   @override
   List<DartType> _getTypeVariables() {
     // Create synthetic type variables for the mixin application.
@@ -1072,7 +1098,7 @@
   }
 
   @override
-  AsyncMarker get asyncMarker => _unsupported('asyncMarker');
+  AsyncMarker get asyncMarker => AsyncMarker.SYNC;
 
   @override
   InterfaceType computeEffectiveTargetType(InterfaceType newType) {
@@ -1336,6 +1362,11 @@
   }
 
   @override
+  AsyncMarker get asyncMarker {
+    return _decoder.getEnum(Key.ASYNC_MARKER, AsyncMarker.values);
+  }
+
+  @override
   bool get isOperator => _decoder.getBool(Key.IS_OPERATOR);
 }
 
@@ -1430,6 +1461,9 @@
   accept(ElementVisitor visitor, arg) {
     return visitor.visitGetterElement(this, arg);
   }
+
+  @override
+  AsyncMarker get asyncMarker => AsyncMarker.SYNC;
 }
 
 class TopLevelGetterElementZ extends GetterElementZ with LibraryMemberMixin {
@@ -1467,6 +1501,9 @@
   accept(ElementVisitor visitor, arg) {
     return visitor.visitSetterElement(this, arg);
   }
+
+  @override
+  AsyncMarker get asyncMarker => AsyncMarker.SYNC;
 }
 
 class TopLevelSetterElementZ extends SetterElementZ with LibraryMemberMixin {
@@ -1698,7 +1735,7 @@
   SourceSpan get sourcePosition => typeDeclaration.sourcePosition;
 }
 
-class ParameterElementZ extends DeserializedElementZ
+abstract class ParameterElementZ extends DeserializedElementZ
     with AnalyzableElementMixin, AstElementMixin, TypedElementMixin
     implements ParameterElement {
   FunctionElement _functionDeclaration;
@@ -1708,9 +1745,10 @@
   ParameterElementZ(ObjectDecoder decoder) : super(decoder);
 
   @override
-  accept(ElementVisitor visitor, arg) {
-    return visitor.visitParameterElement(this, arg);
-  }
+  bool get isFinal => _decoder.getBool(Key.IS_FINAL);
+
+  @override
+  bool get isConst => false;
 
   @override
   ConstantExpression get constant {
@@ -1755,15 +1793,25 @@
   bool get isOptional => _decoder.getBool(Key.IS_OPTIONAL);
 
   @override
-  ElementKind get kind => ElementKind.PARAMETER;
-
-  @override
   LibraryElement get library => executableContext.library;
 
   @override
   MemberElement get memberContext => executableContext.memberContext;
 }
 
+class LocalParameterElementZ extends ParameterElementZ
+    implements LocalParameterElement {
+  LocalParameterElementZ(ObjectDecoder decoder) : super(decoder);
+
+  @override
+  accept(ElementVisitor visitor, arg) {
+    return visitor.visitParameterElement(this, arg);
+  }
+
+  @override
+  ElementKind get kind => ElementKind.PARAMETER;
+}
+
 class InitializingFormalElementZ extends ParameterElementZ
     implements InitializingFormalElement {
   FieldElement _fieldElement;
@@ -1808,9 +1856,12 @@
   ElementKind get kind => ElementKind.VARIABLE;
 
   @override
+  bool get isFinal => _decoder.getBool(Key.IS_FINAL);
+
+  @override
   bool get isConst {
     if (_isConst == null) {
-      _constant = _decoder.getConstant(Key.CONSTANT);
+      _constant = _decoder.getConstant(Key.CONSTANT, isOptional: true);
       _isConst = _constant != null;
     }
     return _isConst;
diff --git a/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart b/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
index d25426e..eb03860 100644
--- a/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
@@ -10,15 +10,17 @@
 import '../dart_types.dart';
 import '../diagnostics/diagnostic_listener.dart';
 import '../elements/elements.dart';
-import '../parser/parser.dart' show Parser;
+import '../elements/modelx.dart';
 import '../parser/listener.dart' show ParserError;
 import '../parser/node_listener.dart' show NodeListener;
+import '../parser/parser.dart' show Parser;
 import '../resolution/enum_creator.dart';
 import '../resolution/send_structure.dart';
 import '../resolution/tree_elements.dart';
-import '../tree/tree.dart';
 import '../tokens/token.dart';
+import '../tree/tree.dart';
 import '../universe/selector.dart';
+import '../util/util.dart';
 import 'keys.dart';
 import 'serialization.dart';
 import 'serialization_util.dart';
@@ -54,13 +56,15 @@
 
 /// Serializer for [ResolvedAst]s.
 class ResolvedAstSerializer extends Visitor {
+  final SerializerPlugin nativeDataSerializer;
   final ObjectEncoder objectEncoder;
   final ResolvedAst resolvedAst;
   final AstIndexComputer indexComputer = new AstIndexComputer();
   final Map<int, ObjectEncoder> nodeData = <int, ObjectEncoder>{};
   ListEncoder _nodeDataEncoder;
 
-  ResolvedAstSerializer(this.objectEncoder, this.resolvedAst);
+  ResolvedAstSerializer(
+      this.objectEncoder, this.resolvedAst, this.nativeDataSerializer);
 
   AstElement get element => resolvedAst.element;
 
@@ -71,12 +75,44 @@
   Map<Node, int> get nodeIndices => indexComputer.nodeIndices;
   List<Node> get nodeList => indexComputer.nodeList;
 
+  Map<JumpTarget, int> jumpTargetMap = <JumpTarget, int>{};
+  Map<LabelDefinition, int> labelDefinitionMap = <LabelDefinition, int>{};
+
+  /// Returns the unique id for [jumpTarget], creating it if necessary.
+  int getJumpTargetId(JumpTarget jumpTarget) {
+    return jumpTargetMap.putIfAbsent(jumpTarget, () => jumpTargetMap.length);
+  }
+
+  /// Returns the unique id for [labelDefinition], creating it if necessary.
+  int getLabelDefinitionId(LabelDefinition labelDefinition) {
+    return labelDefinitionMap.putIfAbsent(
+        labelDefinition, () => labelDefinitionMap.length);
+  }
+
   /// Serializes [resolvedAst] into [objectEncoder].
   void serialize() {
+    objectEncoder.setEnum(Key.KIND, resolvedAst.kind);
+    switch (resolvedAst.kind) {
+      case ResolvedAstKind.PARSED:
+        serializeParsed();
+        break;
+      case ResolvedAstKind.DEFAULT_CONSTRUCTOR:
+      case ResolvedAstKind.FORWARDING_CONSTRUCTOR:
+        // No additional properties.
+        break;
+    }
+  }
+
+  /// Serialize [ResolvedAst] that is defined in terms of an AST together with
+  /// [TreeElements].
+  void serializeParsed() {
     objectEncoder.setUri(
         Key.URI,
         elements.analyzedElement.compilationUnit.script.resourceUri,
         elements.analyzedElement.compilationUnit.script.resourceUri);
+    if (resolvedAst.body != null) {
+      objectEncoder.setInt(Key.BODY, nodeIndices[resolvedAst.body]);
+    }
     AstKind kind;
     if (element.enclosingClass is EnumClassElement) {
       if (element.name == 'index') {
@@ -110,9 +146,47 @@
         }
       }
     }
-    objectEncoder.setEnum(Key.KIND, kind);
+    objectEncoder.setEnum(Key.SUB_KIND, kind);
     root.accept(indexComputer);
     root.accept(this);
+    if (jumpTargetMap.isNotEmpty) {
+      ListEncoder list = objectEncoder.createList(Key.JUMP_TARGETS);
+      for (JumpTarget jumpTarget in jumpTargetMap.keys) {
+        serializeJumpTarget(jumpTarget, list.createObject());
+      }
+    }
+    if (labelDefinitionMap.isNotEmpty) {
+      ListEncoder list = objectEncoder.createList(Key.LABEL_DEFINITIONS);
+      for (LabelDefinition labelDefinition in labelDefinitionMap.keys) {
+        serializeLabelDefinition(labelDefinition, list.createObject());
+      }
+    }
+  }
+
+  /// Serialize [target] into [encoder].
+  void serializeJumpTarget(JumpTarget jumpTarget, ObjectEncoder encoder) {
+    encoder.setElement(Key.EXECUTABLE_CONTEXT, jumpTarget.executableContext);
+    encoder.setInt(Key.NODE, nodeIndices[jumpTarget.statement]);
+    encoder.setInt(Key.NESTING_LEVEL, jumpTarget.nestingLevel);
+    encoder.setBool(Key.IS_BREAK_TARGET, jumpTarget.isBreakTarget);
+    encoder.setBool(Key.IS_CONTINUE_TARGET, jumpTarget.isContinueTarget);
+    if (jumpTarget.labels.isNotEmpty) {
+      List<int> labelIdList = <int>[];
+      for (LabelDefinition label in jumpTarget.labels) {
+        labelIdList.add(getLabelDefinitionId(label));
+      }
+      encoder.setInts(Key.LABELS, labelIdList);
+    }
+  }
+
+  /// Serialize [label] into [encoder].
+  void serializeLabelDefinition(
+      LabelDefinition labelDefinition, ObjectEncoder encoder) {
+    encoder.setInt(Key.NODE, nodeIndices[labelDefinition.label]);
+    encoder.setString(Key.NAME, labelDefinition.labelName);
+    encoder.setBool(Key.IS_BREAK_TARGET, labelDefinition.isBreakTarget);
+    encoder.setBool(Key.IS_CONTINUE_TARGET, labelDefinition.isContinueTarget);
+    encoder.setInt(Key.JUMP_TARGET, getJumpTargetId(labelDefinition.target));
   }
 
   /// Computes the [ListEncoder] for serializing data for nodes.
@@ -137,13 +211,8 @@
   visitNode(Node node) {
     Element nodeElement = elements[node];
     if (nodeElement != null) {
-      if (nodeElement.enclosingClass != null &&
-          nodeElement.enclosingClass.isUnnamedMixinApplication) {
-        // TODO(johnniwinther): Handle references to members of unnamed mixin
-        // applications.
-      } else {
-        getNodeDataEncoder(node).setElement(Key.ELEMENT, nodeElement);
-      }
+      serializeElementReference(element, Key.ELEMENT, Key.NAME,
+          getNodeDataEncoder(node), nodeElement);
     }
     DartType type = elements.getType(node);
     if (type != null) {
@@ -162,7 +231,16 @@
     if (cachedType != null) {
       getNodeDataEncoder(node).setType(Key.CACHED_TYPE, cachedType);
     }
-    // TODO(johnniwinther): Serialize [JumpTarget]s.
+    JumpTarget jumpTargetDefinition = elements.getTargetDefinition(node);
+    if (jumpTargetDefinition != null) {
+      getNodeDataEncoder(node).setInt(
+          Key.JUMP_TARGET_DEFINITION, getJumpTargetId(jumpTargetDefinition));
+    }
+    var nativeData = elements.getNativeData(node);
+    if (nativeData != null) {
+      nativeDataSerializer.onData(
+          nativeData, getNodeDataEncoder(node).createObject(Key.NATIVE));
+    }
     node.visitChildren(this);
   }
 
@@ -189,13 +267,28 @@
   @override
   visitGotoStatement(GotoStatement node) {
     visitStatement(node);
-    // TODO(johnniwinther): Serialize [JumpTarget]s and [LabelDefinition]s.
+    JumpTarget jumpTarget = elements.getTargetOf(node);
+    if (jumpTarget != null) {
+      getNodeDataEncoder(node)
+          .setInt(Key.JUMP_TARGET, getJumpTargetId(jumpTarget));
+    }
+    if (node.target != null) {
+      LabelDefinition targetLabel = elements.getTargetLabel(node);
+      if (targetLabel != null) {
+        getNodeDataEncoder(node)
+            .setInt(Key.TARGET_LABEL, getLabelDefinitionId(targetLabel));
+      }
+    }
   }
 
   @override
   visitLabel(Label node) {
     visitNode(node);
-    // TODO(johnniwinther): Serialize[LabelDefinition]s.
+    LabelDefinition labelDefinition = elements.getLabelDefinition(node);
+    if (labelDefinition != null) {
+      getNodeDataEncoder(node)
+          .setInt(Key.LABEL_DEFINITION, getLabelDefinitionId(labelDefinition));
+    }
   }
 }
 
@@ -214,8 +307,32 @@
   /// Deserializes the [ResolvedAst] for [element] from [objectDecoder].
   /// [parsing] and [getBeginToken] are used for parsing the [Node] for
   /// [element] from its source code.
-  static ResolvedAst deserialize(Element element, ObjectDecoder objectDecoder,
-      Parsing parsing, Token getBeginToken(Uri uri, int charOffset)) {
+  static ResolvedAst deserialize(
+      Element element,
+      ObjectDecoder objectDecoder,
+      ParsingContext parsing,
+      Token getBeginToken(Uri uri, int charOffset),
+      DeserializerPlugin nativeDataDeserializer) {
+    ResolvedAstKind kind =
+        objectDecoder.getEnum(Key.KIND, ResolvedAstKind.values);
+    switch (kind) {
+      case ResolvedAstKind.PARSED:
+        return deserializeParsed(element, objectDecoder, parsing, getBeginToken,
+            nativeDataDeserializer);
+      case ResolvedAstKind.DEFAULT_CONSTRUCTOR:
+      case ResolvedAstKind.FORWARDING_CONSTRUCTOR:
+        return new SynthesizedResolvedAst(element, kind);
+    }
+  }
+
+  /// Deserialize a [ResolvedAst] that is defined in terms of an AST together
+  /// with [TreeElements].
+  static ResolvedAst deserializeParsed(
+      Element element,
+      ObjectDecoder objectDecoder,
+      ParsingContext parsing,
+      Token getBeginToken(Uri uri, int charOffset),
+      DeserializerPlugin nativeDataDeserializer) {
     CompilationUnitElement compilationUnit = element.compilationUnit;
     DiagnosticReporter reporter = parsing.reporter;
 
@@ -366,21 +483,77 @@
       }
     }
 
-    AstKind kind = objectDecoder.getEnum(Key.KIND, AstKind.values);
+    AstKind kind = objectDecoder.getEnum(Key.SUB_KIND, AstKind.values);
     Node root = computeNode(kind);
     TreeElementMapping elements = new TreeElementMapping(element);
     AstIndexComputer indexComputer = new AstIndexComputer();
     Map<Node, int> nodeIndices = indexComputer.nodeIndices;
     List<Node> nodeList = indexComputer.nodeList;
+    Node body;
+    int bodyNodeIndex = objectDecoder.getInt(Key.BODY, isOptional: true);
+    if (bodyNodeIndex != null) {
+      body = nodeList[bodyNodeIndex];
+    }
     root.accept(indexComputer);
+
+    List<JumpTarget> jumpTargets = <JumpTarget>[];
+    Map<JumpTarget, List<int>> jumpTargetLabels = <JumpTarget, List<int>>{};
+    List<LabelDefinition> labelDefinitions = <LabelDefinition>[];
+
+    ListDecoder jumpTargetsDecoder =
+        objectDecoder.getList(Key.JUMP_TARGETS, isOptional: true);
+    if (jumpTargetsDecoder != null) {
+      for (int i = 0; i < jumpTargetsDecoder.length; i++) {
+        ObjectDecoder decoder = jumpTargetsDecoder.getObject(i);
+        ExecutableElement executableContext =
+            decoder.getElement(Key.EXECUTABLE_CONTEXT);
+        Node statement = nodeList[decoder.getInt(Key.NODE)];
+        int nestingLevel = decoder.getInt(Key.NESTING_LEVEL);
+        JumpTarget jumpTarget =
+            new JumpTargetX(statement, nestingLevel, executableContext);
+        jumpTarget.isBreakTarget = decoder.getBool(Key.IS_BREAK_TARGET);
+        jumpTarget.isContinueTarget = decoder.getBool(Key.IS_CONTINUE_TARGET);
+        jumpTargetLabels[jumpTarget] =
+            decoder.getInts(Key.LABELS, isOptional: true);
+        jumpTargets.add(jumpTarget);
+      }
+    }
+
+    ListDecoder labelDefinitionsDecoder =
+        objectDecoder.getList(Key.LABEL_DEFINITIONS, isOptional: true);
+    if (labelDefinitionsDecoder != null) {
+      for (int i = 0; i < labelDefinitionsDecoder.length; i++) {
+        ObjectDecoder decoder = labelDefinitionsDecoder.getObject(i);
+        Label label = nodeList[decoder.getInt(Key.NODE)];
+        String labelName = decoder.getString(Key.NAME);
+        JumpTarget target = jumpTargets[decoder.getInt(Key.JUMP_TARGET)];
+        LabelDefinitionX labelDefinition =
+            new LabelDefinitionX(label, labelName, target);
+        labelDefinition.isBreakTarget = decoder.getBool(Key.IS_BREAK_TARGET);
+        labelDefinition.isContinueTarget =
+            decoder.getBool(Key.IS_CONTINUE_TARGET);
+        labelDefinitions.add(labelDefinition);
+      }
+    }
+    jumpTargetLabels.forEach((JumpTargetX jumpTarget, List<int> labelIds) {
+      if (labelIds.isEmpty) return;
+      LinkBuilder<LabelDefinition> linkBuilder =
+          new LinkBuilder<LabelDefinition>();
+      for (int labelId in labelIds) {
+        linkBuilder.addLast(labelDefinitions[labelId]);
+      }
+      jumpTarget.labels = linkBuilder.toLink();
+    });
+
     ListDecoder dataDecoder = objectDecoder.getList(Key.DATA);
     if (dataDecoder != null) {
       for (int i = 0; i < dataDecoder.length; i++) {
         ObjectDecoder objectDecoder = dataDecoder.getObject(i);
         int id = objectDecoder.getInt(Key.ID);
         Node node = nodeList[id];
-        Element nodeElement =
-            objectDecoder.getElement(Key.ELEMENT, isOptional: true);
+        Element nodeElement = deserializeElementReference(
+            element, Key.ELEMENT, Key.NAME, objectDecoder,
+            isOptional: true);
         if (nodeElement != null) {
           elements[node] = nodeElement;
         }
@@ -415,8 +588,36 @@
           elements.setNewStructure(
               node, deserializeNewStructure(newStructureDecoder));
         }
+        int targetDefinitionId =
+            objectDecoder.getInt(Key.JUMP_TARGET_DEFINITION, isOptional: true);
+        if (targetDefinitionId != null) {
+          elements.defineTarget(node, jumpTargets[targetDefinitionId]);
+        }
+        int targetOfId =
+            objectDecoder.getInt(Key.JUMP_TARGET, isOptional: true);
+        if (targetOfId != null) {
+          elements.registerTargetOf(node, jumpTargets[targetOfId]);
+        }
+        int labelDefinitionId =
+            objectDecoder.getInt(Key.LABEL_DEFINITION, isOptional: true);
+        if (labelDefinitionId != null) {
+          elements.defineLabel(node, labelDefinitions[labelDefinitionId]);
+        }
+        int targetLabelId =
+            objectDecoder.getInt(Key.TARGET_LABEL, isOptional: true);
+        if (targetLabelId != null) {
+          elements.registerTargetLabel(node, labelDefinitions[targetLabelId]);
+        }
+        ObjectDecoder nativeDataDecoder =
+            objectDecoder.getObject(Key.NATIVE, isOptional: true);
+        if (nativeDataDecoder != null) {
+          var nativeData = nativeDataDeserializer.onData(nativeDataDecoder);
+          if (nativeData != null) {
+            elements.registerNativeData(node, nativeData);
+          }
+        }
       }
     }
-    return new ResolvedAst(element, root, elements);
+    return new ParsedResolvedAst(element, root, body, elements);
   }
 }
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index 1521f39..a16e558 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -682,6 +682,7 @@
     if (element == null) {
       throw new ArgumentError('Serializer._getElementDataObject(null)');
     }
+    element = element.declaration;
     DataObject dataObject = _elementMap[element];
     if (dataObject == null) {
       if (!shouldInclude(element)) {
@@ -856,6 +857,9 @@
   /// Use [creatorEncoder] to create a data object with id [tag] for storing
   /// additional data for [element].
   void onElement(Element element, ObjectEncoder createEncoder(String tag)) {}
+
+  /// Called to serialize custom [data].
+  void onData(var data, ObjectEncoder encoder) {}
 }
 
 /// Plugin for deserializing additional data for an [Element].
@@ -867,6 +871,9 @@
   /// Use [getDecoder] to retrieve the data object with id [tag] stored for
   /// [element]. If not object is stored for [tag], [getDecoder] returns `null`.
   void onElement(Element element, ObjectDecoder getDecoder(String tag)) {}
+
+  /// Called to deserialize custom data from [decoder].
+  dynamic onData(ObjectDecoder decoder) {}
 }
 
 /// Context for parallel deserialization.
diff --git a/pkg/compiler/lib/src/serialization/serialization_util.dart b/pkg/compiler/lib/src/serialization/serialization_util.dart
index cd5e77a..24aa6f8 100644
--- a/pkg/compiler/lib/src/serialization/serialization_util.dart
+++ b/pkg/compiler/lib/src/serialization/serialization_util.dart
@@ -4,19 +4,15 @@
 
 library dart2js.serialization.util;
 
-import '../dart_types.dart';
-import '../common/resolution.dart';
+import '../common.dart';
 import '../constants/expressions.dart';
+import '../dart_types.dart';
 import '../elements/elements.dart';
 import '../resolution/access_semantics.dart';
 import '../resolution/operators.dart';
 import '../resolution/send_structure.dart';
 import '../universe/call_structure.dart';
 import '../universe/selector.dart';
-import '../universe/world_impact.dart';
-import '../universe/use.dart';
-import '../util/enumset.dart';
-
 import 'keys.dart';
 import 'serialization.dart';
 
@@ -479,3 +475,45 @@
       throw new UnsupportedError('Unsupported access kind: $kind');
   }
 }
+
+/// Serialize a reference from [context] to an [element] which might be a member
+/// of an unnamed mixin application. If it is, [element] is by serialized
+/// indirectly by name in the [nameKey] of [encoder], otherwise [element] is
+/// serialized directly in [elementKey] in [encoder].
+void serializeElementReference(Element context, Key elementKey, Key nameKey,
+    ObjectEncoder encoder, Element element) {
+  if (element.isGenerativeConstructor &&
+      element.enclosingClass.isUnnamedMixinApplication) {
+    assert(invariant(element, element.isConstructor,
+        message: "Unexpected reference of forwarding constructor "
+            "${element} from $context."));
+    encoder.setString(nameKey, element.name);
+  } else {
+    encoder.setElement(elementKey, element);
+  }
+}
+
+/// Deserialize a reference from [context] to an [Element] which might be a
+/// member of an unnamed mixin application. If it is, the [Element] is by
+/// deserialized indirectly by name from [nameKey] in [decoder], otherwise
+/// the [Element] is deserialized directly from [elementKey] in [encoder].
+Element deserializeElementReference(
+    Element context, Key elementKey, Key nameKey, ObjectDecoder decoder,
+    {bool isOptional: false}) {
+  Element element = decoder.getElement(elementKey, isOptional: true);
+  if (element == null) {
+    String elementName = decoder.getString(nameKey, isOptional: isOptional);
+    if (elementName == null) {
+      return null;
+    }
+    assert(invariant(NO_LOCATION_SPANNABLE, context.isConstructor,
+        message: "Unexpected reference of forwarding constructor "
+            "'${elementName}' from $context."));
+    ClassElement superclass = context.enclosingClass.superclass;
+    element = superclass.lookupConstructor(elementName);
+    assert(invariant(NO_LOCATION_SPANNABLE, element != null,
+        message: "Unresolved reference of forwarding constructor "
+            "'${elementName}' from $context."));
+  }
+  return element;
+}
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index 1289b77..0eb9db0 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -46,6 +46,16 @@
     return deserializer != null && deserializer.isDeserialized(element);
   }
 
+  bool hasResolutionImpact(Element element) {
+    return deserializer != null && deserializer.hasResolutionImpact(element);
+  }
+
+  ResolutionImpact getResolutionImpact(Element element) {
+    return deserializer != null
+        ? deserializer.getResolutionImpact(element)
+        : null;
+  }
+
   /// Creates the [ResolutionWorkItem] for the deserialized [element].
   ResolutionWorkItem createResolutionWorkItem(
       Element element, ItemCompilationContext context) {
@@ -54,6 +64,14 @@
     return new DeserializedResolutionWorkItem(
         element, context, deserializer.computeWorldImpact(element));
   }
+
+  bool hasResolvedAst(Element element) {
+    return deserializer != null ? deserializer.hasResolvedAst(element) : false;
+  }
+
+  ResolvedAst getResolvedAst(Element element) {
+    return deserializer != null ? deserializer.getResolvedAst(element) : null;
+  }
 }
 
 /// A [ResolutionWorkItem] for a deserialized element.
@@ -84,7 +102,9 @@
 abstract class DeserializerSystem {
   Future<LibraryElement> readLibrary(Uri resolvedUri);
   bool isDeserialized(Element element);
+  bool hasResolvedAst(Element element);
   ResolvedAst getResolvedAst(Element element);
+  bool hasResolutionImpact(Element element);
   ResolutionImpact getResolutionImpact(Element element);
   WorldImpact computeWorldImpact(Element element);
 }
diff --git a/pkg/compiler/lib/src/source_file_provider.dart b/pkg/compiler/lib/src/source_file_provider.dart
index e5b3a03..da15419 100644
--- a/pkg/compiler/lib/src/source_file_provider.dart
+++ b/pkg/compiler/lib/src/source_file_provider.dart
@@ -8,16 +8,16 @@
 import 'dart:convert';
 import 'dart:io';
 import 'dart:math' as math;
-
-import '../compiler.dart' as api show Diagnostic, DiagnosticHandler;
-import '../compiler_new.dart' as api show CompilerInput, CompilerDiagnostics;
-import 'dart2js.dart' show AbortLeg;
-import 'colors.dart' as colors;
-import 'io/source_file.dart';
-import 'filenames.dart';
-import 'util/uri_extras.dart';
 import 'dart:typed_data';
+
+import '../compiler.dart' as api show Diagnostic;
+import '../compiler_new.dart' as api;
 import '../compiler_new.dart';
+import 'colors.dart' as colors;
+import 'dart2js.dart' show AbortLeg;
+import 'filenames.dart';
+import 'io/source_file.dart';
+import 'util/uri_extras.dart';
 
 List<int> readAll(String filename) {
   var file = (new File(filename)).openSync();
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index a05158d..acfdef0 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -18,9 +18,9 @@
 import '../core_types.dart' show CoreClasses;
 import '../dart_types.dart';
 import '../diagnostics/messages.dart' show Message, MessageTemplate;
+import '../dump_info.dart' show InfoReporter;
 import '../elements/elements.dart';
-import '../elements/modelx.dart'
-    show ConstructorBodyElementX, ElementX, VariableElementX;
+import '../elements/modelx.dart' show ConstructorBodyElementX;
 import '../io/source_information.dart';
 import '../js/js.dart' as js;
 import '../js_backend/backend_helpers.dart' show BackendHelpers;
@@ -37,11 +37,9 @@
 import '../universe/side_effects.dart' show SideEffects;
 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
 import '../util/util.dart';
-import '../world.dart' show ClassWorld, World;
-import '../dump_info.dart' show InfoReporter;
-
-import 'nodes.dart';
+import '../world.dart' show ClassWorld;
 import 'codegen.dart';
+import 'nodes.dart';
 import 'optimize.dart';
 import 'types.dart';
 
@@ -109,7 +107,7 @@
       return reporter.withCurrentElement(element, () {
         SsaBuilder builder = new SsaBuilder(
             work.element.implementation,
-            work.resolutionTree,
+            work.resolvedAst,
             work.compilationContext,
             work.registry,
             backend,
@@ -326,11 +324,11 @@
    *
    * Invariant: [function] must be an implementation element.
    */
-  void startFunction(Element element, ast.Node node) {
+  void startFunction(AstElement element, ast.Node node) {
     assert(invariant(element, element.isImplementation));
     Compiler compiler = builder.compiler;
-    closureData = compiler.closureToClassMapper
-        .computeClosureToClassMapping(element, node, builder.elements);
+    closureData = compiler.closureToClassMapper.computeClosureToClassMapping(
+        compiler.backend.frontend.getResolvedAst(element.declaration));
 
     if (element is FunctionElement) {
       FunctionElement functionElement = element;
@@ -459,7 +457,8 @@
           builder.reporter.internalError(builder.compiler.currentElement,
               "Runtime type information not available for $local.");
         } else {
-          builder.reporter.internalError(local, "Cannot find value $local.");
+          builder.reporter.internalError(
+              local, "Cannot find value $local in ${directLocals.keys}.");
         }
       }
       HInstruction value = directLocals[local];
@@ -1005,8 +1004,7 @@
   /// The element for which this SSA builder is being used.
   final Element target;
 
-  /// Reference to resolved elements in [target]'s AST.
-  TreeElements elements;
+  ResolvedAst resolvedAst;
 
   /// Used to report information about inlining (which occurs while building the
   /// SSA graph), when dump-info is enabled.
@@ -1120,7 +1118,7 @@
   // TODO(sigmund): make most args optional
   SsaBuilder(
       this.target,
-      this.elements,
+      this.resolvedAst,
       this.context,
       this.registry,
       JavaScriptBackend backend,
@@ -1149,6 +1147,9 @@
 
   CoreClasses get coreClasses => compiler.coreClasses;
 
+  /// Reference to resolved elements in [target]'s AST.
+  TreeElements get elements => resolvedAst.elements;
+
   @override
   SemanticSendVisitor get sendVisitor => this;
 
@@ -1377,6 +1378,7 @@
     if (compiler.elementHasCompileTimeError(element)) return false;
 
     FunctionElement function = element;
+    ResolvedAst functionResolvedAst = backend.frontend.getResolvedAst(function);
     bool insideLoop = loopNesting > 0 || graph.calledInLoop;
 
     // Bail out early if the inlining decision is in the cache and we can't
@@ -1436,7 +1438,7 @@
 
     bool doesNotContainCode() {
       // A function with size 1 does not contain any code.
-      return InlineWeeder.canBeInlined(function, 1, true,
+      return InlineWeeder.canBeInlined(functionResolvedAst, 1, true,
           enableUserAssertions: compiler.options.enableUserAssertions);
     }
 
@@ -1444,7 +1446,7 @@
       // The call is on a path which is executed rarely, so inline only if it
       // does not make the program larger.
       if (isCalledOnce(element)) {
-        return InlineWeeder.canBeInlined(function, -1, false,
+        return InlineWeeder.canBeInlined(functionResolvedAst, -1, false,
             enableUserAssertions: compiler.options.enableUserAssertions);
       }
       // TODO(sra): Measure if inlining would 'reduce' the size.  One desirable
@@ -1482,7 +1484,7 @@
       if (cachedCanBeInlined == true) {
         // We may have forced the inlining of some methods. Therefore check
         // if we can inline this method regardless of size.
-        assert(InlineWeeder.canBeInlined(function, -1, false,
+        assert(InlineWeeder.canBeInlined(functionResolvedAst, -1, false,
             allowLoops: true,
             enableUserAssertions: compiler.options.enableUserAssertions));
         return true;
@@ -1507,7 +1509,7 @@
       }
       bool canInline;
       canInline = InlineWeeder.canBeInlined(
-          function, maxInliningNodes, useMaxInliningNodes,
+          functionResolvedAst, maxInliningNodes, useMaxInliningNodes,
           enableUserAssertions: compiler.options.enableUserAssertions);
       if (canInline) {
         backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop);
@@ -1531,7 +1533,7 @@
       }
       List<HInstruction> compiledArguments = completeSendArgumentsList(
           function, selector, providedArguments, currentNode);
-      enterInlinedMethod(function, currentNode, compiledArguments,
+      enterInlinedMethod(function, functionResolvedAst, compiledArguments,
           instanceType: instanceType);
       inlinedFrom(function, () {
         if (!isReachable) {
@@ -1678,7 +1680,7 @@
   HGraph buildMethod(FunctionElement functionElement) {
     assert(invariant(functionElement, functionElement.isImplementation));
     graph.calledInLoop = compiler.world.isCalledInLoop(functionElement);
-    ast.FunctionExpression function = functionElement.node;
+    ast.FunctionExpression function = resolvedAst.node;
     assert(function != null);
     assert(elements.getFunctionDefinition(function) != null);
     openFunction(functionElement, function);
@@ -1832,9 +1834,12 @@
   void setupStateForInlining(
       FunctionElement function, List<HInstruction> compiledArguments,
       {InterfaceType instanceType}) {
+    ResolvedAst resolvedAst =
+        compiler.backend.frontend.getResolvedAst(function.declaration);
+    assert(resolvedAst != null);
     localsHandler = new LocalsHandler(this, function, instanceType);
-    localsHandler.closureData = compiler.closureToClassMapper
-        .computeClosureToClassMapping(function, function.node, elements);
+    localsHandler.closureData =
+        compiler.closureToClassMapper.computeClosureToClassMapping(resolvedAst);
     returnLocal = new SyntheticLocal("result", function);
     localsHandler.updateLocal(returnLocal, graph.addConstantNull(compiler));
 
@@ -1863,8 +1868,6 @@
     }
     assert(argumentIndex == compiledArguments.length);
 
-    elements = function.resolvedAst.elements;
-    assert(elements != null);
     returnType = signature.type.returnType;
     stack = <HInstruction>[];
 
@@ -1876,7 +1879,7 @@
     localsHandler = state.oldLocalsHandler;
     returnLocal = state.oldReturnLocal;
     inTryStatement = state.inTryStatement;
-    elements = state.oldElements;
+    resolvedAst = state.oldResolvedAst;
     returnType = state.oldReturnType;
     assert(stack.isEmpty);
     stack = state.oldStack;
@@ -2007,21 +2010,69 @@
       });
 
       // Build the initializers in the context of the new constructor.
-      TreeElements oldElements = elements;
-      ResolvedAst resolvedAst = callee.resolvedAst;
-      elements = resolvedAst.elements;
+      ResolvedAst oldResolvedAst = resolvedAst;
+      resolvedAst = backend.frontend.getResolvedAst(callee);
       ClosureClassMap oldClosureData = localsHandler.closureData;
-      ast.Node node = resolvedAst.node;
       ClosureClassMap newClosureData = compiler.closureToClassMapper
-          .computeClosureToClassMapping(callee, node, elements);
+          .computeClosureToClassMapping(resolvedAst);
       localsHandler.closureData = newClosureData;
-      localsHandler.enterScope(node, callee);
+      if (resolvedAst.kind == ResolvedAstKind.PARSED) {
+        localsHandler.enterScope(resolvedAst.node, callee);
+      }
       buildInitializers(callee, constructors, fieldValues);
       localsHandler.closureData = oldClosureData;
-      elements = oldElements;
+      resolvedAst = oldResolvedAst;
     });
   }
 
+  void buildInitializers(
+      ConstructorElement constructor,
+      List<FunctionElement> constructors,
+      Map<Element, HInstruction> fieldValues) {
+    assert(invariant(
+        constructor, resolvedAst.element == constructor.declaration,
+        message: "Expected ResolvedAst for $constructor, found $resolvedAst"));
+    if (resolvedAst.kind == ResolvedAstKind.PARSED) {
+      buildParsedInitializers(constructor, constructors, fieldValues);
+    } else {
+      buildSynthesizedConstructorInitializers(
+          constructor, constructors, fieldValues);
+    }
+  }
+
+  void buildSynthesizedConstructorInitializers(
+      ConstructorElement constructor,
+      List<FunctionElement> constructors,
+      Map<Element, HInstruction> fieldValues) {
+    assert(invariant(constructor, constructor.isSynthesized));
+    List<HInstruction> arguments = <HInstruction>[];
+    HInstruction compileArgument(ParameterElement parameter) {
+      return localsHandler.readLocal(parameter);
+    }
+
+    Element target = constructor.definingConstructor.implementation;
+    bool match = !target.isMalformed &&
+        CallStructure.addForwardingElementArgumentsToList(
+            constructor,
+            arguments,
+            target,
+            compileArgument,
+            handleConstantForOptionalParameter);
+    if (!match) {
+      if (compiler.elementHasCompileTimeError(constructor)) {
+        return;
+      }
+      // If this fails, the selector we constructed for the call to a
+      // forwarding constructor in a mixin application did not match the
+      // constructor (which, for example, may happen when the libraries are
+      // not compatible for private names, see issue 20394).
+      reporter.internalError(
+          constructor, 'forwarding constructor call does not match');
+    }
+    inlineSuperOrRedirect(
+        target, arguments, constructors, fieldValues, constructor);
+  }
+
   /**
    * Run through the initializers and inline all field initializers. Recursively
    * inlines super initializers.
@@ -2032,40 +2083,13 @@
    * Invariant: The [constructor] and elements in [constructors] must all be
    * implementation elements.
    */
-  void buildInitializers(
+  void buildParsedInitializers(
       ConstructorElement constructor,
       List<FunctionElement> constructors,
       Map<Element, HInstruction> fieldValues) {
     assert(invariant(constructor, constructor.isImplementation));
-    if (constructor.isSynthesized) {
-      List<HInstruction> arguments = <HInstruction>[];
-      HInstruction compileArgument(ParameterElement parameter) {
-        return localsHandler.readLocal(parameter);
-      }
-
-      Element target = constructor.definingConstructor.implementation;
-      bool match = !target.isMalformed &&
-          CallStructure.addForwardingElementArgumentsToList(
-              constructor,
-              arguments,
-              target,
-              compileArgument,
-              handleConstantForOptionalParameter);
-      if (!match) {
-        if (compiler.elementHasCompileTimeError(constructor)) {
-          return;
-        }
-        // If this fails, the selector we constructed for the call to a
-        // forwarding constructor in a mixin application did not match the
-        // constructor (which, for example, may happen when the libraries are
-        // not compatible for private names, see issue 20394).
-        reporter.internalError(
-            constructor, 'forwarding constructor call does not match');
-      }
-      inlineSuperOrRedirect(
-          target, arguments, constructors, fieldValues, constructor);
-      return;
-    }
+    assert(invariant(constructor, !constructor.isSynthesized,
+        message: "Unexpected synthesized constructor: $constructor"));
     ast.FunctionExpression functionNode = constructor.node;
 
     bool foundSuperOrRedirect = false;
@@ -2143,7 +2167,6 @@
         (ClassElement enclosingClass, VariableElement member) {
       if (compiler.elementHasCompileTimeError(member)) return;
       reporter.withCurrentElement(member, () {
-        TreeElements definitions = member.treeElements;
         ast.Node node = member.node;
         ast.Expression initializer = member.initializer;
         if (initializer == null) {
@@ -2154,14 +2177,14 @@
           }
         } else {
           ast.Node right = initializer;
-          TreeElements savedElements = elements;
-          elements = definitions;
+          ResolvedAst savedResolvedAst = resolvedAst;
+          resolvedAst = backend.frontend.getResolvedAst(member);
           // In case the field initializer uses closures, run the
           // closure to class mapper.
           compiler.closureToClassMapper
-              .computeClosureToClassMapping(member, node, elements);
+              .computeClosureToClassMapping(resolvedAst);
           inlinedFrom(member, () => right.accept(this));
-          elements = savedElements;
+          resolvedAst = savedResolvedAst;
           fieldValues[member] = pop();
         }
       });
@@ -2362,7 +2385,7 @@
         bodyCallInputs.add(interceptor);
       }
       bodyCallInputs.add(newObject);
-      ResolvedAst resolvedAst = constructor.resolvedAst;
+      ResolvedAst resolvedAst = backend.frontend.getResolvedAst(constructor);
       ast.Node node = resolvedAst.node;
       ClosureClassMap parameterClosureData =
           compiler.closureToClassMapper.getMappingForNestedFunction(node);
@@ -3436,8 +3459,6 @@
   /// Generate read access of an unresolved static or top level entity.
   void generateStaticUnresolvedGet(ast.Send node, Element element) {
     if (element is ErroneousElement) {
-      SourceInformation sourceInformation =
-          sourceInformationBuilder.buildGet(node);
       // An erroneous element indicates an unresolved static getter.
       handleInvalidStaticGet(node, element);
     } else {
@@ -4015,8 +4036,9 @@
       reporter.internalError(
           node.argumentsNode, 'At least two arguments expected.');
     }
-    native.NativeBehavior nativeBehavior =
-        compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
+    native.NativeBehavior nativeBehavior = elements.getNativeData(node);
+    assert(invariant(node, nativeBehavior != null,
+        message: "No NativeBehavior for $node"));
 
     List<HInstruction> inputs = <HInstruction>[];
     addGenericSendArgumentsToList(link.tail.tail, inputs);
@@ -4183,8 +4205,9 @@
       compiledArguments.add(pop());
     }
 
-    native.NativeBehavior nativeBehavior =
-        compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
+    native.NativeBehavior nativeBehavior = elements.getNativeData(node);
+    assert(invariant(node, nativeBehavior != null,
+        message: "No NativeBehavior for $node"));
 
     TypeMask ssaType =
         TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler);
@@ -4228,8 +4251,9 @@
     String globalName = constant.primitiveValue.slowToString();
     js.Template expr = js.js.expressionTemplateYielding(
         backend.emitter.generateEmbeddedGlobalAccess(globalName));
-    native.NativeBehavior nativeBehavior =
-        compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
+    native.NativeBehavior nativeBehavior = elements.getNativeData(node);
+    assert(invariant(node, nativeBehavior != null,
+        message: "No NativeBehavior for $node"));
     TypeMask ssaType =
         TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler);
     push(new HForeignCode(expr, ssaType, const [],
@@ -4866,10 +4890,10 @@
         constructorDeclaration == helpers.jsArrayTypedConstructor;
 
     if (isSymbolConstructor) {
-      constructor = compiler.symbolValidatedConstructor;
+      constructor = helpers.symbolValidatedConstructor;
       assert(invariant(send, constructor != null,
           message: 'Constructor Symbol.validated is missing'));
-      callStructure = compiler.symbolValidatedConstructorSelector.callStructure;
+      callStructure = helpers.symbolValidatedConstructorSelector.callStructure;
       assert(invariant(send, callStructure != null,
           message: 'Constructor Symbol.validated is missing'));
     }
@@ -5524,17 +5548,10 @@
     }
   }
 
-  bool _hasNamedParameters(FunctionElement function) {
-    FunctionSignature params = function.functionSignature;
-    return params.optionalParameterCount > 0 &&
-        params.optionalParametersAreNamed;
-  }
-
   HForeignCode invokeJsInteropFunction(FunctionElement element,
       List<HInstruction> arguments, SourceInformation sourceInformation) {
     assert(backend.isJsInterop(element));
     nativeEmitter.nativeMethods.add(element);
-    String templateString;
 
     if (element.isFactoryConstructor &&
         backend.jsInteropAnalysis
@@ -6583,7 +6600,7 @@
 
     int position = 0;
 
-    for (ParameterElement targetParameter in targetRequireds) {
+    for (ParameterElement _ in targetRequireds) {
       loadPosition(position++, null);
     }
 
@@ -6905,7 +6922,6 @@
     // method is inlined.  We would require full scalar replacement in that
     // case.
 
-    Selector selector = Selectors.iterator;
     TypeMask mask = elements.getIteratorTypeMask(node);
 
     ClassWorld classWorld = compiler.world;
@@ -7869,18 +7885,19 @@
    * This method is invoked before inlining the body of [function] into this
    * [SsaBuilder].
    */
-  void enterInlinedMethod(FunctionElement function, ast.Node _,
-      List<HInstruction> compiledArguments,
+  void enterInlinedMethod(FunctionElement function,
+      ResolvedAst functionResolvedAst, List<HInstruction> compiledArguments,
       {InterfaceType instanceType}) {
     AstInliningState state = new AstInliningState(
         function,
         returnLocal,
         returnType,
-        elements,
+        resolvedAst,
         stack,
         localsHandler,
         inTryStatement,
         allInlinedFunctionsCalledOnce && isFunctionCalledOnce(function));
+    resolvedAst = functionResolvedAst;
     inliningStack.add(state);
 
     // Setting up the state of the (AST) builder is performed even when the
@@ -8077,14 +8094,14 @@
       this.enableUserAssertions);
 
   static bool canBeInlined(
-      FunctionElement function, int maxInliningNodes, bool useMaxInliningNodes,
+      ResolvedAst resolvedAst, int maxInliningNodes, bool useMaxInliningNodes,
       {bool allowLoops: false, bool enableUserAssertions: null}) {
     assert(enableUserAssertions is bool); // Ensure we passed it.
-    if (function.resolvedAst.elements.containsTryStatement) return false;
+    if (resolvedAst.elements.containsTryStatement) return false;
 
     InlineWeeder weeder = new InlineWeeder(maxInliningNodes,
         useMaxInliningNodes, allowLoops, enableUserAssertions);
-    ast.FunctionExpression functionExpression = function.node;
+    ast.FunctionExpression functionExpression = resolvedAst.node;
     weeder.visit(functionExpression.initializers);
     weeder.visit(functionExpression.body);
     weeder.visit(functionExpression.asyncModifier);
@@ -8196,7 +8213,7 @@
 class AstInliningState extends InliningState {
   final Local oldReturnLocal;
   final DartType oldReturnType;
-  final TreeElements oldElements;
+  final ResolvedAst oldResolvedAst;
   final List<HInstruction> oldStack;
   final LocalsHandler oldLocalsHandler;
   final bool inTryStatement;
@@ -8206,7 +8223,7 @@
       FunctionElement function,
       this.oldReturnLocal,
       this.oldReturnType,
-      this.oldElements,
+      this.oldResolvedAst,
       this.oldStack,
       this.oldLocalsHandler,
       this.inTryStatement,
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 3a5d85a..5938e1c 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -15,17 +15,16 @@
 import '../js/js.dart' as js;
 import '../js_backend/backend_helpers.dart' show BackendHelpers;
 import '../js_backend/js_backend.dart';
-import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter;
+import '../js_emitter/js_emitter.dart' show NativeEmitter;
 import '../native/native.dart' as native;
 import '../types/types.dart';
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
 import '../util/util.dart';
-import '../world.dart' show ClassWorld, World;
-
-import 'nodes.dart';
+import '../world.dart' show ClassWorld;
 import 'codegen_helpers.dart';
+import 'nodes.dart';
 import 'variable_allocator.dart';
 
 class SsaCodeGeneratorTask extends CompilerTask {
@@ -40,7 +39,8 @@
   NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter;
 
   js.Fun buildJavaScriptFunction(
-      FunctionElement element, List<js.Parameter> parameters, js.Block body) {
+      ResolvedAst resolvedAst, List<js.Parameter> parameters, js.Block body) {
+    FunctionElement element = resolvedAst.element;
     js.AsyncModifier asyncModifier = element.asyncMarker.isAsync
         ? (element.asyncMarker.isYielding
             ? const js.AsyncModifier.asyncStar()
@@ -51,8 +51,8 @@
 
     return new js.Fun(parameters, body, asyncModifier: asyncModifier)
         .withSourceInformation(sourceInformationFactory
-            .createBuilderForContext(element)
-            .buildDeclaration(element));
+            .createBuilderForContext(resolvedAst.element)
+            .buildDeclaration(resolvedAst));
   }
 
   js.Expression generateCode(CodegenWorkItem work, HGraph graph) {
@@ -63,12 +63,12 @@
     }
   }
 
-  js.Expression generateLazyInitializer(work, graph) {
+  js.Expression generateLazyInitializer(CodegenWorkItem work, HGraph graph) {
     return measure(() {
       compiler.tracer.traceGraph("codegen", graph);
       SourceInformation sourceInformation = sourceInformationFactory
           .createBuilderForContext(work.element)
-          .buildDeclaration(work.element);
+          .buildDeclaration(work.resolvedAst);
       SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work);
       codegen.visitGraph(graph);
       return new js.Fun(codegen.parameters, codegen.body)
@@ -85,7 +85,8 @@
       SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work);
       codegen.visitGraph(graph);
       compiler.tracer.traceGraph("codegen", graph);
-      return buildJavaScriptFunction(element, codegen.parameters, codegen.body);
+      return buildJavaScriptFunction(
+          work.resolvedAst, codegen.parameters, codegen.body);
     });
   }
 }
@@ -1613,7 +1614,6 @@
     var isolate = new js.VariableUse(
         backend.namer.globalObjectFor(helpers.interceptorsLibrary));
     Selector selector = node.selector;
-    TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask);
     js.Name methodName = backend.registerOneShotInterceptor(selector);
     push(js
         .propertyCall(isolate, methodName, arguments)
@@ -2182,15 +2182,12 @@
       {SourceInformation sourceInformation}) {
     js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper);
     List arguments = [];
-    var location;
     if (argument is List) {
-      location = argument[0];
       argument.forEach((instruction) {
         use(instruction);
         arguments.add(pop());
       });
     } else {
-      location = argument;
       use(argument);
       arguments.add(pop());
     }
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index 1777d96..3249c31 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.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.
 
-import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
+import '../common/codegen.dart' show CodegenWorkItem;
 import '../compiler.dart' show Compiler;
 import '../constants/constant_system.dart';
 import '../constants/values.dart';
@@ -11,8 +11,7 @@
 import '../js_backend/js_backend.dart';
 import '../types/types.dart';
 import '../universe/selector.dart' show Selector;
-import '../world.dart' show ClassWorld, World;
-
+import '../world.dart' show ClassWorld;
 import 'nodes.dart';
 import 'optimize.dart';
 
diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
index ff565f9..cf05b2e 100644
--- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
+++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
@@ -8,10 +8,9 @@
 import '../elements/elements.dart';
 import '../js_backend/js_backend.dart';
 import '../types/types.dart';
-import '../universe/selector.dart';
 import '../universe/call_structure.dart';
-import '../world.dart' show ClassWorld, World;
-
+import '../universe/selector.dart';
+import '../world.dart' show World;
 import 'nodes.dart';
 import 'types.dart';
 
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index a779457..4b55e48 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -20,10 +20,9 @@
 import '../universe/selector.dart' show Selector;
 import '../universe/side_effects.dart' show SideEffects;
 import '../util/util.dart';
-import '../world.dart' show ClassWorld, World;
-
-import 'validate.dart';
+import '../world.dart' show ClassWorld;
 import 'invoke_dynamic_specializers.dart';
+import 'validate.dart';
 
 abstract class HVisitor<R> {
   R visitAdd(HAdd node);
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 4f67597..7d01871 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.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.
 
-import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
+import '../common/codegen.dart' show CodegenWorkItem;
 import '../common/tasks.dart' show CompilerTask;
 import '../compiler.dart' show Compiler;
 import '../constants/constant_system.dart';
@@ -20,13 +20,12 @@
 import '../universe/side_effects.dart' show SideEffects;
 import '../util/util.dart';
 import '../world.dart' show ClassWorld, World;
-
+import 'interceptor_simplifier.dart';
 import 'nodes.dart';
-import 'types_propagation.dart';
 import 'types.dart';
+import 'types_propagation.dart';
 import 'value_range_analyzer.dart';
 import 'value_set.dart';
-import 'interceptor_simplifier.dart';
 
 abstract class OptimizationPhase {
   String get name;
diff --git a/pkg/compiler/lib/src/ssa/types.dart b/pkg/compiler/lib/src/ssa/types.dart
index 2a7ecff..7efebe7 100644
--- a/pkg/compiler/lib/src/ssa/types.dart
+++ b/pkg/compiler/lib/src/ssa/types.dart
@@ -10,7 +10,7 @@
 import '../tree/tree.dart' as ast;
 import '../types/types.dart';
 import '../universe/selector.dart' show Selector;
-import '../world.dart' show ClassWorld, World;
+import '../world.dart' show ClassWorld;
 
 class TypeMaskFactory {
   static TypeMask fromInferredType(TypeMask mask, Compiler compiler) {
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index e5ad513..64e4c30 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -7,8 +7,7 @@
 import '../js_backend/js_backend.dart';
 import '../types/types.dart';
 import '../universe/selector.dart' show Selector;
-import '../world.dart' show ClassWorld, World;
-
+import '../world.dart' show ClassWorld;
 import 'nodes.dart';
 import 'optimize.dart';
 
diff --git a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
index 8893e90..c811c71 100644
--- a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
+++ b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
@@ -2,13 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
+import '../common/codegen.dart' show CodegenWorkItem;
 import '../compiler.dart' show Compiler;
 import '../constant_system_dart.dart';
 import '../constants/constant_system.dart';
 import '../constants/values.dart';
 import '../js_backend/js_backend.dart';
-
 import 'nodes.dart';
 import 'optimize.dart';
 
diff --git a/pkg/compiler/lib/src/tree/nodes.dart b/pkg/compiler/lib/src/tree/nodes.dart
index 9335fef..ae8111b 100644
--- a/pkg/compiler/lib/src/tree/nodes.dart
+++ b/pkg/compiler/lib/src/tree/nodes.dart
@@ -5,15 +5,14 @@
 import 'dart:collection' show IterableMixin;
 
 import '../common.dart';
-import '../tokens/precedence_constants.dart' as Precedence show FUNCTION_INFO;
-import '../tokens/token.dart' show BeginGroupToken, Token;
-import '../tokens/token_constants.dart' as Tokens
-    show IDENTIFIER_TOKEN, KEYWORD_TOKEN, PLUS_TOKEN;
-import '../util/util.dart';
-import '../util/characters.dart';
+import '../elements/elements.dart' show MetadataAnnotation;
 import '../resolution/secret_tree_element.dart'
     show NullTreeElementMixin, StoredTreeElementMixin;
-import '../elements/elements.dart' show MetadataAnnotation;
+import '../tokens/precedence_constants.dart' as Precedence show FUNCTION_INFO;
+import '../tokens/token.dart' show BeginGroupToken, Token;
+import '../tokens/token_constants.dart' as Tokens show PLUS_TOKEN;
+import '../util/characters.dart';
+import '../util/util.dart';
 import 'dartstring.dart';
 import 'prettyprint.dart';
 import 'unparser.dart';
@@ -1737,8 +1736,9 @@
 
 class TypeVariable extends Node {
   final Identifier name;
+  final Token extendsOrSuper;
   final TypeAnnotation bound;
-  TypeVariable(Identifier this.name, TypeAnnotation this.bound);
+  TypeVariable(this.name, this.extendsOrSuper, this.bound);
 
   accept(Visitor visitor) => visitor.visitTypeVariable(this);
 
diff --git a/pkg/compiler/lib/src/tree/prettyprint.dart b/pkg/compiler/lib/src/tree/prettyprint.dart
index dceffaf..837db37 100644
--- a/pkg/compiler/lib/src/tree/prettyprint.dart
+++ b/pkg/compiler/lib/src/tree/prettyprint.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.
 
-import '../tokens/token.dart' show BeginGroupToken, Token;
+import '../tokens/token.dart' show Token;
 import '../util/util.dart';
 import 'nodes.dart';
 
diff --git a/pkg/compiler/lib/src/tree/unparser.dart b/pkg/compiler/lib/src/tree/unparser.dart
index bb1d38e..37838eb 100644
--- a/pkg/compiler/lib/src/tree/unparser.dart
+++ b/pkg/compiler/lib/src/tree/unparser.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.
 
-import '../tokens/token.dart' show BeginGroupToken, Token;
+import '../tokens/token.dart' show Token;
 import '../tokens/token_constants.dart' as Tokens
     show IDENTIFIER_TOKEN, KEYWORD_TOKEN, PLUS_TOKEN;
 import '../util/util.dart';
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
index 39b4bb1..effd18d 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
@@ -587,7 +587,6 @@
     return 'Await($value)';
   }
 
-  @override
   String visitYield(Yield node) {
     String value = visitExpression(node.input);
     return 'Yield($value)';
diff --git a/pkg/compiler/lib/src/typechecker.dart b/pkg/compiler/lib/src/typechecker.dart
index 9593b10..e186ee4 100644
--- a/pkg/compiler/lib/src/typechecker.dart
+++ b/pkg/compiler/lib/src/typechecker.dart
@@ -4,10 +4,10 @@
 
 library dart2js.typechecker;
 
-import 'common.dart';
 import 'common/names.dart' show Identifiers;
 import 'common/resolution.dart' show Resolution;
 import 'common/tasks.dart' show CompilerTask;
+import 'common.dart';
 import 'compiler.dart' show Compiler;
 import 'constants/expressions.dart';
 import 'constants/values.dart';
@@ -30,7 +30,6 @@
         GetterElement,
         InitializingFormalElement,
         LibraryElement,
-        Member,
         MemberSignature,
         Name,
         ParameterElement,
@@ -40,10 +39,9 @@
         SetterElement,
         TypeDeclarationElement,
         TypedElement,
-        TypedefElement,
         VariableElement;
-import 'resolution/tree_elements.dart' show TreeElements;
 import 'resolution/class_members.dart' show MembersCreator;
+import 'resolution/tree_elements.dart' show TreeElements;
 import 'tree/tree.dart';
 import 'util/util.dart' show Link, LinkBuilder;
 
diff --git a/pkg/compiler/lib/src/universe/call_structure.dart b/pkg/compiler/lib/src/universe/call_structure.dart
index fb9c908..84c0a62 100644
--- a/pkg/compiler/lib/src/universe/call_structure.dart
+++ b/pkg/compiler/lib/src/universe/call_structure.dart
@@ -5,11 +5,10 @@
 library dart2js.call_structure;
 
 import '../common.dart';
-import '../common/names.dart' show Identifiers, Names, Selectors;
+import '../common/names.dart' show Names;
 import '../elements/elements.dart';
 import '../tree/tree.dart';
 import '../util/util.dart';
-
 import 'selector.dart' show Selector;
 
 /// The structure of the arguments at a call-site.
diff --git a/pkg/compiler/lib/src/universe/side_effects.dart b/pkg/compiler/lib/src/universe/side_effects.dart
index 2c39999..280d56a 100644
--- a/pkg/compiler/lib/src/universe/side_effects.dart
+++ b/pkg/compiler/lib/src/universe/side_effects.dart
@@ -33,6 +33,8 @@
     clearAllSideEffects();
   }
 
+  SideEffects.fromFlags(this._flags);
+
   bool operator ==(other) => _flags == other._flags;
 
   int get hashCode => throw new UnsupportedError('SideEffects.hashCode');
@@ -147,6 +149,8 @@
     _flags = other._flags;
   }
 
+  int get flags => _flags;
+
   String toString() {
     StringBuffer buffer = new StringBuffer();
     buffer.write('Depends on');
diff --git a/pkg/compiler/lib/src/universe/world_impact.dart b/pkg/compiler/lib/src/universe/world_impact.dart
index 45dcba5..1ba0ab7 100644
--- a/pkg/compiler/lib/src/universe/world_impact.dart
+++ b/pkg/compiler/lib/src/universe/world_impact.dart
@@ -4,10 +4,8 @@
 
 library dart2js.universe.world_impact;
 
-import '../elements/elements.dart'
-    show Element, LocalFunctionElement, MethodElement;
+import '../elements/elements.dart' show Element;
 import '../util/util.dart' show Setlet;
-
 import 'use.dart' show DynamicUse, StaticUse, TypeUse;
 
 class WorldImpact {
diff --git a/pkg/compiler/samples/darttags/darttags.dart b/pkg/compiler/samples/darttags/darttags.dart
index 0333c69..d77966d 100644
--- a/pkg/compiler/samples/darttags/darttags.dart
+++ b/pkg/compiler/samples/darttags/darttags.dart
@@ -29,20 +29,16 @@
 // Where DART_LOCATION is the gclient directory where you found .gclient.
 
 import 'dart:io';
-
 import 'dart:mirrors';
 
-import 'package:sdk_library_metadata/libraries.dart'
-    show libraries, LibraryInfo;
-
-import 'package:compiler/src/mirrors/analyze.dart' show analyze;
-import 'package:compiler/src/mirrors/dart2js_mirrors.dart' show BackDoor;
-import 'package:compiler/src/mirrors/mirrors_util.dart' show nameOf;
-
 import 'package:compiler/src/filenames.dart';
 import 'package:compiler/src/io/source_file.dart';
+import 'package:compiler/src/mirrors/analyze.dart' show analyze;
+import 'package:compiler/src/mirrors/dart2js_mirrors.dart' show BackDoor;
+import 'package:compiler/src/mirrors/mirrors_util.dart' show nameOf;
 import 'package:compiler/src/source_file_provider.dart';
 import 'package:compiler/src/util/uri_extras.dart';
+import 'package:sdk_library_metadata/libraries.dart' show libraries;
 
 const DART2JS = 'package:compiler/src/dart2js.dart';
 const DART2JS_MIRROR = 'package:compiler/src/mirrors/dart2js_mirrors.dart';
diff --git a/pkg/compiler/samples/jsonify/jsonify.dart b/pkg/compiler/samples/jsonify/jsonify.dart
index db8020d..a84cb04 100644
--- a/pkg/compiler/samples/jsonify/jsonify.dart
+++ b/pkg/compiler/samples/jsonify/jsonify.dart
@@ -3,18 +3,15 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:io';
 import 'dart:convert';
-
+import 'dart:io';
 import 'dart:mirrors';
 
-import 'package:sdk_library_metadata/libraries.dart'
-    show libraries, LibraryInfo;
-
-import '../../lib/src/mirrors/analyze.dart' show analyze;
-import '../../lib/src/mirrors/dart2js_mirrors.dart' show BackDoor;
+import 'package:sdk_library_metadata/libraries.dart' show libraries;
 
 import '../../lib/src/filenames.dart';
+import '../../lib/src/mirrors/analyze.dart' show analyze;
+import '../../lib/src/mirrors/dart2js_mirrors.dart' show BackDoor;
 import '../../lib/src/source_file_provider.dart';
 import '../../lib/src/util/uri_extras.dart';
 
diff --git a/pkg/dart2js_incremental/lib/library_updater.dart b/pkg/dart2js_incremental/lib/library_updater.dart
index a5cdc02..7994891 100644
--- a/pkg/dart2js_incremental/lib/library_updater.dart
+++ b/pkg/dart2js_incremental/lib/library_updater.dart
@@ -683,7 +683,7 @@
       PartialFunctionElement before,
       PartialFunctionElement after) {
     FunctionExpression node =
-        after.parseNode(compiler.parsing).asFunctionExpression();
+        after.parseNode(compiler.parsingContext).asFunctionExpression();
     if (node == null) {
       return cannotReuse(after, "Not a function expression: '$node'");
     }
@@ -705,7 +705,7 @@
       Token diffToken,
       PartialClassElement before,
       PartialClassElement after) {
-    ClassNode node = after.parseNode(compiler.parsing).asClassNode();
+    ClassNode node = after.parseNode(compiler.parsingContext).asClassNode();
     if (node == null) {
       return cannotReuse(after, "Not a ClassNode: '$node'");
     }
diff --git a/pkg/fixnum/LICENSE b/pkg/fixnum/LICENSE
deleted file mode 100644
index 5c60afe..0000000
--- a/pkg/fixnum/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright 2014, the Dart project authors. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-    * Neither the name of Google Inc. nor the names of its
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/fixnum/README.md b/pkg/fixnum/README.md
deleted file mode 100644
index 81f6467..0000000
--- a/pkg/fixnum/README.md
+++ /dev/null
@@ -1,22 +0,0 @@
-fixnum
-======
-
-A fixed-size integer library for Dart.
-- - -
-The fixnum package provides data types for signed 32- and 64-bit integers.
-The integer implementations in this library are designed to work identically
-whether executed on the Dart VM or compiled to JavaScript.
-
-Installing
-----------
-
-Use [pub](http://pub.dartlang.org) to install this package. Add the following
-to your `pubspec.yaml` file:
-
-    dependencies:
-      fixnum: any
-
-Then run `pub install`.
-
-For more information, see the
-[fixnum package on pub.dartlang.org](http://pub.dartlang.org/packages/fixnum).
diff --git a/pkg/fixnum/lib/fixnum.dart b/pkg/fixnum/lib/fixnum.dart
deleted file mode 100644
index fe21c47..0000000
--- a/pkg/fixnum/lib/fixnum.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/**
- * Signed 32- and 64-bit integer support.
- *
- * The integer implementations in this library are designed to work
- * identically whether executed on the Dart VM or compiled to JavaScript.
- *
- * For information on installing and importing this library, see the
- * [fixnum package on pub.dartlang.org]
- * (http://pub.dartlang.org/packages/fixnum).
- */
-library fixnum;
-
-part 'src/intx.dart';
-part 'src/int32.dart';
-part 'src/int64.dart';
diff --git a/pkg/fixnum/lib/src/int32.dart b/pkg/fixnum/lib/src/int32.dart
deleted file mode 100644
index 8e0dcca..0000000
--- a/pkg/fixnum/lib/src/int32.dart
+++ /dev/null
@@ -1,380 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of fixnum;
-
-/**
- * An immutable 32-bit signed integer, in the range [-2^31, 2^31 - 1].
- * Arithmetic operations may overflow in order to maintain this range.
- */
-class Int32 implements IntX {
-
-  /**
-   * The maximum positive value attainable by an [Int32], namely
-   * 2147483647.
-   */
-  static const Int32 MAX_VALUE = const Int32._internal(0x7FFFFFFF);
-
-  /**
-   * The minimum positive value attainable by an [Int32], namely
-   * -2147483648.
-   */
-  static const Int32 MIN_VALUE = const Int32._internal(-0x80000000);
-
-  /**
-   * An [Int32] constant equal to 0.
-   */
-  static const Int32 ZERO = const Int32._internal(0);
-
-  /**
-   * An [Int32] constant equal to 1.
-   */
-  static const Int32 ONE = const Int32._internal(1);
-
-  /**
-   * An [Int32] constant equal to 2.
-   */
-  static const Int32 TWO = const Int32._internal(2);
-
-  // Hex digit char codes
-  static const int _CC_0 = 48; // '0'.codeUnitAt(0)
-  static const int _CC_9 = 57; // '9'.codeUnitAt(0)
-  static const int _CC_a = 97; // 'a'.codeUnitAt(0)
-  static const int _CC_z = 122; // 'z'.codeUnitAt(0)
-  static const int _CC_A = 65; // 'A'.codeUnitAt(0)
-  static const int _CC_Z = 90; // 'Z'.codeUnitAt(0)
-
-  static int _decodeDigit(int c) {
-    if (c >= _CC_0 && c <= _CC_9) {
-      return c - _CC_0;
-    } else if (c >= _CC_a && c <= _CC_z) {
-      return c - _CC_a + 10;
-    } else if (c >= _CC_A && c <= _CC_Z) {
-      return c - _CC_A + 10;
-    } else {
-      return -1; // bad char code
-    }
-  }
-
-  static int _validateRadix(int radix) {
-    if (2 <= radix && radix <= 36) return radix;
-    throw new RangeError.range(radix, 2, 36, 'radix');
-  }
-
-  /**
-   * Parses a [String] in a given [radix] between 2 and 16 and returns an
-   * [Int32].
-   */
-  // TODO(rice) - Make this faster by converting several digits at once.
-  static Int32 parseRadix(String s, int radix) {
-    _validateRadix(radix);
-    Int32 x = ZERO;
-    for (int i = 0; i < s.length; i++) {
-      int c = s.codeUnitAt(i);
-      int digit = _decodeDigit(c);
-      if (digit < 0 || digit >= radix) {
-        throw new FormatException("Non-radix code unit: $c");
-      }
-      x = (x * radix) + digit;
-    }
-    return x;
-  }
-
-  /**
-   * Parses a decimal [String] and returns an [Int32].
-   */
-  static Int32 parseInt(String s) => new Int32(int.parse(s));
-
-  /**
-   * Parses a hexadecimal [String] and returns an [Int32].
-   */
-  static Int32 parseHex(String s) => parseRadix(s, 16);
-
-  // Assumes i is <= 32-bit.
-  static int _bitCount(int i) {
-    // See "Hacker's Delight", section 5-1, "Counting 1-Bits".
-
-    // The basic strategy is to use "divide and conquer" to
-    // add pairs (then quads, etc.) of bits together to obtain
-    // sub-counts.
-    //
-    // A straightforward approach would look like:
-    //
-    // i = (i & 0x55555555) + ((i >>  1) & 0x55555555);
-    // i = (i & 0x33333333) + ((i >>  2) & 0x33333333);
-    // i = (i & 0x0F0F0F0F) + ((i >>  4) & 0x0F0F0F0F);
-    // i = (i & 0x00FF00FF) + ((i >>  8) & 0x00FF00FF);
-    // i = (i & 0x0000FFFF) + ((i >> 16) & 0x0000FFFF);
-    //
-    // The code below removes unnecessary &'s and uses a
-    // trick to remove one instruction in the first line.
-
-    i -= ((i >> 1) & 0x55555555);
-    i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
-    i = ((i + (i >> 4)) & 0x0F0F0F0F);
-    i += (i >> 8);
-    i += (i >> 16);
-    return (i & 0x0000003F);
-  }
-
-  // Assumes i is <= 32-bit
-  static int _numberOfLeadingZeros(int i) {
-    i |= i >> 1;
-    i |= i >> 2;
-    i |= i >> 4;
-    i |= i >> 8;
-    i |= i >> 16;
-    return _bitCount(~i);
-  }
-
-  static int _numberOfTrailingZeros(int i) => _bitCount((i & -i) - 1);
-
-  // The internal value, kept in the range [MIN_VALUE, MAX_VALUE].
-  final int _i;
-
-  const Int32._internal(int i) : _i = i;
-
-  /**
-   * Constructs an [Int32] from an [int].  Only the low 32 bits of the input
-   * are used.
-   */
-  Int32([int i=0]) : _i = (i & 0x7fffffff) - (i & 0x80000000);
-
-  // Returns the [int] representation of the specified value. Throws
-  // [ArgumentError] for non-integer arguments.
-  int _toInt(val) {
-    if (val is Int32) {
-      return val._i;
-    } else if (val is int) {
-      return val;
-    }
-    throw new ArgumentError(val);
-  }
-
-  // The +, -, * , &, |, and ^ operaters deal with types as follows:
-  //
-  // Int32 + int => Int32
-  // Int32 + Int32 => Int32
-  // Int32 + Int64 => Int64
-  //
-  // The %, ~/ and remainder operators return an Int32 even with an Int64
-  // argument, since the result cannot be greater than the value on the
-  // left-hand side:
-  //
-  // Int32 % int => Int32
-  // Int32 % Int32 => Int32
-  // Int32 % Int64 => Int32
-
-  IntX operator +(other) {
-    if (other is Int64) {
-      return this.toInt64() + other;
-    }
-    return new Int32(_i + _toInt(other));
-  }
-
-  IntX operator -(other) {
-    if (other is Int64) {
-      return this.toInt64() - other;
-    }
-    return new Int32(_i - _toInt(other));
-  }
-
-  Int32 operator -() => new Int32(-_i);
-
-  IntX operator *(other) {
-    if (other is Int64) {
-      return this.toInt64() * other;
-    }
-    // TODO(rice) - optimize
-    return (this.toInt64() * other).toInt32();
-  }
-
-  Int32 operator %(other) {
-    if (other is Int64) {
-      // Result will be Int32
-      return (this.toInt64() % other).toInt32();
-    }
-    return new Int32(_i % _toInt(other));
-  }
-
-  Int32 operator ~/(other) {
-    if (other is Int64) {
-      return (this.toInt64() ~/ other).toInt32();
-    }
-    return new Int32(_i ~/ _toInt(other));
-  }
-
-  Int32 remainder(other) {
-    if (other is Int64) {
-      Int64 t = this.toInt64();
-      return (t - (t ~/ other) * other).toInt32();
-    }
-    return this - (this ~/ other) * other;
-  }
-
-  Int32 operator &(other) {
-    if (other is Int64) {
-      return (this.toInt64() & other).toInt32();
-    }
-    return new Int32(_i & _toInt(other));
-  }
-
-  Int32 operator |(other) {
-    if (other is Int64) {
-      return (this.toInt64() | other).toInt32();
-    }
-    return new Int32(_i | _toInt(other));
-  }
-
-  Int32 operator ^(other) {
-    if (other is Int64) {
-      return (this.toInt64() ^ other).toInt32();
-    }
-    return new Int32(_i ^ _toInt(other));
-  }
-
-  Int32 operator ~() => new Int32(~_i);
-
-  Int32 operator <<(int n) {
-    if (n < 0) {
-      throw new ArgumentError(n);
-    }
-    n &= 31;
-    return new Int32(_i << n);
-  }
-
-  Int32 operator >>(int n) {
-    if (n < 0) {
-      throw new ArgumentError(n);
-    }
-    n &= 31;
-    int value;
-    if (_i >= 0) {
-      value = _i >> n;
-    } else {
-      value = (_i >> n) | (0xffffffff << (32 - n));
-    }
-    return new Int32(value);
-  }
-
-  Int32 shiftRightUnsigned(int n) {
-    if (n < 0) {
-      throw new ArgumentError(n);
-    }
-    n &= 31;
-    int value;
-    if (_i >= 0) {
-      value = _i >> n;
-    } else {
-      value = (_i >> n) & ((1 << (32 - n)) - 1);
-    }
-    return new Int32(value);
-  }
-
-  /**
-   * Returns [:true:] if this [Int32] has the same numeric value as the
-   * given object.  The argument may be an [int] or an [IntX].
-   */
-  bool operator ==(other) {
-    if (other is Int32) {
-      return _i == other._i;
-    } else if (other is Int64) {
-      return this.toInt64() == other;
-    } else if (other is int) {
-      return _i == other;
-    }
-    return false;
-  }
-
-  int compareTo(IntX other) {
-    if (other is Int64) {
-      return this.toInt64().compareTo(other);
-    }
-    return _i.compareTo(_toInt(other));
-  }
-
-  bool operator <(other) {
-    if (other is Int64) {
-      return this.toInt64() < other;
-    }
-    return _i < _toInt(other);
-  }
-
-  bool operator <=(other) {
-    if (other is Int64) {
-      return this.toInt64() <= other;
-    }
-    return _i <= _toInt(other);
-  }
-
-  bool operator >(other) {
-    if (other is Int64) {
-      return this.toInt64() > other;
-    }
-    return _i > _toInt(other);
-  }
-
-  bool operator >=(other) {
-    if (other is Int64) {
-      return this.toInt64() >= other;
-    }
-    return _i >= _toInt(other);
-  }
-
-  bool get isEven => (_i & 0x1) == 0;
-  bool get isMaxValue => _i == 2147483647;
-  bool get isMinValue => _i == -2147483648;
-  bool get isNegative => _i < 0;
-  bool get isOdd => (_i & 0x1) == 1;
-  bool get isZero => _i == 0;
-  int get bitLength => _i.bitLength;
-
-  int get hashCode => _i;
-
-  Int32 abs() => _i < 0 ? new Int32(-_i) : this;
-
-  Int32 clamp(lowerLimit, upperLimit) {
-    if (this < lowerLimit) {
-      if (lowerLimit is IntX) return lowerLimit.toInt32();
-      if (lowerLimit is int) return new Int32(lowerLimit);
-      throw new ArgumentError(lowerLimit);
-    } else if (this > upperLimit) {
-      if (upperLimit is IntX) return upperLimit.toInt32();
-      if (upperLimit is int) return new Int32(upperLimit);
-      throw new ArgumentError(upperLimit);
-    }
-    return this;
-  }
-
-  int numberOfLeadingZeros() => _numberOfLeadingZeros(_i);
-  int numberOfTrailingZeros() => _numberOfTrailingZeros(_i);
-
-  Int32 toSigned(int width) {
-    if (width < 1 || width > 32) throw new RangeError.range(width, 1, 32);
-    return new Int32(_i.toSigned(width));
-  }
-
-  Int32 toUnsigned(int width) {
-    if (width < 0 || width > 32) throw new RangeError.range(width, 0, 32);
-    return new Int32(_i.toUnsigned(width));
-  }
-
-  List<int> toBytes() {
-    List<int> result = new List<int>(4);
-    result[0] = _i & 0xff;
-    result[1] = (_i >> 8) & 0xff;
-    result[2] = (_i >> 16) & 0xff;
-    result[3] = (_i >> 24) & 0xff;
-    return result;
-  }
-
-  double toDouble() => _i.toDouble();
-  int toInt() => _i;
-  Int32 toInt32() => this;
-  Int64 toInt64() => new Int64(_i);
-
-  String toString() => _i.toString();
-  String toHexString() => _i.toRadixString(16);
-  String toRadixString(int radix) => _i.toRadixString(radix);
-}
diff --git a/pkg/fixnum/lib/src/int64.dart b/pkg/fixnum/lib/src/int64.dart
deleted file mode 100644
index 7770eb1..0000000
--- a/pkg/fixnum/lib/src/int64.dart
+++ /dev/null
@@ -1,1002 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of fixnum;
-
-/**
- * An immutable 64-bit signed integer, in the range [-2^63, 2^63 - 1].
- * Arithmetic operations may overflow in order to maintain this range.
- */
-class Int64 implements IntX {
-
-  // A 64-bit integer is represented internally as three non-negative
-  // integers, storing the 22 low, 22 middle, and 20 high bits of the
-  // 64-bit value.  _l (low) and _m (middle) are in the range
-  // [0, 2^22 - 1] and _h (high) is in the range [0, 2^20 - 1].
-  //
-  // The values being assigned to _l, _m and _h in initialization are masked to
-  // force them into the above ranges.  Sometimes we know that the value is a
-  // small non-negative integer but the dart2js compiler can't infer that, so a
-  // few of the masking operations are not needed for correctness but are
-  // helpful for dart2js code quality.
-
-  final int _l, _m, _h;
-
-  // Note: several functions require _BITS == 22 -- do not change this value.
-  static const int _BITS = 22;
-  static const int _BITS01 = 44; // 2 * _BITS
-  static const int _BITS2 = 20; // 64 - _BITS01
-  static const int _MASK = 4194303; // (1 << _BITS) - 1
-  static const int _MASK2 = 1048575; // (1 << _BITS2) - 1
-  static const int _SIGN_BIT = 19; // _BITS2 - 1
-  static const int _SIGN_BIT_MASK = 1 << _SIGN_BIT;
-
-  /**
-   * The maximum positive value attainable by an [Int64], namely
-   * 9,223,372,036,854,775,807.
-   */
-  static const Int64 MAX_VALUE = const Int64._bits(_MASK, _MASK, _MASK2 >> 1);
-
-  /**
-   * The minimum positive value attainable by an [Int64], namely
-   * -9,223,372,036,854,775,808.
-   */
-  static const Int64 MIN_VALUE = const Int64._bits(0, 0, _SIGN_BIT_MASK);
-
-  /**
-   * An [Int64] constant equal to 0.
-   */
-  static const Int64 ZERO = const Int64._bits(0, 0, 0);
-
-  /**
-   * An [Int64] constant equal to 1.
-   */
-  static const Int64 ONE = const Int64._bits(1, 0, 0);
-
-  /**
-   * An [Int64] constant equal to 2.
-   */
-  static const Int64 TWO = const Int64._bits(2, 0, 0);
-
-  /**
-   * Constructs an [Int64] with a given bitwise representation.  No validation
-   * is performed.
-   */
-  const Int64._bits(int this._l, int this._m, int this._h);
-
-  /**
-   * Parses a [String] in a given [radix] between 2 and 36 and returns an
-   * [Int64].
-   */
-  static Int64 parseRadix(String s, int radix) {
-    return _parseRadix(s, Int32._validateRadix(radix));
-  }
-
-  static Int64 _parseRadix(String s, int radix) {
-    int i = 0;
-    bool negative = false;
-    if (s[0] == '-') {
-      negative = true;
-      i++;
-    }
-    int d0 = 0, d1 = 0, d2 = 0;  //  low, middle, high components.
-    for (; i < s.length; i++) {
-      int c = s.codeUnitAt(i);
-      int digit = Int32._decodeDigit(c);
-      if (digit < 0 || digit >= radix) {
-        throw new FormatException("Non-radix char code: $c");
-      }
-
-      // [radix] and [digit] are at most 6 bits, component is 22, so we can
-      // multiply and add within 30 bit temporary values.
-      d0 = d0 * radix + digit;
-      int carry = d0 >> _BITS;
-      d0 = _MASK & d0;
-
-      d1 = d1 * radix + carry;
-      carry = d1 >> _BITS;
-      d1 = _MASK & d1;
-
-      d2 = d2 * radix + carry;
-      d2 = _MASK2 & d2;
-    }
-
-    if (negative) return _negate(d0, d1, d2);
-
-    return Int64._masked(d0, d1, d2);
-  }
-
-  /**
-   * Parses a decimal [String] and returns an [Int64].
-   */
-  static Int64 parseInt(String s) => _parseRadix(s, 10);
-
-  /**
-   * Parses a hexadecimal [String] and returns an [Int64].
-   */
-  static Int64 parseHex(String s) => _parseRadix(s, 16);
-
-  //
-  // Public constructors
-  //
-
-  /**
-   * Constructs an [Int64] with a given [int] value; zero by default.
-   */
-  factory Int64([int value=0]) {
-    int v0 = 0, v1 = 0, v2 = 0;
-    bool negative = false;
-    if (value < 0) {
-      negative = true;
-      value = -value - 1;
-    }
-    // Avoid using bitwise operations that in JavaScript coerce their input to
-    // 32 bits.
-    v2 = value ~/ 17592186044416; // 2^44
-    value -= v2 * 17592186044416;
-    v1 = value ~/ 4194304; // 2^22
-    value -= v1 * 4194304;
-    v0 = value;
-
-    if (negative) {
-      v0 = ~v0;
-      v1 = ~v1;
-      v2 = ~v2;
-    }
-    return Int64._masked(v0, v1, v2);
-  }
-
-  factory Int64.fromBytes(List<int> bytes) {
-    int top = bytes[7] & 0xff;
-    top <<= 8;
-    top |= bytes[6] & 0xff;
-    top <<= 8;
-    top |= bytes[5] & 0xff;
-    top <<= 8;
-    top |= bytes[4] & 0xff;
-
-    int bottom = bytes[3] & 0xff;
-    bottom <<= 8;
-    bottom |= bytes[2] & 0xff;
-    bottom <<= 8;
-    bottom |= bytes[1] & 0xff;
-    bottom <<= 8;
-    bottom |= bytes[0] & 0xff;
-
-    return new Int64.fromInts(top, bottom);
-  }
-
-  factory Int64.fromBytesBigEndian(List<int> bytes) {
-    int top = bytes[0] & 0xff;
-    top <<= 8;
-    top |= bytes[1] & 0xff;
-    top <<= 8;
-    top |= bytes[2] & 0xff;
-    top <<= 8;
-    top |= bytes[3] & 0xff;
-
-    int bottom = bytes[4] & 0xff;
-    bottom <<= 8;
-    bottom |= bytes[5] & 0xff;
-    bottom <<= 8;
-    bottom |= bytes[6] & 0xff;
-    bottom <<= 8;
-    bottom |= bytes[7] & 0xff;
-
-    return new Int64.fromInts(top, bottom);
- }
-
-  /**
-   * Constructs an [Int64] from a pair of 32-bit integers having the value
-   * [:((top & 0xffffffff) << 32) | (bottom & 0xffffffff):].
-   */
-  factory Int64.fromInts(int top, int bottom) {
-    top &= 0xffffffff;
-    bottom &= 0xffffffff;
-    int d0 = _MASK & bottom;
-    int d1 = ((0xfff & top) << 10) | (0x3ff & (bottom >> _BITS));
-    int d2 = _MASK2 & (top >> 12);
-    return  Int64._masked(d0, d1, d2);
-  }
-
-  // Returns the [Int64] representation of the specified value. Throws
-  // [ArgumentError] for non-integer arguments.
-  static Int64 _promote(value) {
-    if (value is Int64) {
-      return value;
-    } else if (value is int) {
-      return new Int64(value);
-    } else if (value is Int32) {
-      return value.toInt64();
-    }
-    throw new ArgumentError.value(value);
-  }
-
-  Int64 operator +(other) {
-    Int64 o = _promote(other);
-    int sum0 = _l + o._l;
-    int sum1 = _m + o._m + (sum0 >> _BITS);
-    int sum2 = _h + o._h + (sum1 >> _BITS);
-    return Int64._masked(sum0, sum1, sum2);
-  }
-
-  Int64 operator -(other) {
-    Int64 o = _promote(other);
-    return _sub(_l, _m, _h, o._l, o._m, o._h);
-  }
-
-  Int64 operator -() => _negate(_l, _m, _h);
-
-  Int64 operator *(other) {
-    Int64 o = _promote(other);
-
-    // Grab 13-bit chunks.
-    int a0 = _l & 0x1fff;
-    int a1 = (_l >> 13) | ((_m & 0xf) << 9);
-    int a2 = (_m >> 4) & 0x1fff;
-    int a3 = (_m >> 17) | ((_h & 0xff) << 5);
-    int a4 = (_h & 0xfff00) >> 8;
-
-    int b0 = o._l & 0x1fff;
-    int b1 = (o._l >> 13) | ((o._m & 0xf) << 9);
-    int b2 = (o._m >> 4) & 0x1fff;
-    int b3 = (o._m >> 17) | ((o._h & 0xff) << 5);
-    int b4 = (o._h & 0xfff00) >> 8;
-
-    // Compute partial products.
-    // Optimization: if b is small, avoid multiplying by parts that are 0.
-    int p0 = a0 * b0; // << 0
-    int p1 = a1 * b0; // << 13
-    int p2 = a2 * b0; // << 26
-    int p3 = a3 * b0; // << 39
-    int p4 = a4 * b0; // << 52
-
-    if (b1 != 0) {
-      p1 += a0 * b1;
-      p2 += a1 * b1;
-      p3 += a2 * b1;
-      p4 += a3 * b1;
-    }
-    if (b2 != 0) {
-      p2 += a0 * b2;
-      p3 += a1 * b2;
-      p4 += a2 * b2;
-    }
-    if (b3 != 0) {
-      p3 += a0 * b3;
-      p4 += a1 * b3;
-    }
-    if (b4 != 0) {
-      p4 += a0 * b4;
-    }
-
-    // Accumulate into 22-bit chunks:
-    // .........................................c10|...................c00|
-    // |....................|..................xxxx|xxxxxxxxxxxxxxxxxxxxxx| p0
-    // |....................|......................|......................|
-    // |....................|...................c11|......c01.............|
-    // |....................|....xxxxxxxxxxxxxxxxxx|xxxxxxxxx.............| p1
-    // |....................|......................|......................|
-    // |.................c22|...............c12....|......................|
-    // |..........xxxxxxxxxx|xxxxxxxxxxxxxxxxxx....|......................| p2
-    // |....................|......................|......................|
-    // |.................c23|..c13.................|......................|
-    // |xxxxxxxxxxxxxxxxxxxx|xxxxx.................|......................| p3
-    // |....................|......................|......................|
-    // |.........c24........|......................|......................|
-    // |xxxxxxxxxxxx........|......................|......................| p4
-
-    int c00 = p0 & 0x3fffff;
-    int c01 = (p1 & 0x1ff) << 13;
-    int c0 = c00 + c01;
-
-    int c10 = p0 >> 22;
-    int c11 = p1 >> 9;
-    int c12 = (p2 & 0x3ffff) << 4;
-    int c13 = (p3 & 0x1f) << 17;
-    int c1 = c10 + c11 + c12 + c13;
-
-    int c22 = p2 >> 18;
-    int c23 = p3 >> 5;
-    int c24 = (p4 & 0xfff) << 8;
-    int c2 = c22 + c23 + c24;
-
-    // Propagate high bits from c0 -> c1, c1 -> c2.
-    c1 += c0 >> _BITS;
-    c2 += c1 >> _BITS;
-
-    return Int64._masked(c0, c1, c2);
-  }
-
-  Int64 operator %(other) => _divide(this, other, _RETURN_MOD);
-
-  Int64 operator ~/(other) => _divide(this, other, _RETURN_DIV);
-
-  Int64 remainder(other) => _divide(this, other, _RETURN_REM);
-
-  Int64 operator &(other) {
-    Int64 o = _promote(other);
-    int a0 = _l & o._l;
-    int a1 = _m & o._m;
-    int a2 = _h & o._h;
-    return Int64._masked(a0, a1, a2);
-  }
-
-  Int64 operator |(other) {
-    Int64 o = _promote(other);
-    int a0 = _l | o._l;
-    int a1 = _m | o._m;
-    int a2 = _h | o._h;
-    return Int64._masked(a0, a1, a2);
-  }
-
-  Int64 operator ^(other) {
-    Int64 o = _promote(other);
-    int a0 = _l ^ o._l;
-    int a1 = _m ^ o._m;
-    int a2 = _h ^ o._h;
-    return Int64._masked(a0, a1, a2);
-  }
-
-  Int64 operator ~() {
-    return Int64._masked(~_l, ~_m, ~_h);
-  }
-
-  Int64 operator <<(int n) {
-    if (n < 0) {
-      throw new ArgumentError.value(n);
-    }
-    n &= 63;
-
-    int res0, res1, res2;
-    if (n < _BITS) {
-      res0 = _l << n;
-      res1 = (_m << n) | (_l >> (_BITS - n));
-      res2 = (_h << n) | (_m >> (_BITS - n));
-    } else if (n < _BITS01) {
-      res0 = 0;
-      res1 = _l << (n - _BITS);
-      res2 = (_m << (n - _BITS)) | (_l >> (_BITS01 - n));
-    } else {
-      res0 = 0;
-      res1 = 0;
-      res2 = _l << (n - _BITS01);
-    }
-
-    return Int64._masked(res0, res1, res2);
-  }
-
-  Int64 operator >>(int n) {
-    if (n < 0) {
-      throw new ArgumentError.value(n);
-    }
-    n &= 63;
-
-    int res0, res1, res2;
-
-    // Sign extend h(a).
-    int a2 = _h;
-    bool negative = (a2 & _SIGN_BIT_MASK) != 0;
-    if (negative && _MASK > _MASK2) {
-      // Add extra one bits on the left so the sign gets shifted into the wider
-      // lower words.
-      a2 += (_MASK - _MASK2);
-    }
-
-    if (n < _BITS) {
-      res2 = _shiftRight(a2, n);
-      if (negative) {
-        res2 |= _MASK2 & ~(_MASK2 >> n);
-      }
-      res1 = _shiftRight(_m, n) | (a2 << (_BITS - n));
-      res0 = _shiftRight(_l, n) | (_m << (_BITS - n));
-    } else if (n < _BITS01) {
-      res2 = negative ? _MASK2 : 0;
-      res1 = _shiftRight(a2, n - _BITS);
-      if (negative) {
-        res1 |= _MASK & ~(_MASK >> (n - _BITS));
-      }
-      res0 = _shiftRight(_m, n - _BITS) | (a2 << (_BITS01 - n));
-    } else {
-      res2 = negative ? _MASK2 : 0;
-      res1 = negative ? _MASK : 0;
-      res0 = _shiftRight(a2, n - _BITS01);
-      if (negative) {
-        res0 |= _MASK & ~(_MASK >> (n - _BITS01));
-      }
-    }
-
-    return Int64._masked(res0, res1, res2);
-  }
-
-  Int64 shiftRightUnsigned(int n) {
-    if (n < 0) {
-      throw new ArgumentError.value(n);
-    }
-    n &= 63;
-
-    int res0, res1, res2;
-    int a2 = _MASK2 & _h; // Ensure a2 is positive.
-    if (n < _BITS) {
-      res2 = a2 >> n;
-      res1 = (_m >> n) | (a2 << (_BITS - n));
-      res0 = (_l >> n) | (_m << (_BITS - n));
-    } else if (n < _BITS01) {
-      res2 = 0;
-      res1 = a2 >> (n - _BITS);
-      res0 = (_m >> (n - _BITS)) | (_h << (_BITS01 - n));
-    } else {
-      res2 = 0;
-      res1 = 0;
-      res0 = a2 >> (n - _BITS01);
-    }
-
-    return Int64._masked(res0, res1, res2);
-  }
-
-  /**
-   * Returns [:true:] if this [Int64] has the same numeric value as the
-   * given object.  The argument may be an [int] or an [IntX].
-   */
-  bool operator ==(other) {
-    Int64 o;
-    if (other is Int64) {
-      o = other;
-    } else if (other is int) {
-      if (_h == 0 && _m == 0) return _l == other;
-      // Since we know one of [_h] or [_m] is non-zero, if [other] fits in the
-      // low word then it can't be numerically equal.
-      if ((_MASK & other) == other) return false;
-      o = new Int64(other);
-    } else if (other is Int32) {
-      o = other.toInt64();
-    }
-    if (o != null) {
-      return _l == o._l && _m == o._m && _h == o._h;
-    }
-    return false;
-  }
-
-  int compareTo(IntX other) =>_compareTo(other);
-
-  int _compareTo(other) {
-    Int64 o = _promote(other);
-    int signa = _h >> (_BITS2 - 1);
-    int signb = o._h >> (_BITS2 - 1);
-    if (signa != signb) {
-      return signa == 0 ? 1 : -1;
-    }
-    if (_h > o._h) {
-      return 1;
-    } else if (_h < o._h) {
-      return -1;
-    }
-    if (_m > o._m) {
-      return 1;
-    } else if (_m < o._m) {
-      return -1;
-    }
-    if (_l > o._l) {
-      return 1;
-    } else if (_l < o._l) {
-      return -1;
-    }
-    return 0;
-  }
-
-  bool operator <(other) => _compareTo(other) < 0;
-  bool operator <=(other) => _compareTo(other) <= 0;
-  bool operator >(other) => this._compareTo(other) > 0;
-  bool operator >=(other) => _compareTo(other) >= 0;
-
-  bool get isEven => (_l & 0x1) == 0;
-  bool get isMaxValue => (_h == _MASK2 >> 1) && _m == _MASK && _l == _MASK;
-  bool get isMinValue => _h == _SIGN_BIT_MASK && _m == 0 && _l == 0;
-  bool get isNegative => (_h & _SIGN_BIT_MASK) != 0;
-  bool get isOdd => (_l & 0x1) == 1;
-  bool get isZero => _h == 0 && _m == 0 && _l == 0;
-
-  int get bitLength {
-    if (isZero) return 0;
-    int a0 = _l, a1 = _m, a2 = _h;
-    if (isNegative) {
-      a0 = _MASK & ~a0;
-      a1 = _MASK & ~a1;
-      a2 = _MASK2 & ~a2;
-    }
-    if (a2 != 0) return _BITS01 + a2.bitLength;
-    if (a1 != 0) return _BITS + a1.bitLength;
-    return a0.bitLength;
-  }
-
-  /**
-   * Returns a hash code based on all the bits of this [Int64].
-   */
-  int get hashCode {
-    // TODO(sra): Should we ensure that hashCode values match corresponding int?
-    // i.e. should `new Int64(x).hashCode == x.hashCode`?
-    int bottom = ((_m & 0x3ff) << _BITS) | _l;
-    int top = (_h << 12) | ((_m >> 10) & 0xfff);
-    return bottom ^ top;
-  }
-
-  Int64 abs() {
-    return this.isNegative ? -this : this;
-  }
-
-  Int64 clamp(lowerLimit, upperLimit) {
-    Int64 lower = _promote(lowerLimit);
-    Int64 upper = _promote(upperLimit);
-    if (this < lower) return lower;
-    if (this > upper) return upper;
-    return this;
-  }
-
-  /**
-   * Returns the number of leading zeros in this [Int64] as an [int]
-   * between 0 and 64.
-   */
-  int numberOfLeadingZeros() {
-    int b2 = Int32._numberOfLeadingZeros(_h);
-    if (b2 == 32) {
-      int b1 = Int32._numberOfLeadingZeros(_m);
-      if (b1 == 32) {
-        return Int32._numberOfLeadingZeros(_l) + 32;
-      } else {
-        return b1 + _BITS2 - (32 - _BITS);
-      }
-    } else {
-      return b2 - (32 - _BITS2);
-    }
-  }
-
-  /**
-   * Returns the number of trailing zeros in this [Int64] as an [int]
-   * between 0 and 64.
-   */
-  int numberOfTrailingZeros() {
-    int zeros = Int32._numberOfTrailingZeros(_l);
-    if (zeros < 32) {
-      return zeros;
-    }
-
-    zeros = Int32._numberOfTrailingZeros(_m);
-    if (zeros < 32) {
-      return _BITS + zeros;
-    }
-
-    zeros = Int32._numberOfTrailingZeros(_h);
-    if (zeros < 32) {
-      return _BITS01 + zeros;
-    }
-    // All zeros
-    return 64;
-  }
-
-  Int64 toSigned(int width) {
-    if (width < 1 || width > 64) throw new RangeError.range(width, 1, 64);
-    if (width > _BITS01) {
-      return Int64._masked(_l, _m, _h.toSigned(width - _BITS01));
-    } else if (width > _BITS) {
-      int m = _m.toSigned(width - _BITS);
-      return m.isNegative
-          ? Int64._masked(_l, m, _MASK2)
-          : Int64._masked(_l, m, 0);  // Masking for type inferrer.
-    } else {
-      int l = _l.toSigned(width);
-      return l.isNegative
-          ? Int64._masked(l, _MASK, _MASK2)
-          : Int64._masked(l, 0, 0);  // Masking for type inferrer.
-    }
-  }
-
-  Int64 toUnsigned(int width) {
-    if (width < 0 || width > 64) throw new RangeError.range(width, 0, 64);
-    if (width > _BITS01) {
-      int h = _h.toUnsigned(width - _BITS01);
-      return Int64._masked(_l, _m, h);
-    } else if (width > _BITS) {
-      int m = _m.toUnsigned(width - _BITS);
-      return Int64._masked(_l, m, 0);
-    } else {
-      int l = _l.toUnsigned(width);
-      return Int64._masked(l, 0, 0);
-    }
-  }
-
-  List<int> toBytes() {
-    List<int> result = new List<int>(8);
-    result[0] = _l & 0xff;
-    result[1] = (_l >> 8) & 0xff;
-    result[2] = ((_m << 6) & 0xfc) | ((_l >> 16) & 0x3f);
-    result[3] = (_m >> 2) & 0xff;
-    result[4] = (_m >> 10) & 0xff;
-    result[5] = ((_h << 4) & 0xf0) | ((_m >> 18) & 0xf);
-    result[6] = (_h >> 4) & 0xff;
-    result[7] = (_h >> 12) & 0xff;
-    return result;
-  }
-
-  double toDouble() => toInt().toDouble();
-
-  int toInt() {
-    int l = _l;
-    int m = _m;
-    int h = _h;
-    // In the sum we add least significant to most significant so that in
-    // JavaScript double arithmetic rounding occurs on only the last addition.
-    if ((_h & _SIGN_BIT_MASK) != 0) {
-      l = _MASK & ~_l;
-      m = _MASK & ~_m;
-      h = _MASK2 & ~_h;
-      return -((1 + l) + (4194304 * m) + (17592186044416 * h));
-    } else {
-      return l + (4194304 * m) + (17592186044416 * h);
-    }
-  }
-
-  /**
-   * Returns an [Int32] containing the low 32 bits of this [Int64].
-   */
-  Int32 toInt32() {
-    return new Int32(((_m & 0x3ff) << _BITS) | _l);
-  }
-
-  /**
-   * Returns [this].
-   */
-  Int64 toInt64() => this;
-
-  /**
-   * Returns the value of this [Int64] as a decimal [String].
-   */
-  String toString() => _toRadixString(10);
-
-  // TODO(rice) - Make this faster by avoiding arithmetic.
-  String toHexString() {
-    if (isZero) return "0";
-    Int64 x = this;
-    String hexStr = "";
-    while (!x.isZero) {
-      int digit = x._l & 0xf;
-      hexStr = "${_hexDigit(digit)}$hexStr";
-      x = x.shiftRightUnsigned(4);
-    }
-    return hexStr;
-  }
-
-  String toRadixString(int radix) {
-    return _toRadixString(Int32._validateRadix(radix));
-  }
-
-  String _toRadixString(int radix) {
-    int d0 = _l;
-    int d1 = _m;
-    int d2 = _h;
-
-    if (d0 == 0 && d1 == 0 && d2 == 0) return '0';
-
-    String sign = '';
-    if ((d2 & _SIGN_BIT_MASK) != 0) {
-      sign = '-';
-
-      // Negate in-place.
-      d0 = 0 - d0;
-      int borrow = (d0 >> _BITS) & 1;
-      d0 &= _MASK;
-      d1 = 0 - d1 - borrow;
-      borrow = (d1 >> _BITS) & 1;
-      d1 &= _MASK;
-      d2 = 0 - d2 - borrow;
-      d2 &= _MASK2;
-      // d2, d1, d0 now are an unsigned 64 bit integer for MIN_VALUE and an
-      // unsigned 63 bit integer for other values.
-    }
-
-    // Rearrange components into five components where all but the most
-    // significant are 10 bits wide.
-    //
-    //     d4, d3, d4, d1, d0:  24 + 10 + 10 + 10 + 10 bits
-    //
-    // The choice of 10 bits allows a remainder of 20 bits to be scaled by 10
-    // bits and added during division while keeping all intermediate values
-    // within 30 bits (unsigned small integer range for 32 bit implementations
-    // of Dart VM and V8).
-    //
-    //     6  6         5         4         3         2         1
-    //     3210987654321098765432109876543210987654321098765432109876543210
-    //     [--------d2--------][---------d1---------][---------d0---------]
-    //  -->
-    //     [----------d4----------][---d3---][---d2---][---d1---][---d0---]
-
-
-    int d4 = (d2 << 4) | (d1 >> 18);
-    int d3 = (d1 >> 8) & 0x3ff;
-    d2 = ((d1 << 2) | (d0 >> 20)) & 0x3ff;
-    d1 = (d0 >> 10) & 0x3ff;
-    d0 = d0 & 0x3ff;
-
-    int fatRadix = _fatRadixTable[radix];
-
-    // Generate chunks of digits.  In radix 10, generate 6 digits per chunk.
-    //
-    // This loop generates at most 3 chunks, so we store the chunks in locals
-    // rather than a list.  We are trying to generate digits 20 bits at a time
-    // until we have only 30 bits left.  20 + 20 + 30 > 64 would imply that we
-    // need only two chunks, but radix values 17-19 and 33-36 generate only 15
-    // or 16 bits per iteration, so sometimes the third chunk is needed.
-
-    String chunk1 = "", chunk2 = "", chunk3 = "";
-
-    while (!(d4 == 0 && d3 == 0)) {
-      int q = d4 ~/ fatRadix;
-      int r = d4 - q * fatRadix;
-      d4 = q;
-      d3 += r << 10;
-
-      q = d3 ~/ fatRadix;
-      r = d3 - q * fatRadix;
-      d3 = q;
-      d2 += r << 10;
-
-      q = d2 ~/ fatRadix;
-      r = d2 - q * fatRadix;
-      d2 = q;
-      d1 += r << 10;
-
-      q = d1 ~/ fatRadix;
-      r = d1 - q * fatRadix;
-      d1 = q;
-      d0 += r << 10;
-
-      q = d0 ~/ fatRadix;
-      r = d0 - q * fatRadix;
-      d0 = q;
-
-      assert(chunk3 == "");
-      chunk3 = chunk2;
-      chunk2 = chunk1;
-      // Adding [fatRadix] Forces an extra digit which we discard to get a fixed
-      // width.  E.g.  (1000000 + 123) -> "1000123" -> "000123".  An alternative
-      // would be to pad to the left with zeroes.
-      chunk1 = (fatRadix + r).toRadixString(radix).substring(1);
-    }
-    int residue = (d2 << 20) + (d1 << 10) + d0;
-    String leadingDigits = residue == 0 ? '' : residue.toRadixString(radix);
-    return '$sign$leadingDigits$chunk1$chunk2$chunk3';
-  }
-
-  // Table of 'fat' radix values.  Each entry for index `i` is the largest power
-  // of `i` whose remainder fits in 20 bits.
-  static const _fatRadixTable = const <int>[
-      0,
-      0,
-      2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2
-        * 2,
-      3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3,
-      4 * 4 * 4 * 4 * 4 * 4 * 4 * 4 * 4 * 4,
-      5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-      6 * 6 * 6 * 6 * 6 * 6 * 6,
-      7 * 7 * 7 * 7 * 7 * 7 * 7,
-      8 * 8 * 8 * 8 * 8 * 8,
-      9 * 9 * 9 * 9 * 9 * 9,
-      10 * 10 * 10 * 10 * 10 * 10,
-      11 * 11 * 11 * 11 * 11,
-      12 * 12 * 12 * 12 * 12,
-      13 * 13 * 13 * 13 * 13,
-      14 * 14 * 14 * 14 * 14,
-      15 * 15 * 15 * 15 * 15,
-      16 * 16 * 16 * 16 * 16,
-      17 * 17 * 17 * 17,
-      18 * 18 * 18 * 18,
-      19 * 19 * 19 * 19,
-      20 * 20 * 20 * 20,
-      21 * 21 * 21 * 21,
-      22 * 22 * 22 * 22,
-      23 * 23 * 23 * 23,
-      24 * 24 * 24 * 24,
-      25 * 25 * 25 * 25,
-      26 * 26 * 26 * 26,
-      27 * 27 * 27 * 27,
-      28 * 28 * 28 * 28,
-      29 * 29 * 29 * 29,
-      30 * 30 * 30 * 30,
-      31 * 31 * 31 * 31,
-      32 * 32 * 32 * 32,
-      33 * 33 * 33,
-      34 * 34 * 34,
-      35 * 35 * 35,
-      36 * 36 * 36
-  ];
-
-  String toDebugString() {
-    return "Int64[_l=$_l, _m=$_m, _h=$_h]";
-  }
-
-
-  static Int64 _masked(int a0, int a1, int a2) =>
-      new Int64._bits(_MASK & a0, _MASK & a1, _MASK2 & a2);
-
-  static Int64 _sub(int a0, int a1, int a2, int b0, int b1, int b2) {
-    int diff0 = a0 - b0;
-    int diff1 = a1 - b1 - ((diff0 >> _BITS) & 1);
-    int diff2 = a2 - b2 - ((diff1 >> _BITS) & 1);
-    return _masked(diff0, diff1, diff2);
-  }
-
-  static Int64 _negate(int b0, int b1, int b2) {
-    return _sub(0, 0, 0, b0, b1, b2);
-  }
-
-  String _hexDigit(int digit) => "0123456789ABCDEF"[digit];
-
-  // Work around dart2js bugs with negative arguments to '>>' operator.
-  static int _shiftRight(int x, int n) {
-    if (x >= 0) {
-      return x >> n;
-    } else {
-      int shifted = x >> n;
-      if (shifted >= 0x80000000) {
-        shifted -= 4294967296;
-      }
-      return shifted;
-    }
-  }
-
-
-  // Implementation of '~/', '%' and 'remainder'.
-
-  static Int64 _divide(Int64 a, other, int what) {
-    Int64 b = _promote(other);
-    if (b.isZero) {
-      throw new IntegerDivisionByZeroException();
-    }
-    if (a.isZero) return ZERO;
-
-    bool aNeg = a.isNegative;
-    bool bNeg = b.isNegative;
-    a = a.abs();
-    b = b.abs();
-
-    int a0 = a._l;
-    int a1 = a._m;
-    int a2 = a._h;
-
-    int b0 = b._l;
-    int b1 = b._m;
-    int b2 = b._h;
-    return _divideHelper(a0, a1, a2, aNeg, b0, b1, b2, bNeg, what);
-  }
-
-  static const _RETURN_DIV = 1;
-  static const _RETURN_REM = 2;
-  static const _RETURN_MOD = 3;
-
-  static _divideHelper(
-      // up to 64 bits unsigned in a2/a1/a0 and b2/b1/b0
-      int a0, int a1, int a2, bool aNeg,  // input A.
-      int b0, int b1, int b2, bool bNeg,  // input B.
-      int what) {
-    int q0 = 0, q1 = 0, q2 = 0;  // result Q.
-    int r0 = 0, r1 = 0, r2 = 0;  // result R.
-
-    if (b2 == 0 && b1 == 0 && b0 < (1 << (30 - _BITS))) {
-      // Small divisor can be handled by single-digit division within Smi range.
-      //
-      // Handling small divisors here helps the estimate version below by
-      // handling cases where the estimate is off by more than a small amount.
-
-      q2 = a2 ~/ b0;
-      int carry = a2 - q2 * b0;
-      int d1 = a1 + (carry << _BITS);
-      q1 = d1 ~/ b0;
-      carry = d1 - q1 * b0;
-      int d0 = a0 + (carry << _BITS);
-      q0 = d0 ~/ b0;
-      r0 = d0 - q0 * b0;
-    } else {
-      // Approximate Q = A ~/ B and R = A - Q * B using doubles.
-
-      // The floating point approximation is very close to the correct value
-      // when floor(A/B) fits in fewer that 53 bits.
-
-      // We use double arithmetic for intermediate values.  Double arithmetic on
-      // non-negative values is exact under the following conditions:
-      //
-      //   - The values are integer values that fit in 53 bits.
-      //   - Dividing by powers of two (adjusts exponent only).
-      //   - Floor (zeroes bits with fractional weight).
-
-      const double K2 = 17592186044416.0; // 2^44
-      const double K1 = 4194304.0; // 2^22
-
-      // Approximate double values for [a] and [b].
-      double ad = a0 + K1 * a1 + K2 * a2;
-      double bd = b0 + K1 * b1 + K2 * b2;
-      // Approximate quotient.
-      double qd = (ad / bd).floorToDouble();
-
-      // Extract components of [qd] using double arithmetic.
-      double q2d = (qd / K2).floorToDouble();
-      qd = qd - K2 * q2d;
-      double q1d = (qd / K1).floorToDouble();
-      double q0d = qd - K1 * q1d;
-      q2 = q2d.toInt();
-      q1 = q1d.toInt();
-      q0 = q0d.toInt();
-
-      assert(q0 + K1 * q1 + K2 * q2 == (ad / bd).floorToDouble());
-      assert(q2 == 0 || b2 == 0);  // Q and B can't both be big since Q*B <= A.
-
-      // P = Q * B, using doubles to hold intermediates.
-      // We don't need all partial sums since Q*B <= A.
-      double p0d = q0d * b0;
-      double p0carry = (p0d / K1).floorToDouble();
-      p0d = p0d - p0carry * K1;
-      double p1d = q1d * b0 + q0d * b1 + p0carry;
-      double p1carry = (p1d / K1).floorToDouble();
-      p1d = p1d - p1carry * K1;
-      double p2d = q2d * b0 + q1d * b1 + q0d * b2 + p1carry;
-      assert(p2d <= _MASK2);  // No partial sum overflow.
-
-      // R = A - P
-      int diff0 = a0 - p0d.toInt();
-      int diff1 = a1 - p1d.toInt() - ((diff0 >> _BITS) & 1);
-      int diff2 = a2 - p2d.toInt() - ((diff1 >> _BITS) & 1);
-      r0 = _MASK & diff0;
-      r1 = _MASK & diff1;
-      r2 = _MASK2 & diff2;
-
-      // while (R < 0 || R >= B)
-      //  adjust R towards [0, B)
-      while (
-          r2 >= _SIGN_BIT_MASK ||
-          r2 > b2 ||
-          (r2 == b2 && (r1 > b1 || (r1 == b1 && r0 >= b0)))) {
-        // Direction multiplier for adjustment.
-        int m = (r2 & _SIGN_BIT_MASK) == 0 ? 1 : -1;
-        // R = R - B  or  R = R + B
-        int d0 = r0 - m * b0;
-        int d1 = r1 - m * (b1 + ((d0 >> _BITS) & 1));
-        int d2 = r2 - m * (b2 + ((d1 >> _BITS) & 1));
-        r0 = _MASK & d0;
-        r1 = _MASK & d1;
-        r2 = _MASK2 & d2;
-
-        // Q = Q + 1  or  Q = Q - 1
-        d0 = q0 + m;
-        d1 = q1 + m * ((d0 >> _BITS) & 1);
-        d2 = q2 + m * ((d1 >> _BITS) & 1);
-        q0 = _MASK & d0;
-        q1 = _MASK & d1;
-        q2 = _MASK2 & d2;
-      }
-    }
-
-    // 0 <= R < B
-    assert(Int64.ZERO <= new Int64._bits(r0, r1, r2));
-    assert(r2 < b2 ||  // Handles case where B = -(MIN_VALUE)
-        new Int64._bits(r0, r1, r2) < new Int64._bits(b0, b1, b2));
-
-    assert(what == _RETURN_DIV || what == _RETURN_MOD || what == _RETURN_REM);
-    if (what == _RETURN_DIV) {
-      if (aNeg != bNeg) return _negate(q0, q1, q2);
-      return Int64._masked(q0, q1, q2);  // Masking for type inferrer.
-    }
-
-    if (!aNeg) {
-      return Int64._masked(r0, r1, r2);  // Masking for type inferrer.
-    }
-
-    if (what == _RETURN_MOD) {
-      if (r0 == 0 && r1 == 0 && r2 == 0) {
-        return ZERO;
-      } else {
-        return _sub(b0, b1, b2, r0, r1, r2);
-      }
-    } else {
-      return _negate(r0, r1, r2);
-    }
-  }
-}
diff --git a/pkg/fixnum/lib/src/intx.dart b/pkg/fixnum/lib/src/intx.dart
deleted file mode 100644
index f132aff..0000000
--- a/pkg/fixnum/lib/src/intx.dart
+++ /dev/null
@@ -1,235 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of fixnum;
-
-/**
- * A fixed-precision integer.
- */
-abstract class IntX implements Comparable<IntX> {
-
-  /** Addition operator. */
-  IntX operator +(other);
-
-  /** Subtraction operator. */
-  IntX operator -(other);
-
-  /**
-   * Negate operator.
-   *
-   * Note that `-MIN_VALUE` is equal to `MIN_VALUE` due to overflow.
-   */
-  IntX operator -();
-
-  /** Multiplication operator. */
-  IntX operator *(other);
-
-  /**
-   * Euclidean modulo operator.
-   *
-   * Returns the remainder of the euclidean division. The euclidean division
-   * of two integers `a` and `b` yields two integers `q` and `r` such that
-   * `a == b * q + r` and `0 <= r < a.abs()`.
-   */
-  IntX operator %(other);
-
-  /** Truncating division operator. */
-  IntX operator ~/(other);
-
-  /**
-   * Returns the remainder of the truncating division of this integer by
-   * [other].
-   */
-  IntX remainder(other);
-
-  /** Bitwise and operator. */
-  IntX operator &(other);
-
-  /** Bitwise or operator. */
-  IntX operator |(other);
-
-  /** Bitwise xor operator. */
-  IntX operator ^(other);
-
-  /** Bitwise negate operator. */
-  IntX operator ~();
-
-  /**
-   * Left bit-shift operator.
-   *
-   * Returns the result of shifting the bits of this integer by [shiftAmount]
-   * bits to the left. Low-order bits are filled with zeros.
-   */
-  IntX operator <<(int shiftAmount);
-
-  /**
-   * Right bit-shift operator.
-   *
-   * Returns the result of shifting the bits of this integer by [shiftAmount]
-   * bits to the right. High-order bits are filled with zero in the case where
-   * this integer is positive, or one in the case where it is negative.
-   */
-  IntX operator >>(int shiftAmount);
-
-  /**
-   * Unsigned right-shift operator.
-   *
-   * Returns the result of shifting the bits of this integer by [shiftAmount]
-   * bits to the right. High-order bits are filled with zeros.
-   */
-  IntX shiftRightUnsigned(int shiftAmount);
-
-  /**
-   * Returns `true` if and only if [other] is an int or IntX equal in
-   * value to this integer.
-   */
-  bool operator ==(other);
-
-  /** Relational less than operator. */
-  bool operator <(other);
-
-  /** Relational less than or equal to operator. */
-  bool operator <=(other);
-
-  /** Relational greater than operator. */
-  bool operator >(other);
-
-  /** Relational greater than or equal to operator. */
-  bool operator >=(other);
-
-  /** Returns `true` if and only if this integer is even. */
-  bool get isEven;
-
-  /**
-   * Returns `true` if and only if this integer is the maximum signed value
-   * that can be represented within its bit size.
-   */
-  bool get isMaxValue;
-
-  /**
-   * Returns `true` if and only if this integer is the minimum signed value
-   * that can be represented within its bit size.
-   */
-  bool get isMinValue;
-
-  /** Returns `true` if and only if this integer is less than zero. */
-  bool get isNegative;
-
-  /** Returns `true` if and only if this integer is odd. */
-  bool get isOdd;
-
-  /** Returns `true` if and only if this integer is zero. */
-  bool get isZero;
-
-  int get hashCode;
-
-  /** Returns the absolute value of this integer. */
-  IntX abs();
-
-  /** Clamps this integer to be in the range [lowerLimit] - [upperLimit]. */
-  IntX clamp(lowerLimit, upperLimit);
-
-  /**
-   * Returns the minimum number of bits required to store this integer.
-   *
-   * The number of bits excludes the sign bit, which gives the natural length
-   * for non-negative (unsigned) values.  Negative values are complemented to
-   * return the bit position of the first bit that differs from the sign bit.
-   *
-   * To find the the number of bits needed to store the value as a signed value,
-   * add one, i.e. use `x.bitLength + 1`.
-   */
-  int get bitLength;
-
-  /**
-   * Returns the number of high-order zeros in this integer's bit
-   * representation.
-   */
-  int numberOfLeadingZeros();
-
-  /**
-   * Returns the number of low-order zeros in this integer's bit representation.
-   */
-  int numberOfTrailingZeros();
-
-  /**
-   * Returns the least significant [width] bits of this integer, extending the
-   * highest retained bit to the sign.  This is the same as truncating the value
-   * to fit in [width] bits using an signed 2-s complement representation.  The
-   * returned value has the same bit value in all positions higher than [width].
-   *
-   * If the input value fits in [width] bits without truncation, the result is
-   * the same as the input.  The minimum width needed to avoid truncation of `x`
-   * is `x.bitLength + 1`, i.e.
-   *
-   *     x == x.toSigned(x.bitLength + 1);
-   */
-  IntX toSigned(int width);
-
-  /**
-   * Returns the least significant [width] bits of this integer as a
-   * non-negative number (i.e. unsigned representation).  The returned value has
-   * zeros in all bit positions higher than [width].
-   *
-   * If the input fits in [width] bits without truncation, the result is the
-   * same as the input.  The minimum width needed to avoid truncation of `x` is
-   * given by `x.bitLength`, i.e.
-   *
-   *     x == x.toUnsigned(x.bitLength);
-   */
-  IntX toUnsigned(int width);
-
-  /**
-   * Returns a byte-sequence representation of this integer.
-   *
-   * Returns a list of int, starting with the least significant byte.
-   */
-  List<int> toBytes();
-
-  /**
-   * Returns the double representation of this integer.
-   *
-   * On some platforms, inputs with large absolute values (i.e., > 2^52) may
-   * lose some of their low-order bits.
-   */
-  double toDouble();
-
-  /**
-   * Returns the int representation of this integer.
-   *
-   * On some platforms, inputs with large absolute values (i.e., > 2^52) may
-   * lose some of their low-order bits.
-   */
-  int toInt();
-
-  /**
-   * Returns an Int32 representation of this integer.
-   *
-   * Narrower values are sign-extended and wider values have their high bits
-   * truncated.
-   */
-  Int32 toInt32();
-
-  /** Returns an Int64 representation of this integer. */
-  Int64 toInt64();
-
-  /**
-   * Returns a string representing the value of this integer in decimal
-   * notation; example: `'13'`.
-   */
-  String toString();
-
-  /**
-   * Returns a string representing the value of this integer in hexadecimal
-   * notation; example: `'0xd'`.
-   */
-  String toHexString();
-
-  /**
-   * Returns a string representing the value of this integer in the given radix.
-   *
-   * [radix] must be an integer in the range 2 .. 16, inclusive.
-   */
-  String toRadixString(int radix);
-}
diff --git a/pkg/fixnum/pubspec.yaml b/pkg/fixnum/pubspec.yaml
deleted file mode 100644
index 3d3bdaf..0000000
--- a/pkg/fixnum/pubspec.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-name: fixnum
-version: 0.10.3
-author: Dart Team <misc@dartlang.org>
-description: Library for 32- and 64-bit fixed size integers.
-homepage: http://www.dartlang.org
-dev_dependencies:
-  unittest: ">=0.9.0 <0.10.0"
-environment:
-  sdk: ">=0.8.10+6 <2.0.0"
diff --git a/pkg/fixnum/test/int_32_test.dart b/pkg/fixnum/test/int_32_test.dart
deleted file mode 100644
index e5c8c5f..0000000
--- a/pkg/fixnum/test/int_32_test.dart
+++ /dev/null
@@ -1,365 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library Int32test;
-import 'package:fixnum/fixnum.dart';
-import 'package:unittest/unittest.dart';
-
-void main() {
-  group("isX tests", () {
-    test("isEven", () {
-      expect((-Int32.ONE).isEven, false);
-      expect(Int32.ZERO.isEven, true);
-      expect(Int32.ONE.isEven, false);
-      expect(Int32.TWO.isEven, true);
-    });
-    test("isMaxValue", () {
-      expect(Int32.MIN_VALUE.isMaxValue, false);
-      expect(Int32.ZERO.isMaxValue, false);
-      expect(Int32.MAX_VALUE.isMaxValue, true);
-    });
-    test("isMinValue", () {
-      expect(Int32.MIN_VALUE.isMinValue, true);
-      expect(Int32.ZERO.isMinValue, false);
-      expect(Int32.MAX_VALUE.isMinValue, false);
-    });
-    test("isNegative", () {
-      expect(Int32.MIN_VALUE.isNegative, true);
-      expect(Int32.ZERO.isNegative, false);
-      expect(Int32.ONE.isNegative, false);
-    });
-    test("isOdd", () {
-      expect((-Int32.ONE).isOdd, true);
-      expect(Int32.ZERO.isOdd, false);
-      expect(Int32.ONE.isOdd, true);
-      expect(Int32.TWO.isOdd, false);
-    });
-    test("isZero", () {
-      expect(Int32.MIN_VALUE.isZero, false);
-      expect(Int32.ZERO.isZero, true);
-      expect(Int32.MAX_VALUE.isZero, false);
-    });
-    test("bitLength", () {
-      expect(new Int32(-2).bitLength, 1);
-      expect((-Int32.ONE).bitLength, 0);
-      expect(Int32.ZERO.bitLength, 0);
-      expect(Int32.ONE.bitLength, 1);
-      expect(new Int32(2).bitLength, 2);
-      expect(Int32.MAX_VALUE.bitLength, 31);
-      expect(Int32.MIN_VALUE.bitLength, 31);
-    });
-  });
-
-  group("arithmetic operators", () {
-    Int32 n1 = new Int32(1234);
-    Int32 n2 = new Int32(9876);
-    Int32 n3 = new Int32(-1234);
-    Int32 n4 = new Int32(-9876);
-
-    test("+", () {
-      expect(n1 + n2, new Int32(11110));
-      expect(n3 + n2, new Int32(8642));
-      expect(n3 + n4, new Int32(-11110));
-      expect(Int32.MAX_VALUE + 1, Int32.MIN_VALUE);
-      expect(() => new Int32(17) + null, throws);
-    });
-
-    test("-", () {
-      expect(n1 - n2, new Int32(-8642));
-      expect(n3 - n2, new Int32(-11110));
-      expect(n3 - n4, new Int32(8642));
-      expect(Int32.MIN_VALUE - 1, Int32.MAX_VALUE);
-      expect(() => new Int32(17) - null, throws);
-    });
-
-    test("unary -", () {
-      expect(-n1, new Int32(-1234));
-      expect(-Int32.ZERO, Int32.ZERO);
-    });
-
-    test("*", () {
-      expect(n1 * n2, new Int32(12186984));
-      expect(n2 * n3, new Int32(-12186984));
-      expect(n3 * n3, new Int32(1522756));
-      expect(n3 * n2, new Int32(-12186984));
-      expect(new Int32(0x12345678) * new Int32(0x22222222),
-          new Int32(-899716112));
-      expect((new Int32(123456789) * new Int32(987654321)),
-          new Int32(-67153019));
-      expect(new Int32(0x12345678) * new Int64(0x22222222),
-          new Int64.fromInts(0x026D60DC, 0xCA5F6BF0));
-      expect((new Int32(123456789) * 987654321),
-          new Int32(-67153019));
-      expect(() => new Int32(17) * null, throws);
-    });
-
-    test("~/", () {
-      expect(new Int32(829893893) ~/ new Int32(1919), new Int32(432461));
-      expect(new Int32(0x12345678) ~/ new Int32(0x22),
-          new Int32(0x12345678 ~/ 0x22));
-      expect(new Int32(829893893) ~/ new Int64(1919), new Int32(432461));
-      expect(new Int32(0x12345678) ~/ new Int64(0x22),
-          new Int32(0x12345678 ~/ 0x22));
-      expect(new Int32(829893893) ~/ 1919, new Int32(432461));
-      expect(() => new Int32(17) ~/ Int32.ZERO, throws);
-      expect(() => new Int32(17) ~/ null, throws);
-    });
-
-    test("%", () {
-      expect(new Int32(0x12345678) % new Int32(0x22),
-          new Int32(0x12345678 % 0x22));
-      expect(new Int32(0x12345678) % new Int64(0x22),
-          new Int32(0x12345678 % 0x22));
-      expect(() => new Int32(17) % null, throws);
-    });
-
-    test("remainder", () {
-      expect(new Int32(0x12345678).remainder(new Int32(0x22)),
-          new Int32(0x12345678.remainder(0x22)));
-      expect(new Int32(0x12345678).remainder(new Int32(-0x22)),
-          new Int32(0x12345678.remainder(-0x22)));
-      expect(new Int32(-0x12345678).remainder(new Int32(-0x22)),
-          new Int32(-0x12345678.remainder(-0x22)));
-      expect(new Int32(-0x12345678).remainder(new Int32(0x22)),
-          new Int32(-0x12345678.remainder(0x22)));
-      expect(new Int32(0x12345678).remainder(new Int64(0x22)),
-          new Int32(0x12345678.remainder(0x22)));
-      expect(() => new Int32(17).remainder(null), throws);
-    });
-
-    test("clamp", () {
-      Int32 val = new Int32(17);
-      expect(val.clamp(20, 30), new Int32(20));
-      expect(val.clamp(10, 20), new Int32(17));
-      expect(val.clamp(10, 15), new Int32(15));
-
-      expect(val.clamp(new Int32(20), new Int32(30)), new Int32(20));
-      expect(val.clamp(new Int32(10), new Int32(20)), new Int32(17));
-      expect(val.clamp(new Int32(10), new Int32(15)), new Int32(15));
-
-      expect(val.clamp(new Int64(20), new Int64(30)), new Int32(20));
-      expect(val.clamp(new Int64(10), new Int64(20)), new Int32(17));
-      expect(val.clamp(new Int64(10), new Int64(15)), new Int32(15));
-      expect(val.clamp(Int64.MIN_VALUE, new Int64(30)), new Int32(17));
-      expect(val.clamp(new Int64(10), Int64.MAX_VALUE), new Int32(17));
-
-      expect(() => val.clamp(1, 'b'), throwsA(isArgumentError));
-      expect(() => val.clamp('a', 1), throwsA(isArgumentError));
-    });
-  });
-
-  group("comparison operators", () {
-    test("<", () {
-      expect(new Int32(17) < new Int32(18), true);
-      expect(new Int32(17) < new Int32(17), false);
-      expect(new Int32(17) < new Int32(16), false);
-      expect(new Int32(17) < new Int64(18), true);
-      expect(new Int32(17) < new Int64(17), false);
-      expect(new Int32(17) < new Int64(16), false);
-      expect(Int32.MIN_VALUE < Int32.MAX_VALUE, true);
-      expect(Int32.MAX_VALUE < Int32.MIN_VALUE, false);
-      expect(() => new Int32(17) < null, throws);
-    });
-
-    test("<=", () {
-      expect(new Int32(17) <= new Int32(18), true);
-      expect(new Int32(17) <= new Int32(17), true);
-      expect(new Int32(17) <= new Int32(16), false);
-      expect(new Int32(17) <= new Int64(18), true);
-      expect(new Int32(17) <= new Int64(17), true);
-      expect(new Int32(17) <= new Int64(16), false);
-      expect(Int32.MIN_VALUE <= Int32.MAX_VALUE, true);
-      expect(Int32.MAX_VALUE <= Int32.MIN_VALUE, false);
-      expect(() => new Int32(17) <= null, throws);
-    });
-
-    test("==", () {
-      expect(new Int32(17) == new Int32(18), false);
-      expect(new Int32(17) == new Int32(17), true);
-      expect(new Int32(17) == new Int32(16), false);
-      expect(new Int32(17) == new Int64(18), false);
-      expect(new Int32(17) == new Int64(17), true);
-      expect(new Int32(17) == new Int64(16), false);
-      expect(Int32.MIN_VALUE == Int32.MAX_VALUE, false);
-      expect(new Int32(17) == new Object(), false);
-      expect(new Int32(17) == null, false);
-    });
-
-    test(">=", () {
-      expect(new Int32(17) >= new Int32(18), false);
-      expect(new Int32(17) >= new Int32(17), true);
-      expect(new Int32(17) >= new Int32(16), true);
-      expect(new Int32(17) >= new Int64(18), false);
-      expect(new Int32(17) >= new Int64(17), true);
-      expect(new Int32(17) >= new Int64(16), true);
-      expect(Int32.MIN_VALUE >= Int32.MAX_VALUE, false);
-      expect(Int32.MAX_VALUE >= Int32.MIN_VALUE, true);
-      expect(() => new Int32(17) >= null, throws);
-    });
-
-    test(">", () {
-      expect(new Int32(17) > new Int32(18), false);
-      expect(new Int32(17) > new Int32(17), false);
-      expect(new Int32(17) > new Int32(16), true);
-      expect(new Int32(17) > new Int64(18), false);
-      expect(new Int32(17) > new Int64(17), false);
-      expect(new Int32(17) > new Int64(16), true);
-      expect(Int32.MIN_VALUE > Int32.MAX_VALUE, false);
-      expect(Int32.MAX_VALUE > Int32.MIN_VALUE, true);
-      expect(() => new Int32(17) > null, throws);
-    });
-  });
-
-  group("bitwise operators", () {
-    test("&", () {
-      expect(new Int32(0x12345678) & new Int32(0x22222222),
-          new Int32(0x12345678 & 0x22222222));
-      expect(new Int32(0x12345678) & new Int64(0x22222222),
-          new Int64(0x12345678 & 0x22222222));
-      expect(() => new Int32(17) & null, throwsArgumentError);
-    });
-
-    test("|", () {
-      expect(new Int32(0x12345678) | new Int32(0x22222222),
-          new Int32(0x12345678 | 0x22222222));
-      expect(new Int32(0x12345678) | new Int64(0x22222222),
-          new Int64(0x12345678 | 0x22222222));
-      expect(() => new Int32(17) | null, throws);
-    });
-
-    test("^", () {
-      expect(new Int32(0x12345678) ^ new Int32(0x22222222),
-          new Int32(0x12345678 ^ 0x22222222));
-      expect(new Int32(0x12345678) ^ new Int64(0x22222222),
-          new Int64(0x12345678 ^ 0x22222222));
-      expect(() => new Int32(17) ^ null, throws);
-    });
-
-    test("~", () {
-      expect(~(new Int32(0x12345678)), new Int32(~0x12345678));
-      expect(-(new Int32(0x12345678)), new Int64(-0x12345678));
-    });
-  });
-
-  group("bitshift operators", () {
-    test("<<", () {
-      expect(new Int32(0x12345678) << 7, new Int32(0x12345678 << 7));
-      expect(() => new Int32(17) << -1, throwsArgumentError);
-      expect(() => new Int32(17) << null, throws);
-    });
-
-    test(">>", () {
-      expect(new Int32(0x12345678) >> 7, new Int32(0x12345678 >> 7));
-      expect(() => new Int32(17) >> -1, throwsArgumentError);
-      expect(() => new Int32(17) >> null, throws);
-    });
-
-    test("shiftRightUnsigned", () {
-      expect(new Int32(0x12345678).shiftRightUnsigned(7),
-          new Int32(0x12345678 >> 7));
-      expect(() => (new Int32(17).shiftRightUnsigned(-1)), throwsArgumentError);
-      expect(() => (new Int32(17).shiftRightUnsigned(null)), throws);
-    });
-  });
-
-  group("conversions", () {
-    test("toSigned", () {
-      expect(Int32.ONE.toSigned(2), Int32.ONE);
-      expect(Int32.ONE.toSigned(1), -Int32.ONE);
-      expect(Int32.MAX_VALUE.toSigned(32), Int32.MAX_VALUE);
-      expect(Int32.MIN_VALUE.toSigned(32), Int32.MIN_VALUE);
-      expect(Int32.MAX_VALUE.toSigned(31), -Int32.ONE);
-      expect(Int32.MIN_VALUE.toSigned(31), Int32.ZERO);
-      expect(() => Int32.ONE.toSigned(0), throwsRangeError);
-      expect(() => Int32.ONE.toSigned(33), throwsRangeError);
-    });
-    test("toUnsigned", () {
-      expect(Int32.ONE.toUnsigned(1), Int32.ONE);
-      expect(Int32.ONE.toUnsigned(0), Int32.ZERO);
-      expect(Int32.MAX_VALUE.toUnsigned(32), Int32.MAX_VALUE);
-      expect(Int32.MIN_VALUE.toUnsigned(32), Int32.MIN_VALUE);
-      expect(Int32.MAX_VALUE.toUnsigned(31), Int32.MAX_VALUE);
-      expect(Int32.MIN_VALUE.toUnsigned(31), Int32.ZERO);
-      expect(() => Int32.ONE.toUnsigned(-1), throwsRangeError);
-      expect(() => Int32.ONE.toUnsigned(33), throwsRangeError);
-    });
-    test("toDouble", () {
-      expect(new Int32(17).toDouble(), same(17.0));
-      expect(new Int32(-17).toDouble(), same(-17.0));
-    });
-    test("toInt", () {
-      expect(new Int32(17).toInt(), 17);
-      expect(new Int32(-17).toInt(), -17);
-    });
-    test("toInt32", () {
-      expect(new Int32(17).toInt32(), new Int32(17));
-      expect(new Int32(-17).toInt32(), new Int32(-17));
-    });
-    test("toInt64", () {
-      expect(new Int32(17).toInt64(), new Int64(17));
-      expect(new Int32(-17).toInt64(), new Int64(-17));
-    });
-  });
-
-  group("parse", () {
-    test("base 10", () {
-      checkInt(int x) {
-        expect(Int32.parseRadix('$x', 10), new Int32(x));
-      }
-      checkInt(0);
-      checkInt(1);
-      checkInt(1000);
-      checkInt(12345678);
-      checkInt(2147483647);
-      checkInt(2147483648);
-      checkInt(4294967295);
-      checkInt(4294967296);
-      expect(() => Int32.parseRadix('xyzzy', -1), throwsArgumentError);
-      expect(() => Int32.parseRadix('plugh', 10),
-          throwsA(new isInstanceOf<FormatException>()));
-    });
-
-    test("parseRadix", () {
-      check(String s, int r, String x) {
-        expect(Int32.parseRadix(s, r).toString(), x);
-      }
-      check('deadbeef', 16, '-559038737');
-      check('95', 12, '113');
-    });
-  });
-
-  group("string representation", () {
-    test("toString", () {
-      expect(new Int32(0).toString(), "0");
-      expect(new Int32(1).toString(), "1");
-      expect(new Int32(-1).toString(), "-1");
-      expect(new Int32(1000).toString(), "1000");
-      expect(new Int32(-1000).toString(), "-1000");
-      expect(new Int32(123456789).toString(), "123456789");
-      expect(new Int32(2147483647).toString(), "2147483647");
-      expect(new Int32(2147483648).toString(), "-2147483648");
-      expect(new Int32(2147483649).toString(), "-2147483647");
-      expect(new Int32(2147483650).toString(), "-2147483646");
-      expect(new Int32(-2147483648).toString(), "-2147483648");
-      expect(new Int32(-2147483649).toString(), "2147483647");
-      expect(new Int32(-2147483650).toString(), "2147483646");
-    });
-  });
-
-  group("toHexString", () {
-    test("returns hexadecimal string representation", () {
-      expect(new Int32(-1).toHexString(), "-1");
-      expect((new Int32(-1) >> 8).toHexString(), "-1");
-      expect((new Int32(-1) << 8).toHexString(), "-100");
-      expect(new Int32(123456789).toHexString(), "75bcd15");
-      expect(new Int32(-1).shiftRightUnsigned(8).toHexString(), "ffffff");
-    });
-  });
-
-  group("toRadixString", () {
-    test("returns base n string representation", () {
-      expect(new Int32(123456789).toRadixString(5), "223101104124");
-    });
-  });
-}
diff --git a/pkg/fixnum/test/int_64_test.dart b/pkg/fixnum/test/int_64_test.dart
deleted file mode 100644
index 1e17dae..0000000
--- a/pkg/fixnum/test/int_64_test.dart
+++ /dev/null
@@ -1,773 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library int64test;
-import 'package:fixnum/fixnum.dart';
-import 'package:unittest/unittest.dart';
-
-void main() {
-
-  argumentErrorTest(name, op, [receiver = Int64.ONE]) {
-    throwsArgumentErrorMentioning(substring) =>
-        throwsA((e) => e is ArgumentError && '$e'.contains(substring));
-
-    expect(() => op(receiver, null), throwsArgumentErrorMentioning('null'));
-    expect(() => op(receiver, 'foo'), throwsArgumentErrorMentioning(r'"foo"'));
-  }
-
-  group("is-tests", () {
-    test("isEven", () {
-      expect((-Int64.ONE).isEven, false);
-      expect(Int64.ZERO.isEven, true);
-      expect(Int64.ONE.isEven, false);
-      expect(Int64.TWO.isEven, true);
-    });
-    test("isMaxValue", () {
-      expect(Int64.MIN_VALUE.isMaxValue, false);
-      expect(Int64.ZERO.isMaxValue, false);
-      expect(Int64.MAX_VALUE.isMaxValue, true);
-    });
-    test("isMinValue", () {
-      expect(Int64.MIN_VALUE.isMinValue, true);
-      expect(Int64.ZERO.isMinValue, false);
-      expect(Int64.MAX_VALUE.isMinValue, false);
-    });
-    test("isNegative", () {
-      expect(Int64.MIN_VALUE.isNegative, true);
-      expect(Int64.ZERO.isNegative, false);
-      expect(Int64.ONE.isNegative, false);
-    });
-    test("isOdd", () {
-      expect((-Int64.ONE).isOdd, true);
-      expect(Int64.ZERO.isOdd, false);
-      expect(Int64.ONE.isOdd, true);
-      expect(Int64.TWO.isOdd, false);
-    });
-    test("isZero", () {
-      expect(Int64.MIN_VALUE.isZero, false);
-      expect(Int64.ZERO.isZero, true);
-      expect(Int64.MAX_VALUE.isZero, false);
-    });
-    test("bitLength", () {
-      expect(new Int64(-2).bitLength, 1);
-      expect((-Int64.ONE).bitLength, 0);
-      expect(Int64.ZERO.bitLength, 0);
-      expect((Int64.ONE << 21).bitLength, 22);
-      expect((Int64.ONE << 22).bitLength, 23);
-      expect((Int64.ONE << 43).bitLength, 44);
-      expect((Int64.ONE << 44).bitLength, 45);
-      expect(new Int64(2).bitLength, 2);
-      expect(Int64.MAX_VALUE.bitLength, 63);
-      expect(Int64.MIN_VALUE.bitLength, 63);
-    });
-  });
-
-  group("arithmetic operators", () {
-    Int64 n1 = new Int64(1234);
-    Int64 n2 = new Int64(9876);
-    Int64 n3 = new Int64(-1234);
-    Int64 n4 = new Int64(-9876);
-    Int64 n5 = new Int64.fromInts(0x12345678, 0xabcdabcd);
-    Int64 n6 = new Int64.fromInts(0x77773333, 0x22224444);
-
-    test("+", () {
-      expect(n1 + n2, new Int64(11110));
-      expect(n3 + n2, new Int64(8642));
-      expect(n3 + n4, new Int64(-11110));
-      expect(n5 + n6, new Int64.fromInts(0x89ab89ab, 0xcdeff011));
-      expect(Int64.MAX_VALUE + 1, Int64.MIN_VALUE);
-      argumentErrorTest("+", (a, b) => a + b);
-    });
-
-    test("-", () {
-      expect(n1 - n2, new Int64(-8642));
-      expect(n3 - n2, new Int64(-11110));
-      expect(n3 - n4, new Int64(8642));
-      expect(n5 - n6, new Int64.fromInts(0x9abd2345, 0x89ab6789));
-      expect(Int64.MIN_VALUE - 1, Int64.MAX_VALUE);
-      argumentErrorTest("-", (a, b) => a - b);
-    });
-
-    test("unary -", () {
-      expect(-n1, new Int64(-1234));
-      expect(-Int64.ZERO, Int64.ZERO);
-    });
-
-    test("*", () {
-      expect(new Int64(1111) * new Int64(3), new Int64(3333));
-      expect(new Int64(1111) * new Int64(-3), new Int64(-3333));
-      expect(new Int64(-1111) * new Int64(3), new Int64(-3333));
-      expect(new Int64(-1111) * new Int64(-3), new Int64(3333));
-      expect(new Int64(100) * Int64.ZERO, Int64.ZERO);
-
-      expect(new Int64.fromInts(0x12345678, 0x12345678) *
-          new Int64.fromInts(0x1234, 0x12345678),
-          new Int64.fromInts(0x7ff63f7c, 0x1df4d840));
-      expect(new Int64.fromInts(0xf2345678, 0x12345678) *
-          new Int64.fromInts(0x1234, 0x12345678),
-          new Int64.fromInts(0x7ff63f7c, 0x1df4d840));
-      expect(new Int64.fromInts(0xf2345678, 0x12345678) *
-          new Int64.fromInts(0xffff1234, 0x12345678),
-          new Int64.fromInts(0x297e3f7c, 0x1df4d840));
-
-      // RHS Int32
-      expect((new Int64(123456789) * new Int32(987654321)),
-          new Int64.fromInts(0x1b13114, 0xfbff5385));
-      expect((new Int64(123456789) * new Int32(987654321)),
-          new Int64.fromInts(0x1b13114, 0xfbff5385));
-
-      // Wraparound
-      expect((new Int64(123456789) * new Int64(987654321)),
-          new Int64.fromInts(0x1b13114, 0xfbff5385));
-
-      expect(Int64.MIN_VALUE * new Int64(2), Int64.ZERO);
-      expect(Int64.MIN_VALUE * new Int64(1), Int64.MIN_VALUE);
-      expect(Int64.MIN_VALUE * new Int64(-1), Int64.MIN_VALUE);
-      argumentErrorTest("*", (a, b) => a * b);
-    });
-
-    test("~/", () {
-      Int64 deadBeef = new Int64.fromInts(0xDEADBEEF, 0xDEADBEEF);
-      Int64 ten = new Int64(10);
-
-      expect(deadBeef ~/ ten, new Int64.fromInts(0xfcaaf97e, 0x63115fe5));
-      expect(Int64.ONE ~/ Int64.TWO, Int64.ZERO);
-      expect(Int64.MAX_VALUE ~/ Int64.TWO,
-          new Int64.fromInts(0x3fffffff, 0xffffffff));
-      expect(Int64.ZERO ~/ new Int64(1000), Int64.ZERO);
-      expect(Int64.MIN_VALUE ~/ Int64.MIN_VALUE, Int64.ONE);
-      expect(new Int64(1000) ~/ Int64.MIN_VALUE, Int64.ZERO);
-      expect(Int64.MIN_VALUE ~/ new Int64(8192), new Int64(-1125899906842624));
-      expect(Int64.MIN_VALUE ~/ new Int64(8193), new Int64(-1125762484664320));
-      expect(new Int64(-1000) ~/ new Int64(8192), Int64.ZERO);
-      expect(new Int64(-1000) ~/ new Int64(8193), Int64.ZERO);
-      expect(new Int64(-1000000000) ~/ new Int64(8192), new Int64(-122070));
-      expect(new Int64(-1000000000) ~/ new Int64(8193), new Int64(-122055));
-      expect(new Int64(1000000000) ~/ new Int64(8192), new Int64(122070));
-      expect(new Int64(1000000000) ~/ new Int64(8193), new Int64(122055));
-      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00000000, 0x00000400),
-          new Int64.fromInts(0x1fffff, 0xffffffff));
-      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00000000, 0x00040000),
-          new Int64.fromInts(0x1fff, 0xffffffff));
-      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00000000, 0x04000000),
-          new Int64.fromInts(0x1f, 0xffffffff));
-      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00000004, 0x00000000),
-          new Int64(536870911));
-      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00000400, 0x00000000),
-          new Int64(2097151));
-      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00040000, 0x00000000),
-          new Int64(8191));
-      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x04000000, 0x00000000),
-          new Int64(31));
-      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00000000, 0x00000300),
-          new Int64.fromInts(0x2AAAAA, 0xAAAAAAAA));
-      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00000000, 0x30000000),
-          new Int64.fromInts(0x2, 0xAAAAAAAA));
-      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00300000, 0x00000000),
-          new Int64(0x2AA));
-      expect(Int64.MAX_VALUE ~/ new Int64(0x123456),
-          new Int64.fromInts(0x708, 0x002E9501));
-      expect(Int64.MAX_VALUE % new Int64(0x123456), new Int64(0x3BDA9));
-      expect(new Int64(5) ~/ new Int64(5), Int64.ONE);
-      expect(new Int64(1000) ~/ new Int64(3), new Int64(333));
-      expect(new Int64(1000) ~/ new Int64(-3), new Int64(-333));
-      expect(new Int64(-1000) ~/ new Int64(3), new Int64(-333));
-      expect(new Int64(-1000) ~/ new Int64(-3), new Int64(333));
-      expect(new Int64(3) ~/ new Int64(1000), Int64.ZERO);
-      expect(new Int64.fromInts( 0x12345678, 0x12345678) ~/
-          new Int64.fromInts(0x0, 0x123),
-          new Int64.fromInts(0x1003d0, 0xe84f5ae8));
-      expect(new Int64.fromInts(0x12345678, 0x12345678) ~/
-          new Int64.fromInts(0x1234, 0x12345678),
-          new Int64.fromInts(0x0, 0x10003));
-      expect(new Int64.fromInts(0xf2345678, 0x12345678) ~/
-          new Int64.fromInts(0x1234, 0x12345678),
-          new Int64.fromInts(0xffffffff, 0xffff3dfe));
-      expect(new Int64.fromInts(0xf2345678, 0x12345678) ~/
-          new Int64.fromInts(0xffff1234, 0x12345678),
-          new Int64.fromInts(0x0, 0xeda));
-      expect(new Int64(829893893) ~/ new Int32(1919), new Int32(432461));
-      expect(new Int64(829893893) ~/ new Int64(1919), new Int32(432461));
-      expect(new Int64(829893893) ~/ 1919, new Int32(432461));
-      expect(() => new Int64(1) ~/ Int64.ZERO,
-          throwsA(new isInstanceOf<IntegerDivisionByZeroException>()));
-      expect(Int64.MIN_VALUE ~/ new Int64(2),
-          new Int64.fromInts(0xc0000000, 0x00000000));
-      expect(Int64.MIN_VALUE ~/ new Int64(1), Int64.MIN_VALUE);
-      expect(Int64.MIN_VALUE ~/ new Int64(-1), Int64.MIN_VALUE);
-      expect(() => new Int64(17) ~/ Int64.ZERO, throws);
-      argumentErrorTest("~/", (a, b) => a ~/ b);
-    });
-
-    test("%", () {
-      // Define % as Euclidean mod, with positive result for all arguments
-      expect(Int64.ZERO % new Int64(1000), Int64.ZERO);
-      expect(Int64.MIN_VALUE % Int64.MIN_VALUE, Int64.ZERO);
-      expect(new Int64(1000) % Int64.MIN_VALUE, new Int64(1000));
-      expect(Int64.MIN_VALUE % new Int64(8192), Int64.ZERO);
-      expect(Int64.MIN_VALUE % new Int64(8193), new Int64(6145));
-      expect(new Int64(-1000) % new Int64(8192), new Int64(7192));
-      expect(new Int64(-1000) % new Int64(8193), new Int64(7193));
-      expect(new Int64(-1000000000) % new Int64(8192), new Int64(5632));
-      expect(new Int64(-1000000000) % new Int64(8193), new Int64(4808));
-      expect(new Int64(1000000000) % new Int64(8192), new Int64(2560));
-      expect(new Int64(1000000000) % new Int64(8193), new Int64(3385));
-      expect(Int64.MAX_VALUE % new Int64.fromInts(0x00000000, 0x00000400),
-          new Int64.fromInts(0x0, 0x3ff));
-      expect(Int64.MAX_VALUE % new Int64.fromInts(0x00000000, 0x00040000),
-          new Int64.fromInts(0x0, 0x3ffff));
-      expect(Int64.MAX_VALUE % new Int64.fromInts(0x00000000, 0x04000000),
-          new Int64.fromInts(0x0, 0x3ffffff));
-      expect(Int64.MAX_VALUE % new Int64.fromInts(0x00000004, 0x00000000),
-          new Int64.fromInts(0x3, 0xffffffff));
-      expect(Int64.MAX_VALUE % new Int64.fromInts(0x00000400, 0x00000000),
-          new Int64.fromInts(0x3ff, 0xffffffff));
-      expect(Int64.MAX_VALUE % new Int64.fromInts(0x00040000, 0x00000000),
-          new Int64.fromInts(0x3ffff, 0xffffffff));
-      expect(Int64.MAX_VALUE % new Int64.fromInts(0x04000000, 0x00000000),
-          new Int64.fromInts(0x3ffffff, 0xffffffff));
-      expect(new Int64(0x12345678).remainder(new Int64(0x22)),
-          new Int64(0x12345678.remainder(0x22)));
-      expect(new Int64(0x12345678).remainder(new Int64(-0x22)),
-          new Int64(0x12345678.remainder(-0x22)));
-      expect(new Int64(-0x12345678).remainder(new Int64(-0x22)),
-          new Int64(-0x12345678.remainder(-0x22)));
-      expect(new Int64(-0x12345678).remainder(new Int64(0x22)),
-          new Int64(-0x12345678.remainder(0x22)));
-      expect(new Int32(0x12345678).remainder(new Int64(0x22)),
-          new Int64(0x12345678.remainder(0x22)));
-      argumentErrorTest("%", (a, b) => a % b);
-    });
-
-    test("clamp", () {
-      Int64 val = new Int64(17);
-      expect(val.clamp(20, 30), new Int64(20));
-      expect(val.clamp(10, 20), new Int64(17));
-      expect(val.clamp(10, 15), new Int64(15));
-
-      expect(val.clamp(new Int32(20), new Int32(30)), new Int64(20));
-      expect(val.clamp(new Int32(10), new Int32(20)), new Int64(17));
-      expect(val.clamp(new Int32(10), new Int32(15)), new Int64(15));
-
-      expect(val.clamp(new Int64(20), new Int64(30)), new Int64(20));
-      expect(val.clamp(new Int64(10), new Int64(20)), new Int64(17));
-      expect(val.clamp(new Int64(10), new Int64(15)), new Int64(15));
-      expect(val.clamp(Int64.MIN_VALUE, new Int64(30)), new Int64(17));
-      expect(val.clamp(new Int64(10), Int64.MAX_VALUE), new Int64(17));
-
-      expect(() => val.clamp(1, 'b'), throwsA(isArgumentError));
-      expect(() => val.clamp('a', 1), throwsA(isArgumentError));
-    });
-  });
-
-  group("comparison operators", () {
-    Int64 largeNeg = new Int64.fromInts(0x82341234, 0x0);
-    Int64 largePos = new Int64.fromInts(0x12341234, 0x0);
-    Int64 largePosPlusOne = largePos + new Int64(1);
-
-    test("<", () {
-      expect(new Int64(10) < new Int64(11), true);
-      expect(new Int64(10) < new Int64(10), false);
-      expect(new Int64(10) < new Int64(9), false);
-      expect(new Int64(10) < new Int32(11), true);
-      expect(new Int64(10) < new Int32(10), false);
-      expect(new Int64(10) < new Int32(9), false);
-      expect(new Int64(-10) < new Int64(-11), false);
-      expect(Int64.MIN_VALUE < Int64.ZERO, true);
-      expect(largeNeg < largePos, true);
-      expect(largePos < largePosPlusOne, true);
-      expect(largePos < largePos, false);
-      expect(largePosPlusOne < largePos, false);
-      expect(Int64.MIN_VALUE < Int64.MAX_VALUE, true);
-      expect(Int64.MAX_VALUE < Int64.MIN_VALUE, false);
-      argumentErrorTest("<", (a, b) => a < b);
-    });
-
-    test("<=", () {
-      expect(new Int64(10) <= new Int64(11), true);
-      expect(new Int64(10) <= new Int64(10), true);
-      expect(new Int64(10) <= new Int64(9), false);
-      expect(new Int64(10) <= new Int32(11), true);
-      expect(new Int64(10) <= new Int32(10), true);
-      expect(new Int64(10) <= new Int64(9), false);
-      expect(new Int64(-10) <= new Int64(-11), false);
-      expect(new Int64(-10) <= new Int64(-10), true);
-      expect(largeNeg <= largePos, true);
-      expect(largePos <= largeNeg, false);
-      expect(largePos <= largePosPlusOne, true);
-      expect(largePos <= largePos, true);
-      expect(largePosPlusOne <= largePos, false);
-      expect(Int64.MIN_VALUE <= Int64.MAX_VALUE, true);
-      expect(Int64.MAX_VALUE <= Int64.MIN_VALUE, false);
-      argumentErrorTest("<=", (a, b) => a <= b);
-    });
-
-    test("==", () {
-      expect(new Int64(10) == new Int64(11), false);
-      expect(new Int64(10) == new Int64(10), true);
-      expect(new Int64(10) == new Int64(9), false);
-      expect(new Int64(10) == new Int32(11), false);
-      expect(new Int64(10) == new Int32(10), true);
-      expect(new Int64(10) == new Int32(9), false);
-      expect(new Int64(-10) == new Int64(-10), true);
-      expect(new Int64(-10) != new Int64(-10), false);
-      expect(largePos == largePos, true);
-      expect(largePos == largePosPlusOne, false);
-      expect(largePosPlusOne == largePos, false);
-      expect(Int64.MIN_VALUE == Int64.MAX_VALUE, false);
-      expect(new Int64(17) == new Object(), false);
-      expect(new Int64(17) == null, false);
-    });
-
-    test(">=", () {
-      expect(new Int64(10) >= new Int64(11), false);
-      expect(new Int64(10) >= new Int64(10), true);
-      expect(new Int64(10) >= new Int64(9), true);
-      expect(new Int64(10) >= new Int32(11), false);
-      expect(new Int64(10) >= new Int32(10), true);
-      expect(new Int64(10) >= new Int32(9), true);
-      expect(new Int64(-10) >= new Int64(-11), true);
-      expect(new Int64(-10) >= new Int64(-10), true);
-      expect(largePos >= largeNeg, true);
-      expect(largeNeg >= largePos, false);
-      expect(largePos >= largePosPlusOne, false);
-      expect(largePos >= largePos, true);
-      expect(largePosPlusOne >= largePos, true);
-      expect(Int64.MIN_VALUE >= Int64.MAX_VALUE, false);
-      expect(Int64.MAX_VALUE >= Int64.MIN_VALUE, true);
-      argumentErrorTest(">=", (a, b) => a >= b);
-    });
-
-    test(">", () {
-      expect(new Int64(10) > new Int64(11), false);
-      expect(new Int64(10) > new Int64(10), false);
-      expect(new Int64(10) > new Int64(9), true);
-      expect(new Int64(10) > new Int32(11), false);
-      expect(new Int64(10) > new Int32(10), false);
-      expect(new Int64(10) > new Int32(9), true);
-      expect(new Int64(-10) > new Int64(-11), true);
-      expect(new Int64(10) > new Int64(-11), true);
-      expect(new Int64(-10) > new Int64(11), false);
-      expect(largePos > largeNeg, true);
-      expect(largeNeg > largePos, false);
-      expect(largePos > largePosPlusOne, false);
-      expect(largePos > largePos, false);
-      expect(largePosPlusOne > largePos, true);
-      expect(Int64.ZERO > Int64.MIN_VALUE, true);
-      expect(Int64.MIN_VALUE > Int64.MAX_VALUE, false);
-      expect(Int64.MAX_VALUE > Int64.MIN_VALUE, true);
-      argumentErrorTest(">", (a, b) => a > b);
-    });
-  });
-
-  group("bitwise operators", () {
-    Int64 n1 = new Int64(1234);
-    Int64 n2 = new Int64(9876);
-    Int64 n3 = new Int64(-1234);
-    Int64 n4 = new Int64(0x1234) << 32;
-    Int64 n5 = new Int64(0x9876) << 32;
-
-    test("&", () {
-      expect(n1 & n2, new Int64(1168));
-      expect(n3 & n2, new Int64(8708));
-      expect(n4 & n5, new Int64(0x1034) << 32);
-      expect(() => n1 & null, throwsArgumentError);
-      argumentErrorTest("&", (a, b) => a & b);
-    });
-
-    test("|", () {
-      expect(n1 | n2, new Int64(9942));
-      expect(n3 | n2, new Int64(-66));
-      expect(n4 | n5, new Int64(0x9a76) << 32);
-      expect(() => n1 | null, throwsArgumentError);
-      argumentErrorTest("|", (a, b) => a | b);
-    });
-
-    test("^", () {
-      expect(n1 ^ n2, new Int64(8774));
-      expect(n3 ^ n2, new Int64(-8774));
-      expect(n4 ^ n5, new Int64(0x8a42) << 32);
-      expect(() => n1 ^ null, throwsArgumentError);
-      argumentErrorTest("^", (a, b) => a ^ b);
-    });
-
-    test("~", () {
-      expect(-new Int64(1), new Int64(-1));
-      expect(-new Int64(-1), new Int64(1));
-      expect(-Int64.MIN_VALUE, Int64.MIN_VALUE);
-
-      expect(~n1, new Int64(-1235));
-      expect(~n2, new Int64(-9877));
-      expect(~n3, new Int64(1233));
-      expect(~n4, new Int64.fromInts(0xffffedcb, 0xffffffff));
-      expect(~n5, new Int64.fromInts(0xffff6789, 0xffffffff));
-    });
-  });
-
-  group("bitshift operators", () {
-    test("<<", () {
-      expect(new Int64.fromInts(0x12341234, 0x45674567) << 10,
-          new Int64.fromInts(0xd048d115, 0x9d159c00));
-      expect(new Int64.fromInts(0x92341234, 0x45674567) << 10,
-          new Int64.fromInts(0xd048d115, 0x9d159c00));
-      expect(new Int64(-1) << 5, new Int64(-32));
-      expect(new Int64(-1) << 0, new Int64(-1));
-      expect(() => new Int64(17) << -1, throwsArgumentError);
-      expect(() => new Int64(17) << null, throws);
-    });
-
-    test(">>", () {
-      expect((Int64.MIN_VALUE >> 13).toString(), "-1125899906842624");
-      expect(new Int64.fromInts(0x12341234, 0x45674567) >> 10,
-          new Int64.fromInts(0x48d04, 0x8d1159d1));
-      expect(new Int64.fromInts(0x92341234, 0x45674567) >> 10,
-          new Int64.fromInts(0xffe48d04, 0x8d1159d1));
-      expect(new Int64.fromInts(0xFFFFFFF, 0xFFFFFFFF) >> 34,
-          new Int64(67108863));
-      for (int n = 0; n <= 66; n++) {
-        expect(new Int64(-1) >> n, new Int64(-1));
-      }
-      expect(new Int64.fromInts(0x72345678, 0x9abcdef0) >> 8,
-          new Int64.fromInts(0x00723456, 0x789abcde));
-      expect(new Int64.fromInts(0x72345678, 0x9abcdef0) >> 16,
-          new Int64.fromInts(0x00007234, 0x56789abc));
-      expect(new Int64.fromInts(0x72345678, 0x9abcdef0) >> 24,
-          new Int64.fromInts(0x00000072, 0x3456789a));
-      expect(new Int64.fromInts(0x72345678, 0x9abcdef0) >> 28,
-          new Int64.fromInts(0x00000007, 0x23456789));
-      expect(new Int64.fromInts(0x72345678, 0x9abcdef0) >> 32,
-          new Int64.fromInts(0x00000000, 0x72345678));
-      expect(new Int64.fromInts(0x72345678, 0x9abcdef0) >> 36,
-          new Int64.fromInts(0x00000000, 0x07234567));
-      expect(new Int64.fromInts(0x72345678, 0x9abcdef0) >> 40,
-          new Int64.fromInts(0x00000000, 0x00723456));
-      expect(new Int64.fromInts(0x72345678, 0x9abcde00) >> 44,
-          new Int64.fromInts(0x00000000, 0x00072345));
-      expect(new Int64.fromInts(0x72345678, 0x9abcdef0) >> 48,
-          new Int64.fromInts(0x00000000, 0x00007234));
-      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 8,
-          new Int64.fromInts(0xff923456, 0x789abcde));
-      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 16,
-          new Int64.fromInts(0xffff9234, 0x56789abc));
-      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 24,
-          new Int64.fromInts(0xffffff92, 0x3456789a));
-      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 28,
-          new Int64.fromInts(0xfffffff9, 0x23456789));
-      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 32,
-          new Int64.fromInts(0xffffffff, 0x92345678));
-      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 36,
-          new Int64.fromInts(0xffffffff, 0xf9234567));
-      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 40,
-          new Int64.fromInts(0xffffffff, 0xff923456));
-      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 44,
-          new Int64.fromInts(0xffffffff, 0xfff92345));
-      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 48,
-          new Int64.fromInts(0xffffffff, 0xffff9234));
-      expect(() => new Int64(17) >> -1, throwsArgumentError);
-      expect(() => new Int64(17) >> null, throws);
-    });
-
-    test("shiftRightUnsigned", () {
-      expect(new Int64.fromInts(0x12341234, 0x45674567).shiftRightUnsigned(10),
-          new Int64.fromInts(0x48d04, 0x8d1159d1));
-      expect(new Int64.fromInts(0x92341234, 0x45674567).shiftRightUnsigned(10),
-          new Int64.fromInts(0x248d04, 0x8d1159d1));
-      expect(new Int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(8),
-          new Int64.fromInts(0x00723456, 0x789abcde));
-      expect(new Int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(16),
-          new Int64.fromInts(0x00007234, 0x56789abc));
-      expect(new Int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(24),
-          new Int64.fromInts(0x00000072, 0x3456789a));
-      expect(new Int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(28),
-          new Int64.fromInts(0x00000007, 0x23456789));
-      expect(new Int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(32),
-          new Int64.fromInts(0x00000000, 0x72345678));
-      expect(new Int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(36),
-          new Int64.fromInts(0x00000000, 0x07234567));
-      expect(new Int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(40),
-          new Int64.fromInts(0x00000000, 0x00723456));
-      expect(new Int64.fromInts(0x72345678, 0x9abcde00).shiftRightUnsigned(44),
-          new Int64.fromInts(0x00000000, 0x00072345));
-      expect(new Int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(48),
-          new Int64.fromInts(0x00000000, 0x00007234));
-      expect(new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(8),
-          new Int64.fromInts(0x00923456, 0x789abcde));
-      expect(new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(16),
-          new Int64.fromInts(0x00009234, 0x56789abc));
-      expect(new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(24),
-          new Int64.fromInts(0x00000092, 0x3456789a));
-      expect(new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(28),
-          new Int64.fromInts(0x00000009, 0x23456789));
-      expect(new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(32),
-          new Int64.fromInts(0x00000000, 0x92345678));
-      expect(new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(36),
-          new Int64.fromInts(0x00000000, 0x09234567));
-      expect(new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(40),
-          new Int64.fromInts(0x00000000, 0x00923456));
-      expect(new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(44),
-          new Int64.fromInts(0x00000000, 0x00092345));
-      expect(new Int64.fromInts(0x00000000, 0x00009234),
-          new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(48));
-      expect(() => new Int64(17).shiftRightUnsigned(-1),
-          throwsArgumentError);
-      expect(() => new Int64(17).shiftRightUnsigned(null), throws);
-    });
-
-    test("overflow", () {
-      expect((new Int64(1) << 63) >> 1,
-          -new Int64.fromInts(0x40000000, 0x00000000));
-      expect((new Int64(-1) << 32) << 32, new Int64(0));
-      expect(Int64.MIN_VALUE << 0, Int64.MIN_VALUE);
-      expect(Int64.MIN_VALUE << 1, new Int64(0));
-      expect((-new Int64.fromInts(8, 0)) >> 1,
-          new Int64.fromInts(0xfffffffc, 0x00000000));
-      expect((-new Int64.fromInts(8, 0)).shiftRightUnsigned(1),
-          new Int64.fromInts(0x7ffffffc, 0x0));
-    });
-  });
-
-  group("conversions", () {
-    test("toSigned", () {
-      expect((Int64.ONE << 44).toSigned(46), Int64.ONE << 44);
-      expect((Int64.ONE << 44).toSigned(45), -(Int64.ONE << 44));
-      expect((Int64.ONE << 22).toSigned(24), Int64.ONE << 22);
-      expect((Int64.ONE << 22).toSigned(23), -(Int64.ONE << 22));
-      expect(Int64.ONE.toSigned(2), Int64.ONE);
-      expect(Int64.ONE.toSigned(1), -Int64.ONE);
-      expect(Int64.MAX_VALUE.toSigned(64), Int64.MAX_VALUE);
-      expect(Int64.MIN_VALUE.toSigned(64), Int64.MIN_VALUE);
-      expect(Int64.MAX_VALUE.toSigned(63), -Int64.ONE);
-      expect(Int64.MIN_VALUE.toSigned(63), Int64.ZERO);
-      expect(() => Int64.ONE.toSigned(0), throwsRangeError);
-      expect(() => Int64.ONE.toSigned(65), throwsRangeError);
-    });
-    test("toUnsigned", () {
-      expect((Int64.ONE << 44).toUnsigned(45), Int64.ONE << 44);
-      expect((Int64.ONE << 44).toUnsigned(44), Int64.ZERO);
-      expect((Int64.ONE << 22).toUnsigned(23), Int64.ONE << 22);
-      expect((Int64.ONE << 22).toUnsigned(22), Int64.ZERO);
-      expect(Int64.ONE.toUnsigned(1), Int64.ONE);
-      expect(Int64.ONE.toUnsigned(0), Int64.ZERO);
-      expect(Int64.MAX_VALUE.toUnsigned(64), Int64.MAX_VALUE);
-      expect(Int64.MIN_VALUE.toUnsigned(64), Int64.MIN_VALUE);
-      expect(Int64.MAX_VALUE.toUnsigned(63), Int64.MAX_VALUE);
-      expect(Int64.MIN_VALUE.toUnsigned(63), Int64.ZERO);
-      expect(() => Int64.ONE.toUnsigned(-1), throwsRangeError);
-      expect(() => Int64.ONE.toUnsigned(65), throwsRangeError);
-    });
-    test("toDouble", () {
-      expect(new Int64(0).toDouble(), same(0.0));
-      expect(new Int64(100).toDouble(), same(100.0));
-      expect(new Int64(-100).toDouble(), same(-100.0));
-      expect(new Int64(2147483647).toDouble(), same(2147483647.0));
-      expect(new Int64(2147483648).toDouble(), same(2147483648.0));
-      expect(new Int64(-2147483647).toDouble(), same(-2147483647.0));
-      expect(new Int64(-2147483648).toDouble(), same(-2147483648.0));
-      expect(new Int64(4503599627370495).toDouble(), same(4503599627370495.0));
-      expect(new Int64(4503599627370496).toDouble(), same(4503599627370496.0));
-      expect(new Int64(-4503599627370495).toDouble(),
-          same(-4503599627370495.0));
-      expect(new Int64(-4503599627370496).toDouble(),
-          same(-4503599627370496.0));
-      expect(Int64.parseInt("-10000000000000000").toDouble().toStringAsFixed(1),
-          "-10000000000000000.0");
-      expect(Int64.parseInt("-10000000000000001").toDouble().toStringAsFixed(1),
-          "-10000000000000000.0");
-      expect(Int64.parseInt("-10000000000000002").toDouble().toStringAsFixed(1),
-          "-10000000000000002.0");
-      expect(Int64.parseInt("-10000000000000003").toDouble().toStringAsFixed(1),
-          "-10000000000000004.0");
-      expect(Int64.parseInt("-10000000000000004").toDouble().toStringAsFixed(1),
-          "-10000000000000004.0");
-      expect(Int64.parseInt("-10000000000000005").toDouble().toStringAsFixed(1),
-          "-10000000000000004.0");
-      expect(Int64.parseInt("-10000000000000006").toDouble().toStringAsFixed(1),
-          "-10000000000000006.0");
-      expect(Int64.parseInt("-10000000000000007").toDouble().toStringAsFixed(1),
-          "-10000000000000008.0");
-      expect(Int64.parseInt("-10000000000000008").toDouble().toStringAsFixed(1),
-          "-10000000000000008.0");
-    });
-
-    test("toInt", () {
-      expect(new Int64(0).toInt(), 0);
-      expect(new Int64(100).toInt(), 100);
-      expect(new Int64(-100).toInt(), -100);
-      expect(new Int64(2147483647).toInt(), 2147483647);
-      expect(new Int64(2147483648).toInt(), 2147483648);
-      expect(new Int64(-2147483647).toInt(), -2147483647);
-      expect(new Int64(-2147483648).toInt(), -2147483648);
-      expect(new Int64(4503599627370495).toInt(), 4503599627370495);
-      expect(new Int64(4503599627370496).toInt(), 4503599627370496);
-      expect(new Int64(-4503599627370495).toInt(), -4503599627370495);
-      expect(new Int64(-4503599627370496).toInt(), -4503599627370496);
-      expect(Int64.parseInt("-10000000000000000").toInt(),
-          same(-10000000000000000));
-      expect(Int64.parseInt("-10000000000000001").toInt(),
-          same(-10000000000000001));
-      expect(Int64.parseInt("-10000000000000002").toInt(),
-          same(-10000000000000002));
-      expect(Int64.parseInt("-10000000000000003").toInt(),
-          same(-10000000000000003));
-      expect(Int64.parseInt("-10000000000000004").toInt(),
-          same(-10000000000000004));
-      expect(Int64.parseInt("-10000000000000005").toInt(),
-          same(-10000000000000005));
-      expect(Int64.parseInt("-10000000000000006").toInt(),
-          same(-10000000000000006));
-      expect(Int64.parseInt("-10000000000000007").toInt(),
-          same(-10000000000000007));
-      expect(Int64.parseInt("-10000000000000008").toInt(),
-          same(-10000000000000008));
-    });
-
-    test("toInt32", () {
-      expect(new Int64(0).toInt32(), new Int32(0));
-      expect(new Int64(1).toInt32(), new Int32(1));
-      expect(new Int64(-1).toInt32(), new Int32(-1));
-      expect(new Int64(2147483647).toInt32(), new Int32(2147483647));
-      expect(new Int64(2147483648).toInt32(), new Int32(-2147483648));
-      expect(new Int64(2147483649).toInt32(), new Int32(-2147483647));
-      expect(new Int64(2147483650).toInt32(), new Int32(-2147483646));
-      expect(new Int64(-2147483648).toInt32(), new Int32(-2147483648));
-      expect(new Int64(-2147483649).toInt32(), new Int32(2147483647));
-      expect(new Int64(-2147483650).toInt32(), new Int32(2147483646));
-      expect(new Int64(-2147483651).toInt32(), new Int32(2147483645));
-    });
-  });
-
-  test("JavaScript 53-bit integer boundary", () {
-    Int64 _factorial(Int64 n) {
-      if (n.isZero) {
-        return new Int64(1);
-      } else {
-        return n * _factorial(n - new Int64(1));
-      }
-    }
-    Int64 fact18 = _factorial(new Int64(18));
-    Int64 fact17 = _factorial(new Int64(17));
-    expect(fact18 ~/ fact17, new Int64(18));
-  });
-
-  test("min, max values", () {
-    expect(new Int64(1) << 63, Int64.MIN_VALUE);
-    expect(-(Int64.MIN_VALUE + new Int64(1)), Int64.MAX_VALUE);
-  });
-
-  group("parse", () {
-    test("parseRadix10", () {
-      checkInt(int x) {
-        expect(Int64.parseRadix('$x', 10), new Int64(x));
-      }
-      checkInt(0);
-      checkInt(1);
-      checkInt(-1);
-      checkInt(1000);
-      checkInt(12345678);
-      checkInt(-12345678);
-      checkInt(2147483647);
-      checkInt(2147483648);
-      checkInt(-2147483647);
-      checkInt(-2147483648);
-      checkInt(4294967295);
-      checkInt(4294967296);
-      checkInt(-4294967295);
-      checkInt(-4294967296);
-    });
-
-    test("parseRadix", () {
-      check(String s, int r, String x) {
-        expect(Int64.parseRadix(s, r).toString(), x);
-      }
-      check('ghoul', 36, '27699213');
-      check('ghoul', 35, '24769346');
-      // Min and max value.
-      check("-9223372036854775808", 10, "-9223372036854775808");
-      check("9223372036854775807", 10, "9223372036854775807");
-      // Overflow during parsing.
-      check("9223372036854775808", 10, "-9223372036854775808");
-
-      expect(() => Int64.parseRadix('0', 1), throwsRangeError);
-      expect(() => Int64.parseRadix('0', 37), throwsRangeError);
-      expect(() => Int64.parseRadix('xyzzy', -1), throwsRangeError);
-      expect(() => Int64.parseRadix('xyzzy', 10), throwsFormatException);
-    });
-
-    test("parseRadixN", () {
-      check(String s, int r) {
-        expect(Int64.parseRadix(s, r).toRadixString(r), s);
-      }
-      check("2ppp111222333", 33);  // This value & radix requires three chunks.
-    });
-  });
-
-  group("string representation", () {
-    test("toString", () {
-      expect(new Int64(0).toString(), "0");
-      expect(new Int64(1).toString(), "1");
-      expect(new Int64(-1).toString(), "-1");
-      expect(new Int64(-10).toString(), "-10");
-      expect(Int64.MIN_VALUE.toString(), "-9223372036854775808");
-      expect(Int64.MAX_VALUE.toString(), "9223372036854775807");
-
-      int top = 922337201;
-      int bottom = 967490662;
-      Int64 fullnum = (new Int64(1000000000) * new Int64(top)) +
-          new Int64(bottom);
-      expect(fullnum.toString(), "922337201967490662");
-      expect((-fullnum).toString(), "-922337201967490662");
-      expect(new Int64(123456789).toString(), "123456789");
-    });
-
-    test("toHexString", () {
-      Int64 deadbeef12341234 = new Int64.fromInts(0xDEADBEEF, 0x12341234);
-      expect(Int64.ZERO.toHexString(), "0");
-      expect(deadbeef12341234.toHexString(), "DEADBEEF12341234");
-      expect(new Int64.fromInts(0x17678A7, 0xDEF01234).toHexString(),
-          "17678A7DEF01234");
-      expect(new Int64(123456789).toHexString(), "75BCD15");
-    });
-
-    test("toRadixString", () {
-      expect(new Int64(123456789).toRadixString(5), "223101104124");
-      expect(Int64.MIN_VALUE.toRadixString(2),
-          "-1000000000000000000000000000000000000000000000000000000000000000");
-      expect(Int64.MIN_VALUE.toRadixString(3),
-          "-2021110011022210012102010021220101220222");
-      expect(Int64.MIN_VALUE.toRadixString(4),
-          "-20000000000000000000000000000000");
-      expect(Int64.MIN_VALUE.toRadixString(5), "-1104332401304422434310311213");
-      expect(Int64.MIN_VALUE.toRadixString(6), "-1540241003031030222122212");
-      expect(Int64.MIN_VALUE.toRadixString(7), "-22341010611245052052301");
-      expect(Int64.MIN_VALUE.toRadixString(8), "-1000000000000000000000");
-      expect(Int64.MIN_VALUE.toRadixString(9), "-67404283172107811828");
-      expect(Int64.MIN_VALUE.toRadixString(10), "-9223372036854775808");
-      expect(Int64.MIN_VALUE.toRadixString(11), "-1728002635214590698");
-      expect(Int64.MIN_VALUE.toRadixString(12), "-41a792678515120368");
-      expect(Int64.MIN_VALUE.toRadixString(13), "-10b269549075433c38");
-      expect(Int64.MIN_VALUE.toRadixString(14), "-4340724c6c71dc7a8");
-      expect(Int64.MIN_VALUE.toRadixString(15), "-160e2ad3246366808");
-      expect(Int64.MIN_VALUE.toRadixString(16), "-8000000000000000");
-      expect(Int64.MAX_VALUE.toRadixString(2),
-          "111111111111111111111111111111111111111111111111111111111111111");
-      expect(Int64.MAX_VALUE.toRadixString(3),
-          "2021110011022210012102010021220101220221");
-      expect(Int64.MAX_VALUE.toRadixString(4),
-          "13333333333333333333333333333333");
-      expect(Int64.MAX_VALUE.toRadixString(5), "1104332401304422434310311212");
-      expect(Int64.MAX_VALUE.toRadixString(6), "1540241003031030222122211");
-      expect(Int64.MAX_VALUE.toRadixString(7), "22341010611245052052300");
-      expect(Int64.MAX_VALUE.toRadixString(8), "777777777777777777777");
-      expect(Int64.MAX_VALUE.toRadixString(9), "67404283172107811827");
-      expect(Int64.MAX_VALUE.toRadixString(10), "9223372036854775807");
-      expect(Int64.MAX_VALUE.toRadixString(11), "1728002635214590697");
-      expect(Int64.MAX_VALUE.toRadixString(12), "41a792678515120367");
-      expect(Int64.MAX_VALUE.toRadixString(13), "10b269549075433c37");
-      expect(Int64.MAX_VALUE.toRadixString(14), "4340724c6c71dc7a7");
-      expect(Int64.MAX_VALUE.toRadixString(15), "160e2ad3246366807");
-      expect(() => Int64.ZERO.toRadixString(1), throwsRangeError);
-      expect(() => Int64.ZERO.toRadixString(37), throwsRangeError);
-    });
-  });
-}
diff --git a/pkg/meta/CHANGELOG.md b/pkg/meta/CHANGELOG.md
index b7c6b01..474ddfe 100644
--- a/pkg/meta/CHANGELOG.md
+++ b/pkg/meta/CHANGELOG.md
@@ -1,3 +1,6 @@
+## 0.12.1
+* Fixed markdown in dartdocs.
+
 ## 0.12.0
 * Introduce `@optionalTypeArgs` annotation for classes whose type arguments are to be treated as optional.
 
diff --git a/pkg/meta/lib/meta.dart b/pkg/meta/lib/meta.dart
index b8142fd..ff0f9b0 100644
--- a/pkg/meta/lib/meta.dart
+++ b/pkg/meta/lib/meta.dart
@@ -24,6 +24,7 @@
 /// same annotation.
 ///
 /// Tools, such as the analyzer, can provide feedback if
+///
 /// * the annotation is associated with anything other than an instance method,
 ///   or
 /// * a method that has this annotation that can return anything other than a
@@ -35,6 +36,7 @@
 /// arguments to the constructor is not a compile-time constant.
 ///
 /// Tools, such as the analyzer, can provide feedback if
+///
 /// * the annotation is associated with anything other than a const constructor,
 ///   or
 /// * an invocation of a constructor that has this annotation is not invoked
@@ -50,6 +52,7 @@
 /// outside of the library that defines the annotated method.
 ///
 /// Tools, such as the analyzer, can provide feedback if
+///
 /// * the annotation is associated with anything other than an instance method,
 ///   or
 /// * a method that overrides a method that has this annotation can return
@@ -70,6 +73,7 @@
 /// that `m` should only be invoked on `this`, whether explicitly or implicitly.
 ///
 /// Tools, such as the analyzer, can provide feedback if
+///
 /// * the annotation is associated with anything other than an instance member,
 ///   or
 /// * an invocation of a member that has this annotation is used outside of an
@@ -84,6 +88,7 @@
 /// optional parameter.
 ///
 /// Tools, such as the analyzer, can provide feedback if
+///
 /// * the annotation is associated with anything other than a named parameter,
 /// * the annotation is associated with a named parameter in a method `m1` that
 ///   overrides a method `m0` and `m0` defines a named parameter with the same
diff --git a/pkg/meta/pubspec.yaml b/pkg/meta/pubspec.yaml
index d2f5506..82a1677 100644
--- a/pkg/meta/pubspec.yaml
+++ b/pkg/meta/pubspec.yaml
@@ -1,5 +1,5 @@
 name: meta
-version: 0.12.0
+version: 0.12.1
 author: Dart Team <misc@dartlang.org>
 homepage: http://www.dartlang.org
 description: >
diff --git a/pkg/pkg_files.gyp b/pkg/pkg_files.gyp
index afb09cf..9dd13e3 100644
--- a/pkg/pkg_files.gyp
+++ b/pkg/pkg_files.gyp
@@ -19,7 +19,9 @@
           'action_name': 'make_pkg_files_stamp',
           'inputs': [
             '../tools/create_timestamp_file.py',
-            '<!@(["python", "../tools/list_files.py", "\\.dart$", "."])',
+            '<!@(["python", "../tools/list_files.py",'
+                '"^(?!.*/test/).*(?<!_test)[.]dart$",'
+                '"."])',
             '<(SHARED_INTERMEDIATE_DIR)/third_party_pkg_files_1.stamp',
             '<(SHARED_INTERMEDIATE_DIR)/third_party_pkg_files_2.stamp',
             '<(SHARED_INTERMEDIATE_DIR)/third_party_pkg_files_3.stamp',
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 6e987c4..bd091d9a 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -12,6 +12,16 @@
   # while themselves doing a Debug build.
   dart_debug = false
 
+  # Set the runtime mode. This affects how the runtime is built and what
+  # features it has. Valid values are:
+  # 'develop' (the default) - VM is built to run as a JIT with all development
+  # features enabled.
+  # 'profile' - The VM is built to run with AOT compiled code with only the
+  # CPU profiling features enabled.
+  # 'release' - The VM is built to run with AOT compiled code with no developer
+  # features enabled.
+  dart_runtime_mode = "develop"
+
   # Explicitly set the target architecture in case of precompilation. Leaving
   # this unspecified results in automatic target architecture detection.
   # Available options are: arm, arm64, mips, x64 and ia32
@@ -24,6 +34,58 @@
   ]
 }
 
+# Controls PRODUCT #define.
+config("dart_product_config") {
+  defines = []
+
+  if ((dart_runtime_mode != "develop") &&
+      (dart_runtime_mode != "profile") &&
+      (dart_runtime_mode != "release")) {
+    print("Invalid |dart_runtime_mode|")
+    assert(false)
+  }
+
+  if (dart_runtime_mode == "release") {
+    if (dart_debug) {
+      print("Debug and release mode are mutually exclusive.")
+    }
+    assert(!dart_debug)
+    defines += ["PRODUCT"]
+  }
+}
+
+# Controls DART_PRECOMPILED_RUNTIME #define.
+config("dart_precompiled_runtime_config") {
+  defines = []
+
+  if ((dart_runtime_mode != "develop") &&
+      (dart_runtime_mode != "profile") &&
+      (dart_runtime_mode != "release")) {
+    print("Invalid |dart_runtime_mode|")
+    assert(false)
+  }
+
+  if (dart_runtime_mode == "release") {
+    if (dart_debug) {
+      print("Debug and release mode are mutually exclusive.")
+    }
+    assert(!dart_debug)
+    defines += ["DART_PRECOMPILED_RUNTIME"]
+  } else if (dart_runtime_mode == "profile") {
+    if (dart_debug) {
+      print("Debug and profile mode are mutually exclusive.")
+    }
+    assert(!dart_debug)
+    defines += ["DART_PRECOMPILED_RUNTIME"]
+  }
+}
+
+# Controls DART_PRECOMPILER #define.
+config("dart_precompiler_config") {
+  defines = []
+  defines += ["DART_PRECOMPILER"]
+}
+
 config("dart_config") {
   defines = []
 
@@ -38,69 +100,8 @@
       defines += [ "TARGET_ARCH_X64" ]
     } else if (dart_target_arch == "ia32") {
       defines += [ "TARGET_ARCH_IA32" ]
-    } else  {
-      print("Invalid |dart_target_arch|")
-      assert(false)
-    }
-  }
-
-  if (dart_debug) {
-    defines += ["DEBUG"]
-  } else {
-    defines += ["NDEBUG"]
-  }
-
-  if (is_ios || is_mac) {
-    defines += ["DART_PRECOMPILER"]
-  }
-
-  cflags = [
-    "-Werror",
-    "-Wall",
-    "-Wextra", # Also known as -W.
-    "-Wno-unused-parameter",
-    "-Wnon-virtual-dtor",
-    "-Wvla",
-    "-Wno-conversion-null",
-    "-Woverloaded-virtual",
-    "-g3",
-    "-ggdb3",
-    "-fno-rtti",
-    "-fno-exceptions",
-  ]
-
-  if (dart_debug) {
-    cflags += [
-      "-O1",
-    ]
-  } else {
-    cflags += [
-      "-O3",
-    ]
-  }
-
-  if (is_asan) {
-    ldflags = [
-      "-Wl,-u_sanitizer_options_link_helper",
-      "-fsanitize=address",
-    ]
-  }
-}
-
-config("dart_config_no_precompiler") {
-  defines = []
-
-  if (dart_target_arch != "") {
-    if (dart_target_arch == "arm") {
-      defines += [ "TARGET_ARCH_ARM" ]
-    } else if (dart_target_arch == "arm64") {
-      defines += [ "TARGET_ARCH_ARM64" ]
-    } else if (dart_target_arch == "mips") {
-      defines += [ "TARGET_ARCH_MIPS" ]
-    } else if (dart_target_arch == "x64") {
-      defines += [ "TARGET_ARCH_X64" ]
-    } else if (dart_target_arch == "ia32") {
-      defines += [ "TARGET_ARCH_IA32" ]
+    } else if (dart_target_arch == "dbc") {
+      defines += [ "TARGET_ARCH_DBC" ]
     } else  {
       print("Invalid |dart_target_arch|")
       assert(false)
@@ -146,9 +147,10 @@
   }
 }
 
-
 static_library("libdart") {
-  configs += [":dart_config"]
+  configs += [":dart_config",
+              ":dart_product_config",
+              ":dart_precompiled_runtime_config"]
   deps = [
     "vm:libdart_lib",
     "vm:libdart_vm",
@@ -173,37 +175,6 @@
   ]
 }
 
-
-static_library("libdart_precompiled_runtime") {
-  configs += [":dart_config_no_precompiler"]
-  deps = [
-    "vm:libdart_lib_precompiled_runtime",
-    "vm:libdart_vm_precompiled_runtime",
-    "third_party/double-conversion/src:libdouble_conversion",
-    ":generate_version_cc_file",
-  ]
-  include_dirs = [
-    ".",
-  ]
-  public_configs = [":dart_public_config"]
-  sources = [
-    "include/dart_api.h",
-    "include/dart_mirrors_api.h",
-    "include/dart_native_api.h",
-    "include/dart_tools_api.h",
-    "vm/dart_api_impl.cc",
-    "vm/debugger_api_impl.cc",
-    "vm/mirrors_api_impl.cc",
-    "vm/native_api_impl.cc",
-    "vm/version.h",
-    "$target_gen_dir/version.cc",
-  ]
-  defines = [
-    "DART_PRECOMPILED_RUNTIME",
-  ]
-}
-
-
 action("generate_version_cc_file") {
   deps = [
     ":libdart_dependency_helper",
@@ -228,7 +199,9 @@
 
 
 executable("libdart_dependency_helper") {
-  configs += [":dart_config"]
+  configs += [":dart_config",
+              ":dart_product_config",
+              ":dart_precompiled_runtime_config"]
   deps = [
     "vm:libdart_lib_nosnapshot",
     "vm:libdart_lib",
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 20b2a8a..b5ce6e6 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -119,7 +119,7 @@
                 ["builtin_impl_sources.gypi"])
 
 static_library("libdart_builtin") {
-  configs += ["..:dart_config"]
+  configs += ["..:dart_config", "..:dart_product_config"]
   public_configs = [":libdart_builtin_config"]
   deps = [
     ":generate_builtin_cc_file",
@@ -140,7 +140,9 @@
 
 
 static_library("libdart_nosnapshot") {
-  configs += ["..:dart_config"]
+  configs += ["..:dart_config",
+              "..:dart_product_config",
+              "..:dart_precompiled_runtime_config"]
   deps = [
     "../vm:libdart_lib_nosnapshot",
     "../vm:libdart_vm_nosnapshot",
@@ -171,8 +173,44 @@
 }
 
 
+static_library("libdart_nosnapshot_with_precompiler") {
+  configs += ["..:dart_config",
+              "..:dart_product_config",
+              "..:dart_precompiler_config"]
+  deps = [
+    "../vm:libdart_lib_nosnapshot_with_precompiler",
+    "../vm:libdart_vm_nosnapshot_with_precompiler",
+    "../vm:libdart_platform",
+    "../third_party/double-conversion/src:libdouble_conversion",
+    "..:generate_version_cc_file",
+  ]
+
+  sources = [
+    "../include/dart_api.h",
+    "../include/dart_mirrors_api.h",
+    "../include/dart_native_api.h",
+    "../include/dart_tools_api.h",
+    "../vm/dart_api_impl.cc",
+    "../vm/debugger_api_impl.cc",
+    "../vm/mirrors_api_impl.cc",
+    "../vm/native_api_impl.cc",
+    "$target_gen_dir/../version.cc",
+  ]
+
+  include_dirs = [
+    "..",
+  ]
+
+  defines = [
+    "DART_SHARED_LIB",
+  ]
+}
+
+
 executable("gen_snapshot") {
-  configs += ["..:dart_config"]
+  configs += ["..:dart_config",
+              "..:dart_product_config",
+              "..:dart_precompiler_config"]
   deps = [
     ":gen_resources_cc",
     ":gen_snapshot_dart_io",
@@ -180,7 +218,7 @@
     ":generate_io_cc_file",
     ":generate_io_patch_cc_file",
     ":libdart_builtin",
-    ":libdart_nosnapshot",
+    ":libdart_nosnapshot_with_precompiler",
   ]
 
   sources = [
@@ -207,7 +245,9 @@
 
 
 source_set("libdart_embedder_noio") {
-  configs += ["..:dart_config",]
+  configs += ["..:dart_config",
+              "..:dart_product_config",
+              "..:dart_precompiled_runtime_config"]
   deps = [
     "..:libdart",
     "../vm:libdart_platform",
@@ -224,7 +264,9 @@
 # A source set for the implementation of 'dart:io' library
 # (without secure sockets) suitable for linking with gen_snapshot.
 source_set("gen_snapshot_dart_io") {
-  configs += ["..:dart_config",]
+  configs += ["..:dart_config",
+              "..:dart_product_config",
+              "..:dart_precompiler_config"]
 
   deps = [
     "//third_party/zlib",
@@ -263,7 +305,9 @@
 # A source set for the implementation of 'dart:io' library
 # (without secure sockets).
 source_set("embedded_dart_io") {
-  configs += ["..:dart_config",]
+  configs += ["..:dart_config",
+              "..:dart_product_config",
+              "..:dart_precompiled_runtime_config"]
 
   custom_sources_filter = [
     "*_test.cc",
@@ -285,7 +329,9 @@
       "Security.framework",
     ]
   } else {
-    defines = [ "DART_IO_SECURE_SOCKET_DISABLED" ]
+    deps = [
+      "../../third_party/boringssl",
+    ]
   }
 
   sources = io_impl_sources_gypi.sources + builtin_impl_sources_gypi.sources
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index da8354e..0018712 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -677,41 +677,6 @@
       ]
     },
     {
-      # dart_product binary.
-      'target_name': 'dart_product',
-      'type': 'executable',
-      'dependencies': [
-        'bin/zlib.gyp:zlib_dart',
-        'libdart',
-        'libdart_builtin',
-        'libdart_io',
-      ],
-      'include_dirs': [
-        '..',
-        '../../third_party/', # Zlib
-      ],
-      'defines': [
-        'DART_PRODUCT_BINARY',
-      ],
-      'sources': [
-        'main.cc',
-        'builtin.h',
-        'builtin_common.cc',
-        'builtin_natives.cc',
-        'builtin_nolib.cc',
-        'io_natives.h',
-        'observatory_assets_empty.cc',
-        'snapshot_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/builtin.dart b/runtime/bin/builtin.dart
index 2f64b77..59ccec3 100644
--- a/runtime/bin/builtin.dart
+++ b/runtime/bin/builtin.dart
@@ -822,20 +822,6 @@
 // Dart native extension scheme.
 const _DART_EXT = 'dart-ext:';
 
-String _nativeLibraryExtension() native "Builtin_NativeLibraryExtension";
-
-
-String _platformExtensionFileName(String name) {
-  var extension = _nativeLibraryExtension();
-
-  if (_isWindows) {
-    return '$name.$extension';
-  } else {
-    return 'lib$name.$extension';
-  }
-}
-
-
 // Returns either a file path or a URI starting with http[s]:, as a String.
 String _filePathFromUri(String userUri) {
   var uri = Uri.parse(userUri);
@@ -898,11 +884,9 @@
     name = userUri.substring(index + 1);
     path = userUri.substring(0, index + 1);
   }
-
   path = _filePathFromUri(path);
-  var filename = _platformExtensionFileName(name);
 
-  return [path, filename, name];
+  return [path, name];
 }
 
 
diff --git a/runtime/bin/builtin_natives.cc b/runtime/bin/builtin_natives.cc
index ba45a73..96280df 100644
--- a/runtime/bin/builtin_natives.cc
+++ b/runtime/bin/builtin_natives.cc
@@ -30,7 +30,6 @@
   V(Builtin_LoadSource, 4)                                                     \
   V(Builtin_AsyncLoadError, 3)                                                 \
   V(Builtin_DoneLoading, 0)                                                    \
-  V(Builtin_NativeLibraryExtension, 0)                                         \
   V(Builtin_GetCurrentDirectory, 0)                                            \
 
 
diff --git a/runtime/bin/dart_entries.txt b/runtime/bin/dart_entries.txt
new file mode 100644
index 0000000..ceea4fa
--- /dev/null
+++ b/runtime/bin/dart_entries.txt
@@ -0,0 +1 @@
+dart:vmservice_io,::,main
diff --git a/runtime/bin/dart_product_entries.txt b/runtime/bin/dart_product_entries.txt
new file mode 100644
index 0000000..d8825d2
--- /dev/null
+++ b/runtime/bin/dart_product_entries.txt
@@ -0,0 +1,27 @@
+dart:_builtin,::,_getMainClosure
+dart:_builtin,::,_getPrintClosure
+dart:_builtin,::,_getUriBaseClosure
+dart:_builtin,::,_resolveUri
+dart:_builtin,::,_setWorkingDirectory
+dart:_builtin,::,_setPackageRoot
+dart:_builtin,::,_loadPackagesMap
+dart:_builtin,::,_loadDataAsync
+dart:io,::,_makeUint8ListView
+dart:io,::,_makeDatagram
+dart:io,::,_setupHooks
+dart:io,::,_getWatchSignalInternal
+dart:io,CertificateException,CertificateException.
+dart:io,Directory,Directory.
+dart:io,File,File.
+dart:io,FileSystemException,FileSystemException.
+dart:io,HandshakeException,HandshakeException.
+dart:io,Link,Link.
+dart:io,OSError,OSError.
+dart:io,TlsException,TlsException.
+dart:io,X509Certificate,X509Certificate._
+dart:io,_ExternalBuffer,set:data
+dart:io,_Platform,set:_nativeScript
+dart:io,_ProcessStartStatus,set:_errorCode
+dart:io,_ProcessStartStatus,set:_errorMessage
+dart:io,_SecureFilterImpl,get:ENCRYPTED_SIZE
+dart:io,_SecureFilterImpl,get:SIZE
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index 764c00e..e180479 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -180,6 +180,17 @@
 }
 
 
+void* DartUtils::MapExecutable(const char* name, intptr_t* len) {
+  File* file = File::Open(name, File::kRead);
+  if (file == NULL) {
+    return NULL;
+  }
+  void* addr = file->MapExecutable(len);
+  file->Release();
+  return addr;
+}
+
+
 void* DartUtils::OpenFile(const char* name, bool write) {
   File* file = File::Open(name, write ? File::kWriteTruncate : File::kRead);
   return reinterpret_cast<void*>(file);
@@ -222,7 +233,8 @@
 
 
 void DartUtils::CloseFile(void* stream) {
-  delete reinterpret_cast<File*>(stream);
+  File* file = reinterpret_cast<File*>(stream);
+  file->Release();
 }
 
 
@@ -450,15 +462,20 @@
     if (Dart_IsError(path_parts)) {
       return path_parts;
     }
+#if defined(DEBUG)
+    intptr_t path_parts_length;
+    result = Dart_ListLength(path_parts, &path_parts_length);
+    if (Dart_IsError(result)) {
+      return result;
+    }
+    ASSERT(path_parts_length == 2);
+#endif
     const char* extension_directory = NULL;
     Dart_StringToCString(Dart_ListGetAt(path_parts, 0), &extension_directory);
-    const char* extension_filename = NULL;
-    Dart_StringToCString(Dart_ListGetAt(path_parts, 1), &extension_filename);
     const char* extension_name = NULL;
-    Dart_StringToCString(Dart_ListGetAt(path_parts, 2), &extension_name);
+    Dart_StringToCString(Dart_ListGetAt(path_parts, 1), &extension_name);
 
     return Extensions::LoadExtension(extension_directory,
-                                     extension_filename,
                                      extension_name,
                                      library);
   }
@@ -619,17 +636,6 @@
 }
 
 
-void FUNCTION_NAME(Builtin_NativeLibraryExtension)(Dart_NativeArguments args) {
-  const char* suffix = Platform::LibraryExtension();
-  ASSERT(suffix != NULL);
-  Dart_Handle res = Dart_NewStringFromCString(suffix);
-  if (Dart_IsError(res)) {
-    Dart_PropagateError(res);
-  }
-  Dart_SetReturnValue(args, res);
-}
-
-
 void FUNCTION_NAME(Builtin_GetCurrentDirectory)(Dart_NativeArguments args) {
   const char* current = Directory::Current();
   if (current != NULL) {
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index f9a6d50..ed63c7c 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -115,6 +115,7 @@
   static bool IsDartIOLibURL(const char* url_name);
   static bool IsDartBuiltinLibURL(const char* url_name);
   static bool IsHttpSchemeURL(const char* url_name);
+  static void* MapExecutable(const char* name, intptr_t* file_len);
   static void* OpenFile(const char* name, bool write);
   static void ReadFile(const uint8_t** data, intptr_t* file_len, void* stream);
   static void WriteFile(const void* buffer, intptr_t num_bytes, void* stream);
@@ -600,6 +601,69 @@
   ~ScopedBlockingCall() {
     Dart_ThreadEnableProfiling();
   }
+
+ private:
+  DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(ScopedBlockingCall);
+};
+
+
+// Where the argument to the constructor is the handle for an object
+// implementing List<int>, this class creates a scope in which the memory
+// backing the list can be accessed.
+//
+// Do not make Dart_ API calls while in a ScopedMemBuffer.
+// Do not call Dart_PropagateError while in a ScopedMemBuffer.
+class ScopedMemBuffer {
+ public:
+  explicit ScopedMemBuffer(Dart_Handle object) {
+    if (!Dart_IsTypedData(object) && !Dart_IsList(object)) {
+      Dart_ThrowException(DartUtils::NewDartArgumentError(
+          "Argument is not a List<int>"));
+    }
+
+    uint8_t* bytes = NULL;
+    intptr_t bytes_len = 0;
+    bool is_typed_data = false;
+    if (Dart_IsTypedData(object)) {
+      is_typed_data = true;
+      Dart_TypedData_Type typ;
+      ThrowIfError(Dart_TypedDataAcquireData(
+          object,
+          &typ,
+          reinterpret_cast<void**>(&bytes),
+          &bytes_len));
+    } else {
+      ASSERT(Dart_IsList(object));
+      ThrowIfError(Dart_ListLength(object, &bytes_len));
+      bytes = Dart_ScopeAllocate(bytes_len);
+      ASSERT(bytes != NULL);
+      ThrowIfError(Dart_ListGetAsBytes(object, 0, bytes, bytes_len));
+    }
+
+    object_ = object;
+    bytes_ = bytes;
+    bytes_len_ = bytes_len;
+    is_typed_data_ = is_typed_data;
+  }
+
+  ~ScopedMemBuffer() {
+    if (is_typed_data_) {
+      ThrowIfError(Dart_TypedDataReleaseData(object_));
+    }
+  }
+
+  uint8_t* get() const { return bytes_; }
+  intptr_t length() const { return bytes_len_; }
+
+ private:
+  Dart_Handle object_;
+  uint8_t* bytes_;
+  intptr_t bytes_len_;
+  bool is_typed_data_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(ScopedMemBuffer);
 };
 
 }  // namespace bin
diff --git a/runtime/bin/directory.cc b/runtime/bin/directory.cc
index 982a4be..bb3173f 100644
--- a/runtime/bin/directory.cc
+++ b/runtime/bin/directory.cc
@@ -7,6 +7,7 @@
 #include "bin/directory.h"
 
 #include "bin/dartutils.h"
+#include "bin/log.h"
 #include "include/dart_api.h"
 #include "platform/assert.h"
 
@@ -139,6 +140,61 @@
 }
 
 
+static const int kAsyncDirectoryListerFieldIndex = 0;
+
+
+void FUNCTION_NAME(Directory_GetAsyncDirectoryListerPointer)(
+    Dart_NativeArguments args) {
+  AsyncDirectoryListing* listing;
+  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+  ASSERT(Dart_IsInstance(dart_this));
+  ThrowIfError(Dart_GetNativeInstanceField(
+      dart_this,
+      kAsyncDirectoryListerFieldIndex,
+      reinterpret_cast<intptr_t*>(&listing)));
+  if (listing != NULL) {
+    intptr_t listing_pointer = reinterpret_cast<intptr_t>(listing);
+    // Increment the listing's reference count. This native should only be
+    // be called when we are about to send the AsyncDirectoryListing* to the
+    // IO service.
+    listing->Retain();
+    Dart_SetReturnValue(args, Dart_NewInteger(listing_pointer));
+  }
+}
+
+
+static void ReleaseListing(void* isolate_callback_data,
+                           Dart_WeakPersistentHandle handle,
+                           void* peer) {
+  AsyncDirectoryListing* listing =
+      reinterpret_cast<AsyncDirectoryListing*>(peer);
+  listing->Release();
+}
+
+
+void FUNCTION_NAME(Directory_SetAsyncDirectoryListerPointer)(
+    Dart_NativeArguments args) {
+  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+  intptr_t listing_pointer =
+      DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 1));
+  AsyncDirectoryListing* listing =
+      reinterpret_cast<AsyncDirectoryListing*>(listing_pointer);
+  Dart_NewWeakPersistentHandle(
+      dart_this,
+      reinterpret_cast<void*>(listing),
+      sizeof(*listing),
+      ReleaseListing);
+  Dart_Handle result = Dart_SetNativeInstanceField(
+      dart_this,
+      kAsyncDirectoryListerFieldIndex,
+      listing_pointer);
+  if (Dart_IsError(result)) {
+    Log::PrintErr("SetAsyncDirectoryListerPointer failed\n");
+    Dart_PropagateError(result);
+  }
+}
+
+
 CObject* Directory::CreateRequest(const CObjectArray& request) {
   if ((request.Length() == 1) && request[0]->IsString()) {
     CObjectString path(request[0]);
@@ -226,7 +282,7 @@
     if (dir_listing->error()) {
       // Report error now, so we capture the correct OSError.
       CObject* err = CObject::NewOSError();
-      delete dir_listing;
+      dir_listing->Release();
       CObjectArray* error = new CObjectArray(CObject::NewArray(3));
       error->SetAt(0, new CObjectInt32(
           CObject::NewInt32(AsyncDirectoryListing::kListError)));
@@ -247,6 +303,7 @@
     CObjectIntptr ptr(request[0]);
     AsyncDirectoryListing* dir_listing =
         reinterpret_cast<AsyncDirectoryListing*>(ptr.Value());
+    RefCntReleaseScope<AsyncDirectoryListing> rs(dir_listing);
     if (dir_listing->IsEmpty()) {
       return new CObjectArray(CObject::NewArray(0));
     }
@@ -268,7 +325,15 @@
     CObjectIntptr ptr(request[0]);
     AsyncDirectoryListing* dir_listing =
         reinterpret_cast<AsyncDirectoryListing*>(ptr.Value());
-    delete dir_listing;
+    RefCntReleaseScope<AsyncDirectoryListing> rs(dir_listing);
+
+    // We have retained a reference to the listing here. Therefore the listing's
+    // destructor can't be running. Since no further requests are dispatched by
+    // the Dart code after an async stop call, this PopAll() can't be racing
+    // with any other call on the listing. We don't do an extra Release(), and
+    // we don't delete the weak persistent handle. The file is closed here, but
+    // the memory for the listing will be cleaned up when the finalizer runs.
+    dir_listing->PopAll();
     return new CObjectBool(CObject::Bool(true));
   }
   return CreateIllegalArgumentError();
diff --git a/runtime/bin/directory.h b/runtime/bin/directory.h
index 7a1c5d1..f455710 100644
--- a/runtime/bin/directory.h
+++ b/runtime/bin/directory.h
@@ -7,6 +7,7 @@
 
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
+#include "bin/reference_counting.h"
 #include "bin/thread.h"
 #include "platform/globals.h"
 
@@ -107,9 +108,7 @@
   }
 
   virtual ~DirectoryListing() {
-    while (!IsEmpty()) {
-      Pop();
-    }
+    PopAll();
   }
 
   virtual bool HandleDirectory(const char* dir_name) = 0;
@@ -133,6 +132,12 @@
     return top_ == NULL;
   }
 
+  void PopAll() {
+    while (!IsEmpty()) {
+      Pop();
+    }
+  }
+
   DirectoryListingEntry* top() const {
     return top_;
   }
@@ -166,7 +171,8 @@
 };
 
 
-class AsyncDirectoryListing : public DirectoryListing {
+class AsyncDirectoryListing : public ReferenceCounted<AsyncDirectoryListing>,
+                              public DirectoryListing {
  public:
   enum Response {
     kListFile = 0,
@@ -179,9 +185,12 @@
   AsyncDirectoryListing(const char* dir_name,
                         bool recursive,
                         bool follow_links)
-      : DirectoryListing(dir_name, recursive, follow_links) {}
+      : ReferenceCounted(),
+        DirectoryListing(dir_name, recursive, follow_links),
+        array_(NULL),
+        index_(0),
+        length_(0) {}
 
-  virtual ~AsyncDirectoryListing() {}
   virtual bool HandleDirectory(const char* dir_name);
   virtual bool HandleFile(const char* file_name);
   virtual bool HandleLink(const char* file_name);
@@ -200,11 +209,13 @@
   }
 
  private:
+  virtual ~AsyncDirectoryListing() {}
   bool AddFileSystemEntityToResponse(Response response, const char* arg);
   CObjectArray* array_;
   intptr_t index_;
   intptr_t length_;
 
+  friend class ReferenceCounted<AsyncDirectoryListing>;
   DISALLOW_IMPLICIT_CONSTRUCTORS(AsyncDirectoryListing);
 };
 
@@ -238,6 +249,7 @@
   Dart_Handle file_type_;
   Dart_Handle link_type_;
 
+  DISALLOW_ALLOCATION()
   DISALLOW_IMPLICIT_CONSTRUCTORS(SyncDirectoryListing);
 };
 
diff --git a/runtime/bin/directory_patch.dart b/runtime/bin/directory_patch.dart
index f8643ae..f98a52e 100644
--- a/runtime/bin/directory_patch.dart
+++ b/runtime/bin/directory_patch.dart
@@ -16,3 +16,21 @@
   /* patch */ static List _list(String path, bool recursive, bool followLinks)
       native "Directory_List";
 }
+
+patch class _AsyncDirectoryListerOps {
+  /* patch */ factory _AsyncDirectoryListerOps(int pointer) =>
+      new _AsyncDirectoryListerOpsImpl(pointer);
+}
+
+class _AsyncDirectoryListerOpsImpl extends NativeFieldWrapperClass1
+                                   implements _AsyncDirectoryListerOps {
+  _AsyncDirectoryListerOpsImpl._();
+
+  factory _AsyncDirectoryListerOpsImpl(int pointer)
+      => new _AsyncDirectoryListerOpsImpl._().._setPointer(pointer);
+
+  void _setPointer(int pointer)
+      native "Directory_SetAsyncDirectoryListerPointer";
+  int getPointer()
+      native "Directory_GetAsyncDirectoryListerPointer";
+}
diff --git a/runtime/bin/directory_unsupported.cc b/runtime/bin/directory_unsupported.cc
index 7e82bdd..1b1abd2 100644
--- a/runtime/bin/directory_unsupported.cc
+++ b/runtime/bin/directory_unsupported.cc
@@ -64,6 +64,20 @@
         "Directory is not supported on this platform"));
 }
 
+
+void FUNCTION_NAME(Directory_GetAsyncDirectoryListerPointer)(
+    Dart_NativeArguments args) {
+  Dart_ThrowException(DartUtils::NewInternalError(
+        "Directory is not supported on this platform"));
+}
+
+
+void FUNCTION_NAME(Directory_SetAsyncDirectoryListerPointer)(
+    Dart_NativeArguments args) {
+  Dart_ThrowException(DartUtils::NewInternalError(
+        "Directory is not supported on this platform"));
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/extensions.cc b/runtime/bin/extensions.cc
index 7fa06fd..f4b921f 100644
--- a/runtime/bin/extensions.cc
+++ b/runtime/bin/extensions.cc
@@ -8,6 +8,7 @@
 
 #include "bin/dartutils.h"
 #include "bin/file.h"
+#include "bin/platform.h"
 #include "include/dart_api.h"
 #include "platform/assert.h"
 #include "platform/globals.h"
@@ -16,18 +17,42 @@
 namespace bin {
 
 Dart_Handle Extensions::LoadExtension(const char* extension_directory,
-                                      const char* extension_file,
                                       const char* extension_name,
                                       Dart_Handle parent_library) {
   if (strncmp(extension_directory, "http://", 7) == 0 ||
       strncmp(extension_directory, "https://", 8) == 0) {
     return Dart_NewApiError("Cannot load native extensions over http:");
   }
-  const char* library_strings[] = { extension_directory, extension_file, NULL };
+
+  // For example on Linux: directory/libfoo-arm.so
+  const char* library_strings[] = {
+    extension_directory,  // directory/
+    Platform::LibraryPrefix(),  // lib
+    extension_name,  // foo
+    "-",
+    Platform::HostArchitecture(),  // arm
+    ".",
+    Platform::LibraryExtension(),  // so
+    NULL,
+  };
   const char* library_file = Concatenate(library_strings);
   void* library_handle = LoadExtensionLibrary(library_file);
   if (library_handle == NULL) {
-    return GetError();
+    // Fallback on a library file name that does not specify the host
+    // architecture. For example on Linux: directory/libfoo.so
+    const char* fallback_library_strings[] = {
+      extension_directory,  // directory/
+      Platform::LibraryPrefix(),  // lib
+      extension_name,  // foo
+      ".",
+      Platform::LibraryExtension(),  // so
+      NULL,
+    };
+    const char* fallback_library_file = Concatenate(fallback_library_strings);
+    library_handle = LoadExtensionLibrary(fallback_library_file);
+    if (library_handle == NULL) {
+      return GetError();
+    }
   }
 
   const char* strings[] = { extension_name, "_Init", NULL };
diff --git a/runtime/bin/extensions.h b/runtime/bin/extensions.h
index da18615..d266303 100644
--- a/runtime/bin/extensions.h
+++ b/runtime/bin/extensions.h
@@ -16,7 +16,6 @@
   // TODO(whesse): Make extension load from a relative path relative to
   // the library it is in.  Currently loads from current working directory.
   static Dart_Handle LoadExtension(const char* extension_directory,
-                                   const char* extension_filename,
                                    const char* extension_name,
                                    Dart_Handle parent_library);
 
diff --git a/runtime/bin/file.cc b/runtime/bin/file.cc
index e730b172..43e1944 100644
--- a/runtime/bin/file.cc
+++ b/runtime/bin/file.cc
@@ -18,14 +18,66 @@
 namespace dart {
 namespace bin {
 
+static const int kFileNativeFieldIndex = 0;
 static const int kMSPerSecond = 1000;
 
 // The file pointer has been passed into Dart as an intptr_t and it is safe
 // to pull it out of Dart as a 64-bit integer, cast it to an intptr_t and
 // from there to a File pointer.
-static File* GetFilePointer(Dart_Handle handle) {
-  intptr_t value = DartUtils::GetIntptrValue(handle);
-  return reinterpret_cast<File*>(value);
+static File* GetFile(Dart_NativeArguments args) {
+  File* file;
+  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+  ASSERT(Dart_IsInstance(dart_this));
+  ThrowIfError(Dart_GetNativeInstanceField(
+      dart_this,
+      kFileNativeFieldIndex,
+      reinterpret_cast<intptr_t*>(&file)));
+  return file;
+}
+
+
+static void SetFile(Dart_Handle dart_this, intptr_t file_pointer) {
+  Dart_Handle result = Dart_SetNativeInstanceField(
+      dart_this,
+      kFileNativeFieldIndex,
+      file_pointer);
+  if (Dart_IsError(result)) {
+    Log::PrintErr("SetNativeInstanceField in SetFile() failed\n");
+    Dart_PropagateError(result);
+  }
+}
+
+
+void FUNCTION_NAME(File_GetPointer)(Dart_NativeArguments args) {
+  File* file = GetFile(args);
+  // If the file is already closed, GetFile() will return NULL.
+  if (file != NULL) {
+    // Increment file's reference count. File_GetPointer() should only be called
+    // when we are about to send the File* to the IO Service.
+    file->Retain();
+  }
+  intptr_t file_pointer = reinterpret_cast<intptr_t>(file);
+  Dart_SetReturnValue(args, Dart_NewInteger(file_pointer));
+}
+
+
+static void ReleaseFile(void* isolate_callback_data,
+                        Dart_WeakPersistentHandle handle,
+                        void* peer) {
+  File* file = reinterpret_cast<File*>(peer);
+  file->Release();
+}
+
+
+void FUNCTION_NAME(File_SetPointer)(Dart_NativeArguments args) {
+  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+  intptr_t file_pointer =
+      DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 1));
+  File* file = reinterpret_cast<File*>(file_pointer);
+  Dart_WeakPersistentHandle handle = Dart_NewWeakPersistentHandle(
+      dart_this, reinterpret_cast<void*>(file), sizeof(*file), ReleaseFile);
+  file->SetWeakHandle(handle);
+  SetFile(dart_this, file_pointer);
 }
 
 
@@ -40,8 +92,7 @@
   // reading. This is to prevent the opening of directories as
   // files. Directories can be opened for reading using the posix
   // 'open' call.
-  File* file = NULL;
-  file = File::ScopedOpen(filename, file_mode);
+  File* file = File::ScopedOpen(filename, file_mode);
   if (file != NULL) {
     Dart_SetReturnValue(args,
                         Dart_NewInteger(reinterpret_cast<intptr_t>(file)));
@@ -60,22 +111,20 @@
 
 
 void FUNCTION_NAME(File_Close)(Dart_NativeArguments args) {
-  File* file = GetFilePointer(Dart_GetNativeArgument(args, 0));
+  File* file = GetFile(args);
   ASSERT(file != NULL);
-  delete file;
+  file->DeleteWeakHandle(Dart_CurrentIsolate());
+  file->Release();
+
+  // NULL-out the now potentially dangling pointer.
+  Dart_Handle dart_this = Dart_GetNativeArgument(args, 0);
+  SetFile(dart_this, 0);
   Dart_SetReturnValue(args, Dart_NewInteger(0));
 }
 
 
-void FUNCTION_NAME(File_GetFD)(Dart_NativeArguments args) {
-  File* file = GetFilePointer(Dart_GetNativeArgument(args, 0));
-  ASSERT(file != NULL);
-  Dart_SetReturnValue(args, Dart_NewInteger(file->GetFD()));
-}
-
-
 void FUNCTION_NAME(File_ReadByte)(Dart_NativeArguments args) {
-  File* file = GetFilePointer(Dart_GetNativeArgument(args, 0));
+  File* file = GetFile(args);
   ASSERT(file != NULL);
   uint8_t buffer;
   int64_t bytes_read = file->Read(reinterpret_cast<void*>(&buffer), 1);
@@ -90,7 +139,7 @@
 
 
 void FUNCTION_NAME(File_WriteByte)(Dart_NativeArguments args) {
-  File* file = GetFilePointer(Dart_GetNativeArgument(args, 0));
+  File* file = GetFile(args);
   ASSERT(file != NULL);
   int64_t byte = 0;
   if (DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 1), &byte)) {
@@ -109,7 +158,7 @@
 
 
 void FUNCTION_NAME(File_Read)(Dart_NativeArguments args) {
-  File* file = GetFilePointer(Dart_GetNativeArgument(args, 0));
+  File* file = GetFile(args);
   ASSERT(file != NULL);
   Dart_Handle length_object = Dart_GetNativeArgument(args, 1);
   int64_t length = 0;
@@ -150,7 +199,7 @@
 
 
 void FUNCTION_NAME(File_ReadInto)(Dart_NativeArguments args) {
-  File* file = GetFilePointer(Dart_GetNativeArgument(args, 0));
+  File* file = GetFile(args);
   ASSERT(file != NULL);
   Dart_Handle buffer_obj = Dart_GetNativeArgument(args, 1);
   ASSERT(Dart_IsList(buffer_obj));
@@ -185,7 +234,7 @@
 
 
 void FUNCTION_NAME(File_WriteFrom)(Dart_NativeArguments args) {
-  File* file = GetFilePointer(Dart_GetNativeArgument(args, 0));
+  File* file = GetFile(args);
   ASSERT(file != NULL);
 
   Dart_Handle buffer_obj = Dart_GetNativeArgument(args, 1);
@@ -233,7 +282,7 @@
 
 
 void FUNCTION_NAME(File_Position)(Dart_NativeArguments args) {
-  File* file = GetFilePointer(Dart_GetNativeArgument(args, 0));
+  File* file = GetFile(args);
   ASSERT(file != NULL);
   intptr_t return_value = file->Position();
   if (return_value >= 0) {
@@ -245,7 +294,7 @@
 
 
 void FUNCTION_NAME(File_SetPosition)(Dart_NativeArguments args) {
-  File* file = GetFilePointer(Dart_GetNativeArgument(args, 0));
+  File* file = GetFile(args);
   ASSERT(file != NULL);
   int64_t position = 0;
   if (DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 1), &position)) {
@@ -262,7 +311,7 @@
 
 
 void FUNCTION_NAME(File_Truncate)(Dart_NativeArguments args) {
-  File* file = GetFilePointer(Dart_GetNativeArgument(args, 0));
+  File* file = GetFile(args);
   ASSERT(file != NULL);
   int64_t length = 0;
   if (DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 1), &length)) {
@@ -279,7 +328,7 @@
 
 
 void FUNCTION_NAME(File_Length)(Dart_NativeArguments args) {
-  File* file = GetFilePointer(Dart_GetNativeArgument(args, 0));
+  File* file = GetFile(args);
   ASSERT(file != NULL);
   int64_t return_value = file->Length();
   if (return_value >= 0) {
@@ -315,7 +364,7 @@
 
 
 void FUNCTION_NAME(File_Flush)(Dart_NativeArguments args) {
-  File* file = GetFilePointer(Dart_GetNativeArgument(args, 0));
+  File* file = GetFile(args);
   ASSERT(file != NULL);
   if (file->Flush()) {
     Dart_SetReturnValue(args, Dart_True());
@@ -326,7 +375,7 @@
 
 
 void FUNCTION_NAME(File_Lock)(Dart_NativeArguments args) {
-  File* file = GetFilePointer(Dart_GetNativeArgument(args, 0));
+  File* file = GetFile(args);
   ASSERT(file != NULL);
   int64_t lock;
   int64_t start;
@@ -704,9 +753,16 @@
   intptr_t return_value = -1;
   if ((request.Length() == 1) && request[0]->IsIntptr()) {
     File* file = CObjectToFilePointer(request[0]);
-    ASSERT(file != NULL);
-    delete file;
+    RefCntReleaseScope<File> rs(file);
     return_value = 0;
+    // We have retained a reference to the file here. Therefore the file's
+    // destructor can't be running. Since no further requests are dispatched by
+    // the Dart code after an async close call, this Close() can't be racing
+    // with any other call on the file. We don't do an extra Release(), and we
+    // don't delete the weak persistent handle. The file is closed here, but the
+    // memory will be cleaned up when the finalizer runs.
+    ASSERT(!file->IsClosed());
+    file->Close();
   }
   return new CObjectIntptr(CObject::NewIntptr(return_value));
 }
@@ -715,7 +771,7 @@
 CObject* File::PositionRequest(const CObjectArray& request) {
   if ((request.Length() == 1) && request[0]->IsIntptr()) {
     File* file = CObjectToFilePointer(request[0]);
-    ASSERT(file != NULL);
+    RefCntReleaseScope<File> rs(file);
     if (!file->IsClosed()) {
       intptr_t return_value = file->Position();
       if (return_value >= 0) {
@@ -732,20 +788,22 @@
 
 
 CObject* File::SetPositionRequest(const CObjectArray& request) {
-  if ((request.Length() == 2) &&
-      request[0]->IsIntptr() &&
-      request[1]->IsInt32OrInt64()) {
+  if ((request.Length() >= 1) && request[0]->IsIntptr()) {
     File* file = CObjectToFilePointer(request[0]);
-    ASSERT(file != NULL);
-    if (!file->IsClosed()) {
-      int64_t position = CObjectInt32OrInt64ToInt64(request[1]);
-      if (file->SetPosition(position)) {
-        return CObject::True();
+    RefCntReleaseScope<File> rs(file);
+    if ((request.Length() == 2) && request[1]->IsInt32OrInt64()) {
+      if (!file->IsClosed()) {
+        int64_t position = CObjectInt32OrInt64ToInt64(request[1]);
+        if (file->SetPosition(position)) {
+          return CObject::True();
+        } else {
+          return CObject::NewOSError();
+        }
       } else {
-        return CObject::NewOSError();
+        return CObject::FileClosedError();
       }
     } else {
-      return CObject::FileClosedError();
+      return CObject::IllegalArgumentError();
     }
   }
   return CObject::IllegalArgumentError();
@@ -753,20 +811,22 @@
 
 
 CObject* File::TruncateRequest(const CObjectArray& request) {
-  if ((request.Length() == 2) &&
-      request[0]->IsIntptr() &&
-      request[1]->IsInt32OrInt64()) {
+  if ((request.Length() >= 1) && request[0]->IsIntptr()) {
     File* file = CObjectToFilePointer(request[0]);
-    ASSERT(file != NULL);
-    if (!file->IsClosed()) {
-      int64_t length = CObjectInt32OrInt64ToInt64(request[1]);
-      if (file->Truncate(length)) {
-        return CObject::True();
+    RefCntReleaseScope<File> rs(file);
+    if ((request.Length() == 2) && request[1]->IsInt32OrInt64()) {
+      if (!file->IsClosed()) {
+        int64_t length = CObjectInt32OrInt64ToInt64(request[1]);
+        if (file->Truncate(length)) {
+          return CObject::True();
+        } else {
+          return CObject::NewOSError();
+        }
       } else {
-        return CObject::NewOSError();
+        return CObject::FileClosedError();
       }
     } else {
-      return CObject::FileClosedError();
+      return CObject::IllegalArgumentError();
     }
   }
   return CObject::IllegalArgumentError();
@@ -776,7 +836,7 @@
 CObject* File::LengthRequest(const CObjectArray& request) {
   if ((request.Length() == 1) && request[0]->IsIntptr()) {
     File* file = CObjectToFilePointer(request[0]);
-    ASSERT(file != NULL);
+    RefCntReleaseScope<File> rs(file);
     if (!file->IsClosed()) {
       int64_t return_value = file->Length();
       if (return_value >= 0) {
@@ -823,7 +883,7 @@
 CObject* File::FlushRequest(const CObjectArray& request) {
   if ((request.Length() == 1) && request[0]->IsIntptr()) {
     File* file = CObjectToFilePointer(request[0]);
-    ASSERT(file != NULL);
+    RefCntReleaseScope<File> rs(file);
     if (!file->IsClosed()) {
       if (file->Flush()) {
         return CObject::True();
@@ -841,7 +901,7 @@
 CObject* File::ReadByteRequest(const CObjectArray& request) {
   if ((request.Length() == 1) && request[0]->IsIntptr()) {
     File* file = CObjectToFilePointer(request[0]);
-    ASSERT(file != NULL);
+    RefCntReleaseScope<File> rs(file);
     if (!file->IsClosed()) {
       uint8_t buffer;
       int64_t bytes_read = file->Read(reinterpret_cast<void*>(&buffer), 1);
@@ -861,22 +921,24 @@
 
 
 CObject* File::WriteByteRequest(const CObjectArray& request) {
-  if ((request.Length() == 2) &&
-      request[0]->IsIntptr() &&
-      request[1]->IsInt32OrInt64()) {
+  if ((request.Length() >= 1) && request[0]->IsIntptr()) {
     File* file = CObjectToFilePointer(request[0]);
-    ASSERT(file != NULL);
-    if (!file->IsClosed()) {
-      int64_t byte = CObjectInt32OrInt64ToInt64(request[1]);
-      uint8_t buffer = static_cast<uint8_t>(byte & 0xff);
-      bool success = file->WriteFully(reinterpret_cast<void*>(&buffer), 1);
-      if (success) {
-        return new CObjectInt64(CObject::NewInt64(1));
+    RefCntReleaseScope<File> rs(file);
+    if ((request.Length() == 2) && request[1]->IsInt32OrInt64()) {
+      if (!file->IsClosed()) {
+        int64_t byte = CObjectInt32OrInt64ToInt64(request[1]);
+        uint8_t buffer = static_cast<uint8_t>(byte & 0xff);
+        bool success = file->WriteFully(reinterpret_cast<void*>(&buffer), 1);
+        if (success) {
+          return new CObjectInt64(CObject::NewInt64(1));
+        } else {
+          return CObject::NewOSError();
+        }
       } else {
-        return CObject::NewOSError();
+        return CObject::FileClosedError();
       }
     } else {
-      return CObject::FileClosedError();
+      return CObject::IllegalArgumentError();
     }
   }
   return CObject::IllegalArgumentError();
@@ -884,31 +946,33 @@
 
 
 CObject* File::ReadRequest(const CObjectArray& request) {
-  if ((request.Length() == 2) &&
-      request[0]->IsIntptr() &&
-      request[1]->IsInt32OrInt64()) {
+  if ((request.Length() >= 1) && request[0]->IsIntptr()) {
     File* file = CObjectToFilePointer(request[0]);
-    ASSERT(file != NULL);
-    if (!file->IsClosed()) {
-      int64_t length = CObjectInt32OrInt64ToInt64(request[1]);
-      Dart_CObject* io_buffer = CObject::NewIOBuffer(length);
-      ASSERT(io_buffer != NULL);
-      uint8_t* data = io_buffer->value.as_external_typed_data.data;
-      int64_t bytes_read = file->Read(data, length);
-      if (bytes_read >= 0) {
-        CObjectExternalUint8Array* external_array =
-            new CObjectExternalUint8Array(io_buffer);
-        external_array->SetLength(bytes_read);
-        CObjectArray* result = new CObjectArray(CObject::NewArray(2));
-        result->SetAt(0, new CObjectIntptr(CObject::NewInt32(0)));
-        result->SetAt(1, external_array);
-        return result;
+    RefCntReleaseScope<File> rs(file);
+    if ((request.Length() == 2) && request[1]->IsInt32OrInt64()) {
+      if (!file->IsClosed()) {
+        int64_t length = CObjectInt32OrInt64ToInt64(request[1]);
+        Dart_CObject* io_buffer = CObject::NewIOBuffer(length);
+        ASSERT(io_buffer != NULL);
+        uint8_t* data = io_buffer->value.as_external_typed_data.data;
+        int64_t bytes_read = file->Read(data, length);
+        if (bytes_read >= 0) {
+          CObjectExternalUint8Array* external_array =
+              new CObjectExternalUint8Array(io_buffer);
+          external_array->SetLength(bytes_read);
+          CObjectArray* result = new CObjectArray(CObject::NewArray(2));
+          result->SetAt(0, new CObjectIntptr(CObject::NewInt32(0)));
+          result->SetAt(1, external_array);
+          return result;
+        } else {
+          CObject::FreeIOBufferData(io_buffer);
+          return CObject::NewOSError();
+        }
       } else {
-        CObject::FreeIOBufferData(io_buffer);
-        return CObject::NewOSError();
+        return CObject::FileClosedError();
       }
     } else {
-      return CObject::FileClosedError();
+      return CObject::IllegalArgumentError();
     }
   }
   return CObject::IllegalArgumentError();
@@ -916,32 +980,34 @@
 
 
 CObject* File::ReadIntoRequest(const CObjectArray& request) {
-  if ((request.Length() == 2) &&
-      request[0]->IsIntptr() &&
-      request[1]->IsInt32OrInt64()) {
+  if ((request.Length() >= 1) && request[0]->IsIntptr()) {
     File* file = CObjectToFilePointer(request[0]);
-    ASSERT(file != NULL);
-    if (!file->IsClosed()) {
-      int64_t length = CObjectInt32OrInt64ToInt64(request[1]);
-      Dart_CObject* io_buffer = CObject::NewIOBuffer(length);
-      ASSERT(io_buffer != NULL);
-      uint8_t* data = io_buffer->value.as_external_typed_data.data;
-      int64_t bytes_read = file->Read(data, length);
-      if (bytes_read >= 0) {
-        CObjectExternalUint8Array* external_array =
-            new CObjectExternalUint8Array(io_buffer);
-        external_array->SetLength(bytes_read);
-        CObjectArray* result = new CObjectArray(CObject::NewArray(3));
-        result->SetAt(0, new CObjectIntptr(CObject::NewInt32(0)));
-        result->SetAt(1, new CObjectInt64(CObject::NewInt64(bytes_read)));
-        result->SetAt(2, external_array);
-        return result;
+    RefCntReleaseScope<File> rs(file);
+    if ((request.Length() == 2) && request[1]->IsInt32OrInt64()) {
+      if (!file->IsClosed()) {
+        int64_t length = CObjectInt32OrInt64ToInt64(request[1]);
+        Dart_CObject* io_buffer = CObject::NewIOBuffer(length);
+        ASSERT(io_buffer != NULL);
+        uint8_t* data = io_buffer->value.as_external_typed_data.data;
+        int64_t bytes_read = file->Read(data, length);
+        if (bytes_read >= 0) {
+          CObjectExternalUint8Array* external_array =
+              new CObjectExternalUint8Array(io_buffer);
+          external_array->SetLength(bytes_read);
+          CObjectArray* result = new CObjectArray(CObject::NewArray(3));
+          result->SetAt(0, new CObjectIntptr(CObject::NewInt32(0)));
+          result->SetAt(1, new CObjectInt64(CObject::NewInt64(bytes_read)));
+          result->SetAt(2, external_array);
+          return result;
+        } else {
+          CObject::FreeIOBufferData(io_buffer);
+          return CObject::NewOSError();
+        }
       } else {
-        CObject::FreeIOBufferData(io_buffer);
-        return CObject::NewOSError();
+        return CObject::FileClosedError();
       }
     } else {
-      return CObject::FileClosedError();
+      return CObject::IllegalArgumentError();
     }
   }
   return CObject::IllegalArgumentError();
@@ -974,46 +1040,49 @@
 
 
 CObject* File::WriteFromRequest(const CObjectArray& request) {
-  if ((request.Length() == 4) &&
-      request[0]->IsIntptr() &&
-      (request[1]->IsTypedData() || request[1]->IsArray()) &&
-      request[2]->IsInt32OrInt64() &&
-      request[3]->IsInt32OrInt64()) {
+  if ((request.Length() >= 1) && request[0]->IsIntptr()) {
     File* file = CObjectToFilePointer(request[0]);
-    ASSERT(file != NULL);
-    if (!file->IsClosed()) {
-      int64_t start = CObjectInt32OrInt64ToInt64(request[2]);
-      int64_t end = CObjectInt32OrInt64ToInt64(request[3]);
-      int64_t length = end - start;
-      uint8_t* buffer_start;
-      if (request[1]->IsTypedData()) {
-        CObjectTypedData typed_data(request[1]);
-        start = start * SizeInBytes(typed_data.Type());
-        length = length * SizeInBytes(typed_data.Type());
-        buffer_start = typed_data.Buffer() + start;
-      } else {
-        CObjectArray array(request[1]);
-        buffer_start = Dart_ScopeAllocate(length);
-        for (int i = 0; i < length; i++) {
-          if (array[i + start]->IsInt32OrInt64()) {
-            int64_t value = CObjectInt32OrInt64ToInt64(array[i + start]);
-            buffer_start[i] = static_cast<uint8_t>(value & 0xFF);
-          } else {
-            // Unsupported type.
-            return CObject::IllegalArgumentError();
+    RefCntReleaseScope<File> rs(file);
+    if ((request.Length() == 4) &&
+        (request[1]->IsTypedData() || request[1]->IsArray()) &&
+        request[2]->IsInt32OrInt64() &&
+        request[3]->IsInt32OrInt64()) {
+      if (!file->IsClosed()) {
+        int64_t start = CObjectInt32OrInt64ToInt64(request[2]);
+        int64_t end = CObjectInt32OrInt64ToInt64(request[3]);
+        int64_t length = end - start;
+        uint8_t* buffer_start;
+        if (request[1]->IsTypedData()) {
+          CObjectTypedData typed_data(request[1]);
+          start = start * SizeInBytes(typed_data.Type());
+          length = length * SizeInBytes(typed_data.Type());
+          buffer_start = typed_data.Buffer() + start;
+        } else {
+          CObjectArray array(request[1]);
+          buffer_start = Dart_ScopeAllocate(length);
+          for (int i = 0; i < length; i++) {
+            if (array[i + start]->IsInt32OrInt64()) {
+              int64_t value = CObjectInt32OrInt64ToInt64(array[i + start]);
+              buffer_start[i] = static_cast<uint8_t>(value & 0xFF);
+            } else {
+              // Unsupported type.
+              return CObject::IllegalArgumentError();
+            }
           }
+          start = 0;
         }
-        start = 0;
-      }
-      bool success =
-          file->WriteFully(reinterpret_cast<void*>(buffer_start), length);
-      if (success) {
-        return new CObjectInt64(CObject::NewInt64(length));
+        bool success =
+            file->WriteFully(reinterpret_cast<void*>(buffer_start), length);
+        if (success) {
+          return new CObjectInt64(CObject::NewInt64(length));
+        } else {
+          return CObject::NewOSError();
+        }
       } else {
-        return CObject::NewOSError();
+        return CObject::FileClosedError();
       }
     } else {
-      return CObject::FileClosedError();
+      return CObject::IllegalArgumentError();
     }
   }
   return CObject::IllegalArgumentError();
@@ -1137,24 +1206,27 @@
 
 
 CObject* File::LockRequest(const CObjectArray& request) {
-  if ((request.Length() == 4) &&
-      request[0]->IsIntptr() &&
-      request[1]->IsInt32OrInt64() &&
-      request[2]->IsInt32OrInt64() &&
-      request[3]->IsInt32OrInt64()) {
+  if ((request.Length() >= 1) && request[0]->IsIntptr()) {
     File* file = CObjectToFilePointer(request[0]);
-    ASSERT(file != NULL);
-    if (!file->IsClosed()) {
-      int64_t lock = CObjectInt32OrInt64ToInt64(request[1]);
-      int64_t start = CObjectInt32OrInt64ToInt64(request[2]);
-      int64_t end = CObjectInt32OrInt64ToInt64(request[3]);
-      if (file->Lock(static_cast<File::LockType>(lock), start, end)) {
-        return CObject::True();
+    RefCntReleaseScope<File> rs(file);
+    if ((request.Length() == 4) &&
+        request[1]->IsInt32OrInt64() &&
+        request[2]->IsInt32OrInt64() &&
+        request[3]->IsInt32OrInt64()) {
+      if (!file->IsClosed()) {
+        int64_t lock = CObjectInt32OrInt64ToInt64(request[1]);
+        int64_t start = CObjectInt32OrInt64ToInt64(request[2]);
+        int64_t end = CObjectInt32OrInt64ToInt64(request[3]);
+        if (file->Lock(static_cast<File::LockType>(lock), start, end)) {
+          return CObject::True();
+        } else {
+          return CObject::NewOSError();
+        }
       } else {
-        return CObject::NewOSError();
+        return CObject::FileClosedError();
       }
     } else {
-      return CObject::FileClosedError();
+      return CObject::IllegalArgumentError();
     }
   }
   return CObject::IllegalArgumentError();
diff --git a/runtime/bin/file.h b/runtime/bin/file.h
index 3c8255f..2c153bc 100644
--- a/runtime/bin/file.h
+++ b/runtime/bin/file.h
@@ -12,6 +12,8 @@
 
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
+#include "bin/log.h"
+#include "bin/reference_counting.h"
 
 namespace dart {
 namespace bin {
@@ -19,7 +21,7 @@
 // Forward declaration.
 class FileHandle;
 
-class File {
+class File : public ReferenceCounted<File> {
  public:
   enum FileOpenMode {
     kRead = 0,
@@ -82,10 +84,10 @@
     kLockMax = 2
   };
 
-  ~File();
-
   intptr_t GetFD();
 
+  void* MapExecutable(intptr_t* num_bytes);
+
   // Read/Write attempt to transfer num_bytes to/from buffer. It returns
   // the number of bytes read/written.
   int64_t Read(void* buffer, int64_t num_bytes);
@@ -124,6 +126,26 @@
   // Returns whether the file has been closed.
   bool IsClosed();
 
+  // Calls the platform-specific functions to close the file.
+  void Close();
+
+  // Returns the weak persistent handle for the File's Dart wrapper.
+  Dart_WeakPersistentHandle WeakHandle() const { return weak_handle_; }
+
+  // Set the weak persistent handle for the File's Dart wrapper.
+  void SetWeakHandle(Dart_WeakPersistentHandle handle) {
+    ASSERT(weak_handle_ == NULL);
+    weak_handle_ = handle;
+  }
+
+  // Deletes the weak persistent handle for the File's Dart wrapper. Call
+  // when the file is explicitly closed and the finalizer is no longer
+  // needed.
+  void DeleteWeakHandle(Dart_Isolate isolate) {
+    Dart_DeleteWeakPersistentHandle(isolate, weak_handle_);
+    weak_handle_ = NULL;
+  }
+
   // Open the file with the given path. The file is always opened for
   // reading. If mode contains kWrite the file is opened for both
   // reading and writing. If mode contains kWrite and the file does
@@ -190,8 +212,12 @@
   static CObject* LockRequest(const CObjectArray& request);
 
  private:
-  explicit File(FileHandle* handle) : handle_(handle) { }
-  void Close();
+  explicit File(FileHandle* handle) :
+      ReferenceCounted(),
+      handle_(handle),
+      weak_handle_(NULL) {}
+
+  ~File();
 
   static File* FileOpenW(const wchar_t* system_name, FileOpenMode mode);
 
@@ -200,6 +226,12 @@
   // FileHandle is an OS specific class which stores data about the file.
   FileHandle* handle_;  // OS specific handle for the file.
 
+  // We retain the weak handle because we can do cleanup eagerly when Dart code
+  // calls closeSync(). In that case, we delete the weak handle so that the
+  // finalizer doesn't run.
+  Dart_WeakPersistentHandle weak_handle_;
+
+  friend class ReferenceCounted<File>;
   DISALLOW_COPY_AND_ASSIGN(File);
 };
 
diff --git a/runtime/bin/file_android.cc b/runtime/bin/file_android.cc
index a115715..8b86121 100644
--- a/runtime/bin/file_android.cc
+++ b/runtime/bin/file_android.cc
@@ -10,6 +10,7 @@
 #include <errno.h>  // NOLINT
 #include <fcntl.h>  // NOLINT
 #include <libgen.h>  // NOLINT
+#include <sys/mman.h>  // NOLINT
 #include <sys/sendfile.h>  // NOLINT
 #include <sys/stat.h>  // NOLINT
 #include <sys/types.h>  // NOLINT
@@ -39,7 +40,9 @@
 
 
 File::~File() {
-  Close();
+  if (!IsClosed()) {
+    Close();
+  }
   delete handle_;
 }
 
@@ -75,6 +78,22 @@
 }
 
 
+void* File::MapExecutable(intptr_t* len) {
+  ASSERT(handle_->fd() >= 0);
+
+  intptr_t length = Length();
+  void* addr = mmap(0, length,
+                    PROT_READ | PROT_EXEC, MAP_PRIVATE,
+                    handle_->fd(), 0);
+  if (addr == MAP_FAILED) {
+    *len = -1;
+  } else {
+    *len = length;
+  }
+  return addr;
+}
+
+
 int64_t File::Read(void* buffer, int64_t num_bytes) {
   ASSERT(handle_->fd() >= 0);
   return TEMP_FAILURE_RETRY(read(handle_->fd(), buffer, num_bytes));
@@ -197,10 +216,7 @@
 
 
 File* File::OpenStdio(int fd) {
-  if ((fd < 0) || (2 < fd)) {
-    return NULL;
-  }
-  return new File(new FileHandle(fd));
+  return ((fd < 0) || (2 < fd)) ? NULL : new File(new FileHandle(fd));
 }
 
 
diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc
index 3099715..2e47d74 100644
--- a/runtime/bin/file_linux.cc
+++ b/runtime/bin/file_linux.cc
@@ -10,6 +10,7 @@
 #include <errno.h>  // NOLINT
 #include <fcntl.h>  // NOLINT
 #include <libgen.h>  // NOLINT
+#include <sys/mman.h>  // NOLINT
 #include <sys/sendfile.h>  // NOLINT
 #include <sys/stat.h>  // NOLINT
 #include <sys/types.h>  // NOLINT
@@ -38,7 +39,9 @@
 
 
 File::~File() {
-  Close();
+  if (!IsClosed()) {
+    Close();
+  }
   delete handle_;
 }
 
@@ -73,6 +76,21 @@
 }
 
 
+void* File::MapExecutable(intptr_t* len) {
+  ASSERT(handle_->fd() >= 0);
+  intptr_t length = Length();
+  void* addr = mmap(0, length,
+                    PROT_READ | PROT_EXEC, MAP_PRIVATE,
+                    handle_->fd(), 0);
+  if (addr == MAP_FAILED) {
+    *len = -1;
+  } else {
+    *len = length;
+  }
+  return addr;
+}
+
+
 int64_t File::Read(void* buffer, int64_t num_bytes) {
   ASSERT(handle_->fd() >= 0);
   return TEMP_FAILURE_RETRY(read(handle_->fd(), buffer, num_bytes));
@@ -155,8 +173,8 @@
   // Report errors for non-regular files.
   struct stat64 st;
   if (TEMP_FAILURE_RETRY(stat64(name, &st)) == 0) {
-    // Only accept regular files and character devices.
-    if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode)) {
+    // Only accept regular files, character devices, and pipes.
+    if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode) && !S_ISFIFO(st.st_mode)) {
       errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT;
       return NULL;
     }
@@ -196,10 +214,7 @@
 
 
 File* File::OpenStdio(int fd) {
-  if ((fd < 0) || (2 < fd)) {
-    return NULL;
-  }
-  return new File(new FileHandle(fd));
+  return ((fd < 0) || (2 < fd)) ? NULL : new File(new FileHandle(fd));
 }
 
 
diff --git a/runtime/bin/file_macos.cc b/runtime/bin/file_macos.cc
index 81412f6..941d419 100644
--- a/runtime/bin/file_macos.cc
+++ b/runtime/bin/file_macos.cc
@@ -12,6 +12,7 @@
 #include <fcntl.h>  // NOLINT
 #include <libgen.h>  // NOLINT
 #include <limits.h>  // NOLINT
+#include <sys/mman.h>  // NOLINT
 #include <sys/stat.h>  // NOLINT
 #include <unistd.h>  // NOLINT
 
@@ -40,7 +41,9 @@
 
 
 File::~File() {
-  Close();
+  if (!IsClosed()) {
+    Close();
+  }
   delete handle_;
 }
 
@@ -76,6 +79,21 @@
 }
 
 
+void* File::MapExecutable(intptr_t* len) {
+  ASSERT(handle_->fd() >= 0);
+  intptr_t length = Length();
+  void* addr = mmap(0, length,
+                    PROT_READ | PROT_EXEC, MAP_PRIVATE,
+                    handle_->fd(), 0);
+  if (addr == MAP_FAILED) {
+    *len = -1;
+  } else {
+    *len = length;
+  }
+  return addr;
+}
+
+
 int64_t File::Read(void* buffer, int64_t num_bytes) {
   ASSERT(handle_->fd() >= 0);
   return TEMP_FAILURE_RETRY(read(handle_->fd(), buffer, num_bytes));
@@ -158,8 +176,8 @@
   // Report errors for non-regular files.
   struct stat st;
   if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) {
-    // Only accept regular files and character devices.
-    if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode)) {
+    // Only accept regular files, character devices, and pipes.
+    if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode) && !S_ISFIFO(st.st_mode)) {
       errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT;
       return NULL;
     }
@@ -199,10 +217,7 @@
 
 
 File* File::OpenStdio(int fd) {
-  if ((fd < 0) || (2 < fd)) {
-    return NULL;
-  }
-  return new File(new FileHandle(fd));
+  return ((fd < 0) || (2 < fd)) ? NULL : new File(new FileHandle(fd));
 }
 
 
diff --git a/runtime/bin/file_patch.dart b/runtime/bin/file_patch.dart
index 479bb9f..a3d42e8 100644
--- a/runtime/bin/file_patch.dart
+++ b/runtime/bin/file_patch.dart
@@ -22,24 +22,34 @@
 }
 
 
-patch class _RandomAccessFile {
-  /* patch */ static int _close(int id) native "File_Close";
-  /* patch */ static int _getFD(int id) native "File_GetFD";
-  /* patch */ static _readByte(int id) native "File_ReadByte";
-  /* patch */ static _read(int id, int bytes) native "File_Read";
-  /* patch */ static _readInto(int id, List<int> buffer, int start, int end)
-      native "File_ReadInto";
-  /* patch */ static _writeByte(int id, int value) native "File_WriteByte";
-  /* patch */ static _writeFrom(int id, List<int> buffer, int start, int end)
-      native "File_WriteFrom";
-  /* patch */ static _position(int id) native "File_Position";
-  /* patch */ static _setPosition(int id, int position)
-      native "File_SetPosition";
-  /* patch */ static _truncate(int id, int length) native "File_Truncate";
-  /* patch */ static _length(int id) native "File_Length";
-  /* patch */ static _flush(int id) native "File_Flush";
-  /* patch */ static _lock(int id, int lock, int start, int end)
-      native "File_Lock";
+patch class _RandomAccessFileOps {
+  /* patch */ factory _RandomAccessFileOps(int pointer)
+      => new _RandomAccessFileOpsImpl(pointer);
+}
+
+
+class _RandomAccessFileOpsImpl extends NativeFieldWrapperClass1
+                               implements _RandomAccessFileOps {
+  _RandomAccessFileOpsImpl._();
+
+  factory _RandomAccessFileOpsImpl(int pointer)
+      => new _RandomAccessFileOpsImpl._().._setPointer(pointer);
+
+  void _setPointer(int pointer) native "File_SetPointer";
+
+  int getPointer() native "File_GetPointer";
+  int close() native "File_Close";
+  readByte() native "File_ReadByte";
+  read(int bytes) native "File_Read";
+  readInto(List<int> buffer, int start, int end) native "File_ReadInto";
+  writeByte(int value) native "File_WriteByte";
+  writeFrom(List<int> buffer, int start, int end) native "File_WriteFrom";
+  position() native "File_Position";
+  setPosition(int position) native "File_SetPosition";
+  truncate(int length) native "File_Truncate";
+  length() native "File_Length";
+  flush() native "File_Flush";
+  lock(int lock, int start, int end) native "File_Lock";
 }
 
 
diff --git a/runtime/bin/file_test.cc b/runtime/bin/file_test.cc
index 518e6e5..4c2c0d1 100644
--- a/runtime/bin/file_test.cc
+++ b/runtime/bin/file_test.cc
@@ -32,7 +32,7 @@
   buffer[13] = '\0';
   EXPECT_STREQ("// Copyright ", buffer);
   EXPECT(!file->WriteByte(1));  // Cannot write to a read-only file.
-  delete file;
+  file->Release();
 }
 
 
@@ -42,7 +42,7 @@
   File* file = File::Open(kFilename, File::kRead);
   EXPECT(file != NULL);
   EXPECT_EQ(42, file->Length());
-  delete file;
+  file->Release();
 }
 
 
@@ -56,7 +56,7 @@
   EXPECT_EQ(12, file->Position());
   EXPECT(file->ReadFully(buf, 6));
   EXPECT_EQ(18, file->Position());
-  delete file;
+  file->Release();
 }
 
 }  // namespace bin
diff --git a/runtime/bin/file_unsupported.cc b/runtime/bin/file_unsupported.cc
index 2655f77..55a88d0 100644
--- a/runtime/bin/file_unsupported.cc
+++ b/runtime/bin/file_unsupported.cc
@@ -11,6 +11,19 @@
 namespace dart {
 namespace bin {
 
+
+void FUNCTION_NAME(File_GetPointer)(Dart_NativeArguments args) {
+  Dart_ThrowException(DartUtils::NewInternalError(
+        "File is not supported on this platform"));
+}
+
+
+void FUNCTION_NAME(File_SetPointer)(Dart_NativeArguments args) {
+  Dart_ThrowException(DartUtils::NewInternalError(
+        "File is not supported on this platform"));
+}
+
+
 void FUNCTION_NAME(File_Open)(Dart_NativeArguments args) {
   Dart_ThrowException(DartUtils::NewInternalError(
         "File is not supported on this platform"));
@@ -29,12 +42,6 @@
 }
 
 
-void FUNCTION_NAME(File_GetFD)(Dart_NativeArguments args) {
-  Dart_ThrowException(DartUtils::NewInternalError(
-        "File is not supported on this platform"));
-}
-
-
 void FUNCTION_NAME(File_ReadByte)(Dart_NativeArguments args) {
   Dart_ThrowException(DartUtils::NewInternalError(
         "File is not supported on this platform"));
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 054370a..db3aef8 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -38,7 +38,9 @@
 
 
 File::~File() {
-  Close();
+  if (!IsClosed()) {
+    Close();
+  }
   delete handle_;
 }
 
@@ -71,6 +73,12 @@
 }
 
 
+void* File::MapExecutable(intptr_t* len) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
 int64_t File::Read(void* buffer, int64_t num_bytes) {
   ASSERT(handle_->fd() >= 0);
   return read(handle_->fd(), buffer, num_bytes);
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 258b9a7..7783422 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -22,26 +22,47 @@
 
 #include "include/dart_api.h"
 
+#include "platform/hashmap.h"
 #include "platform/globals.h"
 
 namespace dart {
 namespace bin {
 
+// Exit code indicating an API error.
+static const int kApiErrorExitCode = 253;
+// Exit code indicating a compilation error.
+static const int kCompilationErrorExitCode = 254;
+// Exit code indicating an unhandled error that is not a compilation error.
+static const int kErrorExitCode = 255;
+// Exit code indicating a vm restart request.  Never returned to the user.
+static const int kRestartRequestExitCode = 1000;
+
 #define CHECK_RESULT(result)                                                   \
   if (Dart_IsError(result)) {                                                  \
+    intptr_t exit_code = 0;                                                    \
     Log::PrintErr("Error: %s", Dart_GetError(result));                         \
+    if (Dart_IsCompilationError(result)) {                                     \
+      exit_code = kCompilationErrorExitCode;                                   \
+    } else if (Dart_IsApiError(result)) {                                      \
+      exit_code = kApiErrorExitCode;                                           \
+    } else if (Dart_IsVMRestartRequest(result)) {                              \
+      exit_code = kRestartRequestExitCode;                                     \
+    } else {                                                                   \
+      exit_code = kErrorExitCode;                                              \
+    }                                                                          \
     Dart_ExitScope();                                                          \
     Dart_ShutdownIsolate();                                                    \
-    exit(255);                                                                 \
-  }                                                                            \
+    exit(exit_code);                                                           \
+  }
 
 
 // Global state that indicates whether a snapshot is to be created and
 // if so which file to write the snapshot into.
 static const char* vm_isolate_snapshot_filename = NULL;
 static const char* isolate_snapshot_filename = NULL;
-static const char* instructions_snapshot_filename = NULL;
-static const char* embedder_entry_points_manifest = NULL;
+static const char* assembly_filename = NULL;
+static const char* instructions_blob_filename = NULL;
+static const char* rodata_blob_filename = NULL;
 static const char* package_root = NULL;
 
 
@@ -54,6 +75,10 @@
 // Global state that captures the URL mappings specified on the command line.
 static CommandLineOptions* url_mapping = NULL;
 
+// Global state that captures the entry point manifest files specified on the
+// command line.
+static CommandLineOptions* entry_points_files = NULL;
+
 static bool IsValidFlag(const char* name,
                         const char* prefix,
                         intptr_t prefix_length) {
@@ -63,6 +88,93 @@
 }
 
 
+// The environment provided through the command line using -D options.
+static dart::HashMap* environment = NULL;
+
+static void* GetHashmapKeyFromString(char* key) {
+  return reinterpret_cast<void*>(key);
+}
+
+static bool ProcessEnvironmentOption(const char* arg) {
+  ASSERT(arg != NULL);
+  if (*arg == '\0') {
+    return false;
+  }
+  if (*arg != '-') {
+    return false;
+  }
+  if (*(arg + 1) != 'D') {
+    return false;
+  }
+  arg = arg + 2;
+  if (*arg == '\0') {
+    return true;
+  }
+  if (environment == NULL) {
+    environment = new HashMap(&HashMap::SameStringValue, 4);
+  }
+  // Split the name=value part of the -Dname=value argument.
+  char* name;
+  char* value = NULL;
+  const char* equals_pos = strchr(arg, '=');
+  if (equals_pos == NULL) {
+    // No equal sign (name without value) currently not supported.
+    Log::PrintErr("No value given to -D option\n");
+    return false;
+  } else {
+    int name_len = equals_pos - arg;
+    if (name_len == 0) {
+      Log::PrintErr("No name given to -D option\n");
+      return false;
+    }
+    // Split name=value into name and value.
+    name = reinterpret_cast<char*>(malloc(name_len + 1));
+    strncpy(name, arg, name_len);
+    name[name_len] = '\0';
+    value = strdup(equals_pos + 1);
+  }
+  HashMap::Entry* entry = environment->Lookup(
+      GetHashmapKeyFromString(name), HashMap::StringHash(name), true);
+  ASSERT(entry != NULL);  // Lookup adds an entry if key not found.
+  entry->value = value;
+  return true;
+}
+
+
+static Dart_Handle EnvironmentCallback(Dart_Handle name) {
+  uint8_t* utf8_array;
+  intptr_t utf8_len;
+  Dart_Handle result = Dart_Null();
+  Dart_Handle handle = Dart_StringToUTF8(name, &utf8_array, &utf8_len);
+  if (Dart_IsError(handle)) {
+    handle = Dart_ThrowException(
+        DartUtils::NewDartArgumentError(Dart_GetError(handle)));
+  } else {
+    char* name_chars = reinterpret_cast<char*>(malloc(utf8_len + 1));
+    memmove(name_chars, utf8_array, utf8_len);
+    name_chars[utf8_len] = '\0';
+    const char* value = NULL;
+    printf("Looking for %s\n", name_chars);
+    if (environment != NULL) {
+      HashMap::Entry* entry = environment->Lookup(
+          GetHashmapKeyFromString(name_chars),
+          HashMap::StringHash(name_chars),
+          false);
+      if (entry != NULL) {
+        value = reinterpret_cast<char*>(entry->value);
+      }
+    }
+    if (value != NULL) {
+      result = Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(value),
+                                      strlen(value));
+    }
+    free(name_chars);
+  }
+  return result;
+}
+
+
+
 static const char* ProcessOption(const char* option, const char* name) {
   const intptr_t length = strlen(name);
   if (strncmp(option, name, length) == 0) {
@@ -92,10 +204,30 @@
 }
 
 
-static bool ProcessInstructionsSnapshotOption(const char* option) {
-  const char* name = ProcessOption(option, "--instructions_snapshot=");
+static bool ProcessAssemblyOption(const char* option) {
+  const char* name = ProcessOption(option, "--assembly=");
   if (name != NULL) {
-    instructions_snapshot_filename = name;
+    assembly_filename = name;
+    return true;
+  }
+  return false;
+}
+
+
+static bool ProcessInstructionsBlobOption(const char* option) {
+  const char* name = ProcessOption(option, "--instructions_blob=");
+  if (name != NULL) {
+    instructions_blob_filename = name;
+    return true;
+  }
+  return false;
+}
+
+
+static bool ProcessRodataBlobOption(const char* option) {
+  const char* name = ProcessOption(option, "--rodata_blob=");
+  if (name != NULL) {
+    rodata_blob_filename = name;
     return true;
   }
   return false;
@@ -105,7 +237,7 @@
 static bool ProcessEmbedderEntryPointsManifestOption(const char* option) {
   const char* name = ProcessOption(option, "--embedder_entry_points_manifest=");
   if (name != NULL) {
-    embedder_entry_points_manifest = name;
+    entry_points_files->AddArgument(name);
     return true;
   }
   return false;
@@ -114,6 +246,9 @@
 
 static bool ProcessPackageRootOption(const char* option) {
   const char* name = ProcessOption(option, "--package_root=");
+  if (name == NULL) {
+    name = ProcessOption(option, "--package-root=");
+  }
   if (name != NULL) {
     package_root = name;
     return true;
@@ -135,13 +270,18 @@
 }
 
 
+static bool IsSnapshottingForPrecompilation() {
+  return (assembly_filename != NULL) || (instructions_blob_filename != NULL);
+}
+
+
 // Parse out the command line arguments. Returns -1 if the arguments
 // are incorrect, 0 otherwise.
 static int ParseArguments(int argc,
                           char** argv,
                           CommandLineOptions* vm_options,
                           char** script_name) {
-  const char* kPrefix = "--";
+  const char* kPrefix = "-";
   const intptr_t kPrefixLen = strlen(kPrefix);
 
   // Skip the binary name.
@@ -151,10 +291,13 @@
   while ((i < argc) && IsValidFlag(argv[i], kPrefix, kPrefixLen)) {
     if (ProcessVmIsolateSnapshotOption(argv[i]) ||
         ProcessIsolateSnapshotOption(argv[i]) ||
-        ProcessInstructionsSnapshotOption(argv[i]) ||
+        ProcessAssemblyOption(argv[i]) ||
+        ProcessInstructionsBlobOption(argv[i]) ||
+        ProcessRodataBlobOption(argv[i]) ||
         ProcessEmbedderEntryPointsManifestOption(argv[i]) ||
         ProcessURLmappingOption(argv[i]) ||
-        ProcessPackageRootOption(argv[i])) {
+        ProcessPackageRootOption(argv[i]) ||
+        ProcessEnvironmentOption(argv[i])) {
       i += 1;
       continue;
     }
@@ -180,32 +323,36 @@
     return -1;
   }
 
-  if ((instructions_snapshot_filename != NULL) &&
-      (embedder_entry_points_manifest == NULL)) {
+  bool precompiled_as_assembly = assembly_filename != NULL;
+  bool precompiled_as_blobs = (instructions_blob_filename != NULL) ||
+                              (rodata_blob_filename != NULL);
+  if (precompiled_as_assembly && precompiled_as_blobs) {
+    Log::PrintErr(
+      "Cannot request a precompiled snapshot simultaneously as "
+      "assembly (--assembly=<output.file>) and as blobs "
+      "(--instructions-blob=<output.file> and "
+      "--rodata-blob=<output.file>)\n\n");
+    return -1;
+  }
+  if ((instructions_blob_filename != NULL) != (rodata_blob_filename != NULL)) {
+    Log::PrintErr(
+      "Requesting a precompiled snapshot as blobs requires both "
+      "(--instructions-blob=<output.file> and "
+      "--rodata-blob=<output.file>)\n\n");
+    return -1;
+  }
+  if (IsSnapshottingForPrecompilation() &&
+      (entry_points_files->count() == 0)) {
     Log::PrintErr(
         "Specifying an instructions snapshot filename indicates precompilation"
         ". But no embedder entry points manifest was specified.\n\n");
     return -1;
   }
 
-  if ((embedder_entry_points_manifest != NULL) &&
-      (instructions_snapshot_filename == NULL)) {
-    Log::PrintErr(
-        "Specifying the embedder entry points manifest indicates "
-        "precompilation. But no instuctions snapshot was specified.\n\n");
-    return -1;
-  }
-
   return 0;
 }
 
 
-static bool IsSnapshottingForPrecompilation(void) {
-  return embedder_entry_points_manifest != NULL &&
-         instructions_snapshot_filename != NULL;
-}
-
-
 static void WriteSnapshotFile(const char* filename,
                               const uint8_t* buffer,
                               const intptr_t size) {
@@ -214,7 +361,7 @@
   if (!file->WriteFully(buffer, size)) {
     Log::PrintErr("Error: Failed to write snapshot file.\n\n");
   }
-  delete file;
+  file->Release();
 }
 
 
@@ -469,17 +616,23 @@
 "  optional.                                                                 \n"
 "                                                                            \n"
 "  Precompilation:                                                           \n"
-"  In order to configure the snapshotter for precompilation, both the        \n"
-"  instructions snapshot and embedder entry points manifest must be          \n"
-"  specified. Assembly for the target architecture will be dumped into the   \n"
-"  instructions snapshot. This must be linked into the target binary in a    \n"
-"  separate step. The embedder entry points manifest lists the standalone    \n"
-"  entry points into the VM. Not specifying these will cause the tree shaker \n"
-"  to disregard the same as being used. The format of this manifest is as    \n"
-"  follows. Each line in the manifest is a comma separated list of three     \n"
-"  elements. The first entry is the library URI, the second entry is the     \n"
-"  class name and the final entry the function name. The file must be        \n"
-"  terminated with a newline charater.                                       \n"
+"  In order to configure the snapshotter for precompilation, either          \n"
+"  --assembly=outputfile or --instructions_blob=outputfile1 and              \n"
+"  --rodata_blob=outputfile2 must be specified. If the former is choosen,    \n"
+"  assembly for the target architecture will be output into the given file,  \n"
+"  which must be compiled separately and either statically linked or         \n"
+"  dynamically loaded in the target executable. The symbols                  \n"
+"  kInstructionsSnapshot and kDataSnapshot must be passed to Dart_Initialize.\n"
+"  If the latter is choosen, binary data is output into the given files,     \n"
+"  which should be mmapped and passed to Dart_Initialize, with the           \n"
+"  instruction blob being mapped as executable.                              \n"
+"  In both cases, a entry points manifest must be given to list the places   \n"
+"  in the Dart program the embedder calls from the C API (Dart_Invoke, etc). \n"
+"  Not specifying these may cause the tree shaker to remove them from the    \n"
+"  program. The format of this manifest is as follows. Each line in the      \n"
+"  manifest is a comma separated list of three elements. The first entry is  \n"
+"  the library URI, the second entry is the class name and the final entry   \n"
+"  the function name. The file must be terminated with a newline charater.   \n"
 "                                                                            \n"
 "    Example:                                                                \n"
 "      dart:something,SomeClass,doSomething                                  \n"
@@ -497,12 +650,18 @@
 "                                      the command line to load the          \n"
 "                                      libraries.                            \n"
 "                                                                            \n"
-"    --instructions_snapshot=<file>    (Precompilation only) Contains the    \n"
+"    --assembly=<file>                 (Precompilation only) Contains the    \n"
 "                                      assembly that must be linked into     \n"
 "                                      the target binary                     \n"
 "                                                                            \n"
-"    --embedder_entry_points_manifest=<file> (Precompilation only) Contains  \n"
-"                                      the stanalone embedder entry points\n");
+"    --instructions_blob=<file>        (Precompilation only) Contains the    \n"
+"    --rodata_blob=<file>              instructions and read-only data that  \n"
+"                                      must be mapped into the target binary \n"
+"                                                                            \n"
+"    --embedder_entry_points_manifest=<file> (Precompilation or app          \n"
+"                                      snapshots) Contains embedder's entry  \n"
+"                                      points into Dart code from the C API. \n"
+"\n");
 }
 
 
@@ -510,9 +669,7 @@
   if (Dart_IsError(library)) {
     const char* err_msg = Dart_GetError(library);
     Log::PrintErr("Errors encountered while loading: %s\n", err_msg);
-    Dart_ExitScope();
-    Dart_ShutdownIsolate();
-    exit(255);
+    CHECK_RESULT(library);
   }
   ASSERT(Dart_IsLibrary(library));
 }
@@ -781,31 +938,34 @@
 }
 
 
-static Dart_QualifiedFunctionName* ParseEntryPointsManifestFile(
-    const char* path) {
-  if (path == NULL) {
-    return NULL;
-  }
+static Dart_QualifiedFunctionName* ParseEntryPointsManifestFiles() {
+  // Total number of entries across all manifest files.
+  int64_t entry_count = 0;
 
-  FILE* file = fopen(path, "r");
-
-  if (file == NULL) {
-    Log::PrintErr("Could not open entry points manifest file\n");
-    return NULL;
-  }
-
-  // Parse the file once but don't store the results. This is done to first
+  // Parse the files once but don't store the results. This is done to first
   // determine the number of entries in the manifest
-  int64_t entry_count = ParseEntryPointsManifestLines(file, NULL);
+  for (intptr_t i = 0; i < entry_points_files->count(); i++) {
+    const char* path = entry_points_files->GetArgument(i);
 
-  if (entry_count <= 0) {
-    Log::PrintErr(
-        "Manifest file specified is invalid or contained no entries\n");
+    FILE* file = fopen(path, "r");
+
+    if (file == NULL) {
+      Log::PrintErr("Could not open entry points manifest file `%s`\n", path);
+      return NULL;
+    }
+
+    int64_t entries = ParseEntryPointsManifestLines(file, NULL);
     fclose(file);
-    return NULL;
-  }
 
-  rewind(file);
+    if (entries <= 0) {
+      Log::PrintErr(
+          "Manifest file `%s` specified is invalid or contained no entries\n",
+          path);
+      return NULL;
+    }
+
+    entry_count += entries;
+  }
 
   // Allocate enough storage for the entries in the file plus a termination
   // sentinel and parse it again to populate the allocation
@@ -813,10 +973,16 @@
       reinterpret_cast<Dart_QualifiedFunctionName*>(
           calloc(entry_count + 1, sizeof(Dart_QualifiedFunctionName)));
 
-  int64_t parsed_entry_count = ParseEntryPointsManifestLines(file, entries);
-  ASSERT(parsed_entry_count == entry_count);
+  int64_t parsed_entry_count = 0;
+  for (intptr_t i = 0; i < entry_points_files->count(); i++) {
+    const char* path = entry_points_files->GetArgument(i);
+    FILE* file = fopen(path, "r");
+    parsed_entry_count +=
+        ParseEntryPointsManifestLines(file, &entries[parsed_entry_count]);
+    fclose(file);
+  }
 
-  fclose(file);
+  ASSERT(parsed_entry_count == entry_count);
 
   // The entries allocation must be explicitly cleaned up via
   // |CleanupEntryPointsCollection|
@@ -825,8 +991,7 @@
 
 
 static Dart_QualifiedFunctionName* ParseEntryPointsManifestIfPresent() {
-  Dart_QualifiedFunctionName* entries =
-      ParseEntryPointsManifestFile(embedder_entry_points_manifest);
+  Dart_QualifiedFunctionName* entries = ParseEntryPointsManifestFiles();
   if ((entries == NULL) && IsSnapshottingForPrecompilation()) {
     Log::PrintErr(
         "Could not find native embedder entry points during precompilation\n");
@@ -874,34 +1039,58 @@
   intptr_t vm_isolate_size = 0;
   uint8_t* isolate_buffer = NULL;
   intptr_t isolate_size = 0;
-  uint8_t* instructions_buffer = NULL;
-  intptr_t instructions_size = 0;
+  uint8_t* assembly_buffer = NULL;
+  intptr_t assembly_size = 0;
+  uint8_t* instructions_blob_buffer = NULL;
+  intptr_t instructions_blob_size = 0;
+  uint8_t* rodata_blob_buffer = NULL;
+  intptr_t rodata_blob_size = 0;
 
   // Precompile with specified embedder entry points
   result = Dart_Precompile(standalone_entry_points, true);
   CHECK_RESULT(result);
 
-  // Create a precompiled snapshot. This gives us an instruction buffer with
-  // machine code
-  result = Dart_CreatePrecompiledSnapshot(&vm_isolate_buffer,
-                                          &vm_isolate_size,
-                                          &isolate_buffer,
-                                          &isolate_size,
-                                          &instructions_buffer,
-                                          &instructions_size);
-  CHECK_RESULT(result);
+  // Create a precompiled snapshot.
+  bool as_assembly = assembly_filename != NULL;
+  if (as_assembly) {
+    result = Dart_CreatePrecompiledSnapshotAssembly(&vm_isolate_buffer,
+                                                    &vm_isolate_size,
+                                                    &isolate_buffer,
+                                                    &isolate_size,
+                                                    &assembly_buffer,
+                                                    &assembly_size);
+    CHECK_RESULT(result);
+  } else {
+    result = Dart_CreatePrecompiledSnapshotBlob(&vm_isolate_buffer,
+                                                &vm_isolate_size,
+                                                &isolate_buffer,
+                                                &isolate_size,
+                                                &instructions_blob_buffer,
+                                                &instructions_blob_size,
+                                                &rodata_blob_buffer,
+                                                &rodata_blob_size);
+    CHECK_RESULT(result);
+  }
 
-  // Now write the vm isolate, isolate and instructions snapshots out to the
-  // specified files and exit.
+  // Now write the snapshot pieces out to the specified files and exit.
   WriteSnapshotFile(vm_isolate_snapshot_filename,
                     vm_isolate_buffer,
                     vm_isolate_size);
   WriteSnapshotFile(isolate_snapshot_filename,
                     isolate_buffer,
                     isolate_size);
-  WriteSnapshotFile(instructions_snapshot_filename,
-                    instructions_buffer,
-                    instructions_size);
+  if (as_assembly) {
+    WriteSnapshotFile(assembly_filename,
+                      assembly_buffer,
+                      assembly_size);
+  } else {
+    WriteSnapshotFile(instructions_blob_filename,
+                      instructions_blob_buffer,
+                      instructions_blob_size);
+    WriteSnapshotFile(rodata_blob_filename,
+                      rodata_blob_buffer,
+                      rodata_blob_size);
+  }
   Dart_ExitScope();
 
   // Shutdown the isolate.
@@ -998,6 +1187,10 @@
   CommandLineOptions url_mapping_array(argc);
   url_mapping = &url_mapping_array;
 
+  // Initialize the entrypoints array.
+  CommandLineOptions entry_points_files_array(argc);
+  entry_points_files = &entry_points_files_array;
+
   // Parse command line arguments.
   if (ParseArguments(argc,
                      argv,
@@ -1067,6 +1260,9 @@
   Dart_Handle library;
   Dart_EnterScope();
 
+  result = Dart_SetEnvironmentCallback(EnvironmentCallback);
+  CHECK_RESULT(result);
+
   ASSERT(vm_isolate_snapshot_filename != NULL);
   ASSERT(isolate_snapshot_filename != NULL);
   // Load up the script before a snapshot is created.
@@ -1108,6 +1304,8 @@
       exit(255);
     }
     Dart_EnterScope();
+    result = Dart_SetEnvironmentCallback(EnvironmentCallback);
+    CHECK_RESULT(result);
 
     // Set up the library tag handler in such a manner that it will use the
     // URL mapping specified on the command line to load the libraries.
@@ -1129,8 +1327,7 @@
     result = Dart_FinalizeLoading(false);
     CHECK_RESULT(result);
 
-    if (entry_points == NULL) {
-      ASSERT(!IsSnapshottingForPrecompilation());
+    if (!IsSnapshottingForPrecompilation()) {
       CreateAndWriteSnapshot();
     } else {
       CreateAndWritePrecompiledSnapshot(entry_points);
diff --git a/runtime/bin/io_impl_sources.gypi b/runtime/bin/io_impl_sources.gypi
index ccb050c..c0de4c23 100644
--- a/runtime/bin/io_impl_sources.gypi
+++ b/runtime/bin/io_impl_sources.gypi
@@ -46,12 +46,14 @@
     'process_macos.cc',
     'process_unsupported.cc',
     'process_win.cc',
+    'reference_counting.h',
     '../../third_party/root_certificates/root_certificates.cc',
     'root_certificates_unsupported.cc',
     'secure_socket.h',
     'secure_socket_boringssl.cc',
     'secure_socket_boringssl.h',
     'secure_socket_ios.cc',
+    'secure_socket_ios.h',
     'secure_socket_macos.cc',
     'secure_socket_macos.h',
     'secure_socket_unsupported.cc',
diff --git a/runtime/bin/io_natives.cc b/runtime/bin/io_natives.cc
index 39946a7..4c55b6f 100644
--- a/runtime/bin/io_natives.cc
+++ b/runtime/bin/io_natives.cc
@@ -29,11 +29,14 @@
   V(Directory_Delete, 2)                                                       \
   V(Directory_Rename, 2)                                                       \
   V(Directory_List, 3)                                                         \
+  V(Directory_GetAsyncDirectoryListerPointer, 1)                               \
+  V(Directory_SetAsyncDirectoryListerPointer, 2)                               \
   V(EventHandler_SendData, 3)                                                  \
   V(EventHandler_TimerMillisecondClock, 0)                                     \
+  V(File_GetPointer, 1)                                                        \
+  V(File_SetPointer, 2)                                                        \
   V(File_Open, 2)                                                              \
   V(File_Exists, 1)                                                            \
-  V(File_GetFD, 1)                                                             \
   V(File_Close, 1)                                                             \
   V(File_ReadByte, 1)                                                          \
   V(File_WriteByte, 2)                                                         \
@@ -75,6 +78,7 @@
   V(Filter_Processed, 3)                                                       \
   V(InternetAddress_Parse, 1)                                                  \
   V(IOService_NewServicePort, 0)                                               \
+  V(NetworkInterface_ListSupported, 0)                                         \
   V(Platform_NumberOfProcessors, 0)                                            \
   V(Platform_OperatingSystem, 0)                                               \
   V(Platform_PathSeparator, 0)                                                 \
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index fdf6248..0ef6653 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -83,6 +83,11 @@
 static bool run_precompiled_snapshot = false;
 
 
+// Global flag that is used to indicate that we want to use blobs/mmap instead
+// of assembly/shared libraries for precompilation.
+static bool use_blobs = false;
+
+
 // Value of the --gen/run_precompiled_snapshot flag.
 // (This pointer points into an argv buffer and does not need to be
 // free'd.)
@@ -105,7 +110,10 @@
 extern const char* kPrecompiledDataSymbolName;
 static const char* kPrecompiledVmIsolateName = "precompiled.vmisolate";
 static const char* kPrecompiledIsolateName = "precompiled.isolate";
-static const char* kPrecompiledInstructionsName = "precompiled.S";
+static const char* kPrecompiledAssemblyName = "precompiled.S";
+static const char* kPrecompiledInstructionsBlobName =
+    "precompiled.instructions";
+static const char* kPrecompiledRodataBlobName = "precompiled.rodata";
 static const char* kVMIsolateSuffix = "vmisolate";
 static const char* kIsolateSuffix = "isolate";
 
@@ -326,6 +334,17 @@
 }
 
 
+static bool ProcessUseBlobsOption(const char* arg,
+                                  CommandLineOptions* vm_options) {
+  ASSERT(arg != NULL);
+  if (*arg != '\0') {
+    return false;
+  }
+  use_blobs = true;
+  return true;
+}
+
+
 static bool ProcessGenPrecompiledSnapshotOption(
     const char* arg,
     CommandLineOptions* vm_options) {
@@ -410,13 +429,13 @@
 
 static bool ProcessRunFullSnapshotOption(
     const char* filename, CommandLineOptions* vm_options) {
-#ifndef DART_PRODUCT_BINARY
+#if !defined(PRODUCT)
   Log::PrintErr("Full Application snapshots can only be be run with"
-                " dart_product\n");
+                " product mode\n");
   return false;
 #else
   return ProcessSnapshotOptionHelper(filename, &run_full_snapshot);
-#endif  // defined(DART_PRODUCT_BINARY)
+#endif  // defined(PRODUCT)
 }
 
 
@@ -513,6 +532,7 @@
 
   // VM specific options to the standalone dart program.
   { "--compile_all", ProcessCompileAllOption },
+  { "--use_blobs", ProcessUseBlobsOption },
   { "--enable-vm-service", ProcessEnableVmServiceOption },
   { "--gen-precompiled-snapshot", ProcessGenPrecompiledSnapshotOption },
   { "--observe", ProcessObserveOption },
@@ -746,14 +766,12 @@
                                                 int* exit_code) {
   ASSERT(script_uri != NULL);
 
-#if defined(DART_PRODUCT_BINARY)
-  const bool run_service_isolate = false;
-#elif defined(PRODUCT)
+#if defined(PRODUCT)
   const bool run_service_isolate = !run_full_snapshot &&
                                    !run_precompiled_snapshot;
 #else
   const bool run_service_isolate = !run_full_snapshot;
-#endif
+#endif  // PRODUCT
   if (!run_service_isolate &&
       (strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0)) {
     // We do not create a service isolate when running a full application
@@ -787,9 +805,6 @@
   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,
@@ -806,7 +821,6 @@
     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.
@@ -1105,7 +1119,7 @@
               "Unable to open file %s for writing snapshot\n",
               qualified_filename);
   }
-  delete file;
+  file->Release();
   if (concat != NULL) {
     delete concat;
   }
@@ -1149,6 +1163,35 @@
 }
 
 
+static void ReadExecutableSnapshotFile(const char* snapshot_directory,
+                                       const char* filename,
+                                       const uint8_t** buffer) {
+  char* concat = NULL;
+  const char* qualified_filename;
+  if ((snapshot_directory != NULL) && (strlen(snapshot_directory) > 0)) {
+    intptr_t len = snprintf(NULL, 0, "%s/%s", snapshot_directory, filename);
+    concat = new char[len + 1];
+    snprintf(concat, len + 1, "%s/%s", snapshot_directory, filename);
+    qualified_filename = concat;
+  } else {
+    qualified_filename = filename;
+  }
+
+  intptr_t len = -1;
+  *buffer = reinterpret_cast<uint8_t*>(
+      DartUtils::MapExecutable(qualified_filename, &len));
+  if ((*buffer == NULL) || (len == -1)) {
+    fprintf(stderr,
+            "Error: Unable to read snapshot file %s\n", qualified_filename);
+    fflush(stderr);
+    Platform::Exit(kErrorExitCode);
+  }
+  if (concat != NULL) {
+    delete concat;
+  }
+}
+
+
 static void* LoadLibrarySymbol(const char* snapshot_directory,
                                const char* libname,
                                const char* symname) {
@@ -1307,7 +1350,7 @@
         reinterpret_cast<IsolateData*>(Dart_IsolateData(isolate));
     result = Dart_LibraryImportLibrary(
         isolate_data->builtin_lib(), root_lib, Dart_Null());
-#if !defined(DART_PRODUCT_BINARY) && !defined(PRODUCT)
+#if !defined(PRODUCT)
     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.
@@ -1319,7 +1362,7 @@
         exit(kErrorExitCode);
       }
     }
-#endif  // !DART_PRODUCT_BINARY
+#endif  // PRODUCT
 
     if (compile_all) {
       result = Dart_CompileAll();
@@ -1371,15 +1414,33 @@
       intptr_t vm_isolate_size = 0;
       uint8_t* isolate_buffer = NULL;
       intptr_t isolate_size = 0;
-      uint8_t* instructions_buffer = NULL;
-      intptr_t instructions_size = 0;
-      result = Dart_CreatePrecompiledSnapshot(&vm_isolate_buffer,
-                                              &vm_isolate_size,
-                                              &isolate_buffer,
-                                              &isolate_size,
-                                              &instructions_buffer,
-                                              &instructions_size);
-      CHECK_RESULT(result);
+      uint8_t* assembly_buffer = NULL;
+      intptr_t assembly_size = 0;
+      uint8_t* instructions_blob_buffer = NULL;
+      intptr_t instructions_blob_size = NULL;
+      uint8_t* rodata_blob_buffer = NULL;
+      intptr_t rodata_blob_size = NULL;
+      if (use_blobs) {
+        result = Dart_CreatePrecompiledSnapshotBlob(
+            &vm_isolate_buffer,
+            &vm_isolate_size,
+            &isolate_buffer,
+            &isolate_size,
+            &instructions_blob_buffer,
+            &instructions_blob_size,
+            &rodata_blob_buffer,
+            &rodata_blob_size);
+        CHECK_RESULT(result);
+      } else {
+        result = Dart_CreatePrecompiledSnapshotAssembly(
+            &vm_isolate_buffer,
+            &vm_isolate_size,
+            &isolate_buffer,
+            &isolate_size,
+            &assembly_buffer,
+            &assembly_size);
+        CHECK_RESULT(result);
+      }
       WriteSnapshotFile(precompiled_snapshot_directory,
                         kPrecompiledVmIsolateName,
                         false,
@@ -1390,11 +1451,24 @@
                         false,
                         isolate_buffer,
                         isolate_size);
-      WriteSnapshotFile(precompiled_snapshot_directory,
-                        kPrecompiledInstructionsName,
-                        false,
-                        instructions_buffer,
-                        instructions_size);
+      if (use_blobs) {
+        WriteSnapshotFile(precompiled_snapshot_directory,
+                          kPrecompiledInstructionsBlobName,
+                          false,
+                          instructions_blob_buffer,
+                          instructions_blob_size);
+        WriteSnapshotFile(precompiled_snapshot_directory,
+                          kPrecompiledRodataBlobName,
+                          false,
+                          rodata_blob_buffer,
+                          rodata_blob_size);
+      } else {
+        WriteSnapshotFile(precompiled_snapshot_directory,
+                          kPrecompiledAssemblyName,
+                          false,
+                          assembly_buffer,
+                          assembly_size);
+      }
     } else {
       if (Dart_IsNull(root_lib)) {
         ErrorExit(kErrorExitCode,
@@ -1611,21 +1685,29 @@
   const uint8_t* instructions_snapshot = NULL;
   const uint8_t* data_snapshot = NULL;
   if (run_precompiled_snapshot) {
-    instructions_snapshot = reinterpret_cast<const uint8_t*>(
-        LoadLibrarySymbol(precompiled_snapshot_directory,
-                          kPrecompiledLibraryName,
-                          kPrecompiledInstructionsSymbolName));
-    data_snapshot = reinterpret_cast<const uint8_t*>(
-        LoadLibrarySymbol(precompiled_snapshot_directory,
-                          kPrecompiledLibraryName,
-                          kPrecompiledDataSymbolName));
     ReadSnapshotFile(precompiled_snapshot_directory,
                      kPrecompiledVmIsolateName,
                      &vm_isolate_snapshot_buffer);
     ReadSnapshotFile(precompiled_snapshot_directory,
                      kPrecompiledIsolateName,
                      &isolate_snapshot_buffer);
-
+    if (use_blobs) {
+      ReadExecutableSnapshotFile(precompiled_snapshot_directory,
+                                 kPrecompiledInstructionsBlobName,
+                                 &instructions_snapshot);
+      ReadSnapshotFile(precompiled_snapshot_directory,
+                       kPrecompiledRodataBlobName,
+                       &data_snapshot);
+    } else {
+      instructions_snapshot = reinterpret_cast<const uint8_t*>(
+          LoadLibrarySymbol(precompiled_snapshot_directory,
+                            kPrecompiledLibraryName,
+                            kPrecompiledInstructionsSymbolName));
+      data_snapshot = reinterpret_cast<const uint8_t*>(
+          LoadLibrarySymbol(precompiled_snapshot_directory,
+                            kPrecompiledLibraryName,
+                            kPrecompiledDataSymbolName));
+    }
   } else if (run_full_snapshot) {
     char* vm_snapshot_fname;
     char* isolate_snapshot_fname;
diff --git a/runtime/bin/platform.h b/runtime/bin/platform.h
index 79cb7be..b4c10a2 100644
--- a/runtime/bin/platform.h
+++ b/runtime/bin/platform.h
@@ -6,6 +6,7 @@
 #define BIN_PLATFORM_H_
 
 #include "bin/builtin.h"
+#include "platform/globals.h"
 
 namespace dart {
 namespace bin {
@@ -19,10 +20,30 @@
   static int NumberOfProcessors();
 
   // Returns a string representing the operating system ("linux",
-  // "macos" or "windows"). The returned string should not be
+  // "macos", "windows", or "android"). The returned string should not be
   // deallocated by the caller.
   static const char* OperatingSystem();
 
+  // Returns the architecture name of the processor the VM is running on
+  // (ia32, x64, arm, arm64, or mips).
+  static const char* HostArchitecture() {
+#if defined(HOST_ARCH_ARM)
+    return "arm";
+#elif defined(HOST_ARCH_ARM64)
+    return "arm64";
+#elif defined(HOST_ARCH_IA32)
+    return "ia32";
+#elif defined(HOST_ARCH_MIPS)
+    return "mips";
+#elif defined(HOST_ARCH_X64)
+    return "x64";
+#else
+#error Architecture detection failed.
+#endif
+  }
+
+  static const char* LibraryPrefix();
+
   // Returns a string representing the operating system's shared library
   // extension (e.g. 'so', 'dll', ...). The returned string should not be
   // deallocated by the caller.
diff --git a/runtime/bin/platform_android.cc b/runtime/bin/platform_android.cc
index 1f29b21..f713c9a 100644
--- a/runtime/bin/platform_android.cc
+++ b/runtime/bin/platform_android.cc
@@ -47,6 +47,11 @@
 }
 
 
+const char* Platform::LibraryPrefix() {
+  return "lib";
+}
+
+
 const char* Platform::LibraryExtension() {
   return "so";
 }
diff --git a/runtime/bin/platform_linux.cc b/runtime/bin/platform_linux.cc
index 054ff6d..4eb1a07 100644
--- a/runtime/bin/platform_linux.cc
+++ b/runtime/bin/platform_linux.cc
@@ -47,6 +47,11 @@
 }
 
 
+const char* Platform::LibraryPrefix() {
+  return "lib";
+}
+
+
 const char* Platform::LibraryExtension() {
   return "so";
 }
diff --git a/runtime/bin/platform_macos.cc b/runtime/bin/platform_macos.cc
index 24c83fd..628056b 100644
--- a/runtime/bin/platform_macos.cc
+++ b/runtime/bin/platform_macos.cc
@@ -64,6 +64,11 @@
 }
 
 
+const char* Platform::LibraryPrefix() {
+  return "lib";
+}
+
+
 const char* Platform::LibraryExtension() {
   return "dylib";
 }
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index 1eb9d3b..ee1ac49 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -45,6 +45,11 @@
 }
 
 
+const char* Platform::LibraryPrefix() {
+  return "";
+}
+
+
 const char* Platform::LibraryExtension() {
   return "dll";
 }
diff --git a/runtime/bin/reference_counting.h b/runtime/bin/reference_counting.h
new file mode 100644
index 0000000..8e79f4f
--- /dev/null
+++ b/runtime/bin/reference_counting.h
@@ -0,0 +1,159 @@
+// 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.
+
+#ifndef BIN_REFERENCE_COUNTING_H_
+#define BIN_REFERENCE_COUNTING_H_
+
+#include "vm/atomic.h"
+
+namespace dart {
+namespace bin {
+
+// Forward declaration.
+template <class Target> class RefCntReleaseScope;
+
+// Inherit from this class where instances of the derived class should be
+// reference counted. Reference counts on instances are incremented and
+// decremented explicitly with calls to Retain() and Release(). E.g.:
+//
+// class Foo : public ReferenceCounted<Foo> {
+//  public:
+//   Foo() : ReferenceCounted() {}
+//   ...
+// };
+//
+// void DoStuffWithAFoo() {
+//   Foo* foo = new Foo();  // Reference count starts at 1, so no explicit
+//                          // call to Retain is needed after allocation.
+//   ...
+//   foo->Release();
+// }
+template <class Derived>
+class ReferenceCounted {
+ public:
+  ReferenceCounted() :
+    ref_count_(1) {
+  }
+
+  ~ReferenceCounted() {
+    ASSERT(ref_count_ == 0);
+  }
+
+  void Retain() {
+    uintptr_t old = AtomicOperations::FetchAndIncrement(&ref_count_);
+    ASSERT(old > 0);
+  }
+
+  void Release() {
+    uintptr_t old = AtomicOperations::FetchAndDecrement(&ref_count_);
+    ASSERT(old > 0);
+    if (old == 1) {
+      delete static_cast<Derived*>(this);
+    }
+  }
+
+ private:
+  uintptr_t ref_count_;
+
+  // These are used only in the ASSERT below in RefCntReleaseScope.
+  uintptr_t ref_count() const { return ref_count_; }
+  friend class RefCntReleaseScope<Derived>;
+  DISALLOW_COPY_AND_ASSIGN(ReferenceCounted);
+};
+
+// Creates a scope at the end of which a reference counted object is
+// Released. This is useful for reference counted objects recieved by the IO
+// Service, which have already been Retained E.g.:
+//
+// CObject* Foo::FooRequest(const CObjectArray& request) {
+//   Foo* foo = CObjectToFoo(request[0]);
+//   RefCntReleaseScope<Foo> rs(foo);
+//   ...
+// }
+template <class Target>
+class RefCntReleaseScope {
+ public:
+  explicit RefCntReleaseScope(ReferenceCounted<Target>* t) : target_(t) {
+    ASSERT(target_ != NULL);
+    ASSERT(target_->ref_count() > 0);
+  }
+  ~RefCntReleaseScope() {
+    target_->Release();
+  }
+
+ private:
+  ReferenceCounted<Target>* target_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(RefCntReleaseScope);
+};
+
+// Instances of RetainedPointer manage Retaining and Releasing reference counted
+// objects. There are two ways to use it. First, it can be used as a field in
+// a class, e.g.:
+//
+// class Foo {
+//  private:
+//   RetainedPointer<Bar> bar_;
+//  public:
+//   explicit Foo(Bar* b) : bar_(b) {}
+// }
+//
+// In this case, b will be Retained in Foo's constructor, and Released
+// automatically during Foo's destructor.
+//
+// RetainedPointer can also be used as a scope, as with RefCntReleaseScope,
+// with the difference that entering the scope also Retains the pointer, e.g.:
+//
+// void RetainAndDoStuffWithFoo(Foo* foo) {
+//   RetainedPointer<Foo> retained(foo);
+//   ..
+// }
+//
+// This Retains foo on entry and Releases foo at every exit from the scope.
+//
+// The underlying pointer can be accessed with the get() and set() methods.
+// Overwriting a non-NULL pointer with set causes that pointer to be Released.
+template <class Target>
+class RetainedPointer {
+ public:
+  RetainedPointer() : target_(NULL) {}
+
+  explicit RetainedPointer(ReferenceCounted<Target>* t) : target_(t) {
+    if (target_ != NULL) {
+      target_->Retain();
+    }
+  }
+
+  ~RetainedPointer() {
+    if (target_ != NULL) {
+      target_->Release();
+    }
+  }
+
+  void set(ReferenceCounted<Target>* t) {
+    if (target_ != NULL) {
+      target_->Release();
+    }
+    target_ = t;
+    if (target_ != NULL) {
+      target_->Retain();
+    }
+  }
+
+  Target* get() const {
+    return static_cast<Target*>(target_);
+  }
+
+ private:
+  ReferenceCounted<Target>* target_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(RetainedPointer);
+};
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // BIN_REFERENCE_COUNTING_H_
diff --git a/runtime/bin/secure_socket.h b/runtime/bin/secure_socket.h
index 07ff2b0..5dfee9e 100644
--- a/runtime/bin/secure_socket.h
+++ b/runtime/bin/secure_socket.h
@@ -15,7 +15,11 @@
     defined(TARGET_OS_WINDOWS)
 #include "bin/secure_socket_boringssl.h"
 #elif defined(TARGET_OS_MACOS)
+#if TARGET_OS_IOS
+#include "bin/secure_socket_ios.h"
+#else  // TARGET_OS_IOS
 #include "bin/secure_socket_macos.h"
+#endif  // TARGET_OS_IOS
 #else
 #error Unknown target os.
 #endif
diff --git a/runtime/bin/secure_socket_boringssl.cc b/runtime/bin/secure_socket_boringssl.cc
index 530c21a..0fd1c9e 100644
--- a/runtime/bin/secure_socket_boringssl.cc
+++ b/runtime/bin/secure_socket_boringssl.cc
@@ -121,7 +121,7 @@
     Dart_WeakPersistentHandle handle,
     void* context_pointer) {
   SSLFilter* filter = reinterpret_cast<SSLFilter*>(context_pointer);
-  delete filter;
+  filter->Release();
 }
 
 
@@ -207,7 +207,7 @@
   SSLFilter* filter = new SSLFilter();
   Dart_Handle err = SetFilter(args, filter);
   if (Dart_IsError(err)) {
-    delete filter;
+    filter->Release();
     Dart_PropagateError(err);
   }
   err = filter->Init(dart_this);
@@ -324,7 +324,11 @@
 
 
 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) {
-  intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args));
+  SSLFilter* filter = GetFilter(args);
+  // This filter pointer is passed to the IO Service thread. The IO Service
+  // thread must Release() the pointer when it is done with it.
+  filter->Retain();
+  intptr_t filter_pointer = reinterpret_cast<intptr_t>(filter);
   Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer));
 }
 
@@ -1086,6 +1090,8 @@
 CObject* SSLFilter::ProcessFilterRequest(const CObjectArray& request) {
   CObjectIntptr filter_object(request[0]);
   SSLFilter* filter = reinterpret_cast<SSLFilter*>(filter_object.Value());
+  RefCntReleaseScope<SSLFilter> rs(filter);
+
   bool in_handshake = CObjectBool(request[1]).Value();
   int starts[SSLFilter::kNumBuffers];
   int ends[SSLFilter::kNumBuffers];
diff --git a/runtime/bin/secure_socket_boringssl.h b/runtime/bin/secure_socket_boringssl.h
index 9dbe250..d5449a4 100644
--- a/runtime/bin/secure_socket_boringssl.h
+++ b/runtime/bin/secure_socket_boringssl.h
@@ -21,6 +21,7 @@
 
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
+#include "bin/reference_counting.h"
 #include "bin/socket.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
@@ -39,7 +40,7 @@
  * reading and writing encrypted text.  The filter handles handshaking
  * and certificate verification.
  */
-class SSLFilter {
+class SSLFilter : public ReferenceCounted<SSLFilter> {
  public:
   // These enums must agree with those in sdk/lib/io/secure_socket.dart.
   enum BufferIndex {
diff --git a/runtime/bin/secure_socket_ios.cc b/runtime/bin/secure_socket_ios.cc
index 76da230..a92c45b 100644
--- a/runtime/bin/secure_socket_ios.cc
+++ b/runtime/bin/secure_socket_ios.cc
@@ -8,7 +8,7 @@
 #if TARGET_OS_IOS
 
 #include "bin/secure_socket.h"
-#include "bin/secure_socket_macos.h"
+#include "bin/secure_socket_ios.h"
 
 #include <errno.h>
 #include <fcntl.h>
@@ -52,58 +52,21 @@
 
 static const bool SSL_LOG_STATUS = false;
 static const bool SSL_LOG_DATA = false;
+static const bool SSL_LOG_CERTS = false;
 static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 1000;
+static const intptr_t PEM_BUFSIZE = 1024;
 
-// SSLCertContext wraps the certificates needed for a SecureTransport
-// connection. Fields are protected by the mutex_ field, and may only be set
-// once. This is to allow access by both the Dart thread and the IOService
-// thread. Setters return false if the field was already set.
-class SSLCertContext {
- public:
-  SSLCertContext() :
-      mutex_(new Mutex()),
-      trusted_certs_(NULL),
-      trust_builtin_(false) {}
+static char* CFStringRefToCString(CFStringRef cfstring) {
+  CFIndex len = CFStringGetLength(cfstring);
+  CFIndex max_len =
+      CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8) + 1;
+  char* result = reinterpret_cast<char*>(Dart_ScopeAllocate(max_len));
+  ASSERT(result != NULL);
+  bool success =
+      CFStringGetCString(cfstring, result, max_len, kCFStringEncodingUTF8);
+  return success ? result : NULL;
+}
 
-  ~SSLCertContext() {
-    delete mutex_;
-    if (trusted_certs_ != NULL) {
-      CFRelease(trusted_certs_);
-    }
-  }
-
-  CFMutableArrayRef trusted_certs() {
-    MutexLocker m(mutex_);
-    return trusted_certs_;
-  }
-  void add_trusted_cert(SecCertificateRef trusted_cert) {
-    // Takes ownership of trusted_cert.
-    MutexLocker m(mutex_);
-    if (trusted_certs_ == NULL) {
-      trusted_certs_ = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-    }
-    CFArrayAppendValue(trusted_certs_, trusted_cert);
-    CFRelease(trusted_cert);  // trusted_cert is retained by the array.
-  }
-
-  bool trust_builtin() {
-    MutexLocker m(mutex_);
-    return trust_builtin_;
-  }
-  void set_trust_builtin(bool trust_builtin) {
-    MutexLocker m(mutex_);
-    trust_builtin_ = trust_builtin;
-  }
-
- private:
-  // The context is accessed both by Dart code and the IOService. This mutex
-  // protects all fields.
-  Mutex* mutex_;
-  CFMutableArrayRef trusted_certs_;
-  bool trust_builtin_;
-
-  DISALLOW_COPY_AND_ASSIGN(SSLCertContext);
-};
 
 // Handle an error reported from the SecureTransport library.
 static void ThrowIOException(OSStatus status,
@@ -148,7 +111,7 @@
                          Dart_WeakPersistentHandle handle,
                          void* context_pointer) {
   SSLFilter* filter = reinterpret_cast<SSLFilter*>(context_pointer);
-  delete filter;
+  filter->Release();
 }
 
 
@@ -187,7 +150,7 @@
                               Dart_WeakPersistentHandle handle,
                               void* context_pointer) {
   SSLCertContext* context = static_cast<SSLCertContext*>(context_pointer);
-  delete context;
+  context->Release();
 }
 
 
@@ -210,6 +173,18 @@
 }
 
 
+static SecCertificateRef GetX509Certificate(Dart_NativeArguments args) {
+  SecCertificateRef certificate;
+  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+  ASSERT(Dart_IsInstance(dart_this));
+  ThrowIfError(Dart_GetNativeInstanceField(
+      dart_this,
+      kX509NativeFieldIndex,
+      reinterpret_cast<intptr_t*>(&certificate)));
+  return certificate;
+}
+
+
 static void ReleaseCertificate(void* isolate_data,
                                Dart_WeakPersistentHandle handle,
                                void* context_pointer) {
@@ -256,12 +231,161 @@
 }
 
 
+static const char* GetPasswordArgument(Dart_NativeArguments args,
+                                       intptr_t index) {
+  Dart_Handle password_object =
+      ThrowIfError(Dart_GetNativeArgument(args, index));
+  const char* password = NULL;
+  if (Dart_IsString(password_object)) {
+    ThrowIfError(Dart_StringToCString(password_object, &password));
+    if (strlen(password) > PEM_BUFSIZE - 1) {
+      Dart_ThrowException(DartUtils::NewDartArgumentError(
+          "Password length is greater than 1023 bytes."));
+    }
+  } else if (Dart_IsNull(password_object)) {
+    password = "";
+  } else {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "Password is not a String or null"));
+  }
+  return password;
+}
+
+
+static OSStatus TryPKCS12Import(CFDataRef cfdata,
+                                CFStringRef password,
+                                CFArrayRef* out_certs,
+                                SecIdentityRef* out_identity) {
+  const void* keys[] = { kSecImportExportPassphrase };
+  const void* values[] = { password };
+  CFDictionaryRef params =
+      CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
+  CFArrayRef items = NULL;
+  OSStatus status = SecPKCS12Import(cfdata, params, &items);
+  CFRelease(params);
+
+  if (status != noErr) {
+    if (SSL_LOG_STATUS) {
+      Log::PrintErr("SecPKCS12Import: status = %ld",
+          static_cast<intptr_t>(status));
+      return status;
+    }
+  }
+
+  CFIndex items_length = (items == NULL) ? 0 : CFArrayGetCount(items);
+  if (SSL_LOG_CERTS) {
+    Log::PrintErr("TryPKCS12Import succeeded, count = %ld\n", items_length);
+  }
+
+  // Empty list indicates a decoding failure of some sort.
+  if ((items != NULL) && (items_length == 0)) {
+    CFRelease(items);
+    return errSSLBadCert;
+  }
+
+  CFMutableArrayRef result_certs =
+      CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+  SecIdentityRef result_identity = NULL;
+
+  for (CFIndex i = 0; i < items_length; i++) {
+    CFTypeRef item =
+        reinterpret_cast<CFTypeRef>(CFArrayGetValueAtIndex(items, i));
+    ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID());
+    CFDictionaryRef dict = reinterpret_cast<CFDictionaryRef>(item);
+
+    //  Trust.
+    CFTypeRef trust_item = CFDictionaryGetValue(dict, kSecImportItemTrust);
+    if (trust_item != NULL) {
+      ASSERT(CFGetTypeID(trust_item) == SecTrustGetTypeID());
+      if (SSL_LOG_CERTS) {
+        Log::PrintErr("\titem %ld has a trust object\n", i);
+      }
+      // TODO(zra): Is this useful for anything?
+    }
+
+    // Identity.
+    CFTypeRef identity_item =
+        CFDictionaryGetValue(dict, kSecImportItemIdentity);
+    if (identity_item != NULL) {
+      ASSERT(CFGetTypeID(identity_item) == SecIdentityGetTypeID());
+      if (SSL_LOG_CERTS) {
+        Log::PrintErr("\titem %ld has an identity object\n", i);
+      }
+      // Only extract the first identity we find.
+      if (result_identity == NULL) {
+        result_identity =
+            reinterpret_cast<SecIdentityRef>(const_cast<void*>(identity_item));
+        CFRetain(result_identity);
+      }
+    }
+
+    // Certificates.
+    CFTypeRef cert_items = CFDictionaryGetValue(dict, kSecImportItemCertChain);
+    if (cert_items != NULL) {
+      ASSERT(CFGetTypeID(cert_items) == CFArrayGetTypeID());
+      CFArrayRef certs = reinterpret_cast<CFArrayRef>(cert_items);
+      if (SSL_LOG_CERTS) {
+        CFIndex count = CFArrayGetCount(certs);
+        Log::PrintErr("\titem %ld has a cert chain %ld certs long\n", i, count);
+      }
+      CFArrayAppendArray(
+          result_certs, certs, CFRangeMake(0, CFArrayGetCount(certs)));
+    }
+  }
+
+  if (out_certs == NULL) {
+    if (result_certs != NULL) {
+      CFRelease(result_certs);
+    }
+  } else {
+    *out_certs = result_certs;
+  }
+
+  if (out_identity == NULL) {
+    if (result_identity != NULL) {
+      CFRelease(result_identity);
+    }
+  } else {
+    *out_identity = result_identity;
+  }
+
+  // On failure, don't return any objects.
+  ASSERT((status == noErr) ||
+         ((result_certs == NULL) && (result_identity == NULL)));
+  return status;
+}
+
+
+static OSStatus ExtractSecItems(uint8_t* buffer,
+                                intptr_t length,
+                                const char* password,
+                                CFArrayRef* out_certs,
+                                SecIdentityRef* out_identity) {
+  ASSERT(buffer != NULL);
+  ASSERT(password != NULL);
+  OSStatus status = noErr;
+
+  CFDataRef cfdata = CFDataCreateWithBytesNoCopy(
+      NULL, buffer, length, kCFAllocatorNull);
+  CFStringRef cfpassword = CFStringCreateWithCStringNoCopy(
+      NULL, password, kCFStringEncodingUTF8, kCFAllocatorNull);
+  ASSERT(cfdata != NULL);
+  ASSERT(cfpassword != NULL);
+
+  status = TryPKCS12Import(cfdata, cfpassword, out_certs, out_identity);
+
+  CFRelease(cfdata);
+  CFRelease(cfpassword);
+  return status;
+}
+
+
 void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) {
   Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
   SSLFilter* filter = new SSLFilter();  // Deleted in DeleteFilter finalizer.
   Dart_Handle err = SetFilter(args, filter);
   if (Dart_IsError(err)) {
-    delete filter;
+    filter->Release();
     Dart_PropagateError(err);
   }
   err = filter->Init(dart_this);
@@ -372,7 +496,11 @@
 
 
 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) {
-  intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args));
+  SSLFilter* filter = GetFilter(args);
+  // This filter pointer is passed to the IO Service thread. The IO Service
+  // thread must Release() the pointer when it is done with it.
+  filter->Retain();
+  intptr_t filter_pointer = reinterpret_cast<intptr_t>(filter);
   Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer));
 }
 
@@ -382,7 +510,7 @@
   // cert_context deleted in DeleteCertContext finalizer.
   Dart_Handle err = SetSecurityContext(args, cert_context);
   if (Dart_IsError(err)) {
-    delete cert_context;
+    cert_context->Release();
     Dart_PropagateError(err);
   }
 }
@@ -390,8 +518,42 @@
 
 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)(
     Dart_NativeArguments args) {
-  Dart_ThrowException(DartUtils::NewDartUnsupportedError(
-      "SecurityContext.usePrivateKeyBytes is not yet implemented."));
+  SSLCertContext* context = GetSecurityContext(args);
+  const char* password = GetPasswordArgument(args, 2);
+
+  OSStatus status;
+  CFArrayRef cert_chain = NULL;
+  SecIdentityRef identity = NULL;
+  {
+    ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+    status = ExtractSecItems(
+        buffer.get(), buffer.length(), password, &cert_chain, &identity);
+  }
+
+  // Set the context fields. Repeated calls to usePrivateKeyBytes are an error.
+  bool set_failure = false;
+  if ((identity != NULL) && !context->set_identity(identity)) {
+    CFRelease(identity);
+    if (cert_chain != NULL) {
+      CFRelease(cert_chain);
+    }
+    set_failure = true;
+  }
+
+  // We can't have set a cert_chain without also having set an identity.
+  // That is, if context->set_identity() succeeds, then it is impossible for
+  // context->set_cert_chain() to fail. This is because SecPKCS12Import never
+  // returns a cert chain without also returning a private key.
+  ASSERT(set_failure || (context->cert_chain() == NULL));
+  if (!set_failure && (cert_chain != NULL)) {
+    context->set_cert_chain(cert_chain);
+  }
+
+  if (set_failure) {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "usePrivateKeyBytes has already been called on the given context."));
+  }
+  CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes");
 }
 
 
@@ -433,15 +595,16 @@
 
 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)(
     Dart_NativeArguments args) {
-  Dart_ThrowException(DartUtils::NewDartUnsupportedError(
-      "SecurityContext.useCertificateChainBytes is not yet implemented."));
+  // This is a no-op on iOS. We get the cert chain along with the private key
+  // in UsePrivateyKeyBytes().
 }
 
 
 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)(
     Dart_NativeArguments args) {
   Dart_ThrowException(DartUtils::NewDartUnsupportedError(
-      "SecurityContext.setClientAuthoritiesBytes is not yet implemented."));
+      "SecurityContext.setClientAuthoritiesBytes is not supported on this "
+      "platform."));
 }
 
 
@@ -453,8 +616,16 @@
 
 
 void FUNCTION_NAME(X509_Subject)(Dart_NativeArguments args) {
-  Dart_ThrowException(DartUtils::NewDartUnsupportedError(
-      "X509Certificate.subject is not yet implemented."));
+  SecCertificateRef certificate = GetX509Certificate(args);
+  CFStringRef cfsubject = SecCertificateCopySubjectSummary(certificate);
+  if (cfsubject != NULL) {
+    char* csubject = CFStringRefToCString(cfsubject);
+    CFRelease(cfsubject);
+    Dart_SetReturnValue(args, Dart_NewStringFromCString(csubject));
+  } else {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "X509.subject failed to find subject's common name."));
+  }
 }
 
 
@@ -498,6 +669,8 @@
 CObject* SSLFilter::ProcessFilterRequest(const CObjectArray& request) {
   CObjectIntptr filter_object(request[0]);
   SSLFilter* filter = reinterpret_cast<SSLFilter*>(filter_object.Value());
+  RefCntReleaseScope<SSLFilter> rs(filter);
+
   bool in_handshake = CObjectBool(request[1]).Value();
   intptr_t starts[SSLFilter::kNumBuffers];
   intptr_t ends[SSLFilter::kNumBuffers];
@@ -864,6 +1037,27 @@
       "TlsException",
       "Failed to set minimum protocol version to kTLSProtocol1");
 
+  // If the context has an identity pass it to SSLSetCertificate().
+  if (context->identity() != NULL) {
+    CFMutableArrayRef chain =
+        CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+    CFArrayAppendValue(chain, context->identity());
+
+    // Append the certificate chain if there is one.
+    if (context->cert_chain() != NULL) {
+      // Skip the first one, it's already included in the identity.
+      CFIndex chain_length = CFArrayGetCount(context->cert_chain());
+      if (chain_length > 1) {
+        CFArrayAppendArray(
+            chain, context->cert_chain(), CFRangeMake(1, chain_length));
+      }
+    }
+
+    status = SSLSetCertificate(ssl_context, chain);
+    CFRelease(chain);
+    CheckStatus(status, "TlsException", "SSLSetCertificate failed");
+  }
+
   if (is_server) {
     SSLAuthenticate auth =
         require_client_certificate
@@ -886,7 +1080,7 @@
   }
 
   // Add the contexts to our wrapper.
-  cert_context_ = context;
+  cert_context_.set(context);
   ssl_context_ = ssl_context;
   is_server_ = is_server;
 
@@ -908,7 +1102,7 @@
   OSStatus status = noErr;
 
   if (SSL_LOG_STATUS) {
-    Log::Print("Handshake evaluating trust.\n");
+    Log::PrintErr("Handshake evaluating trust.\n");
   }
   SecTrustRef peer_trust = NULL;
   status = SSLCopyPeerTrust(ssl_context_, &peer_trust);
@@ -918,15 +1112,16 @@
       return noErr;
     }
     if (SSL_LOG_STATUS) {
-      Log::Print("Handshake error from SSLCopyPeerTrust(): %ld.\n",
+      Log::PrintErr("Handshake error from SSLCopyPeerTrust(): %ld.\n",
           static_cast<intptr_t>(status));
     }
     return status;
   }
 
   CFArrayRef trusted_certs = NULL;
-  if (cert_context_->trusted_certs() != NULL) {
-    trusted_certs = CFArrayCreateCopy(NULL, cert_context_->trusted_certs());
+  if (cert_context_.get()->trusted_certs() != NULL) {
+    trusted_certs =
+        CFArrayCreateCopy(NULL, cert_context_.get()->trusted_certs());
   } else {
     trusted_certs = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
   }
@@ -934,7 +1129,7 @@
   status = SecTrustSetAnchorCertificates(peer_trust, trusted_certs);
   if (status != noErr) {
     if (SSL_LOG_STATUS) {
-      Log::Print("Handshake error from SecTrustSetAnchorCertificates: %ld\n",
+      Log::PrintErr("Handshake error from SecTrustSetAnchorCertificates: %ld\n",
           static_cast<intptr_t>(status));
     }
     CFRelease(trusted_certs);
@@ -943,12 +1138,12 @@
   }
 
   if (SSL_LOG_STATUS) {
-    Log::Print("Handshake %s built in root certs\n",
-        cert_context_->trust_builtin() ? "trusting" : "not trusting");
+    Log::PrintErr("Handshake %s built in root certs\n",
+        cert_context_.get()->trust_builtin() ? "trusting" : "not trusting");
   }
 
   status = SecTrustSetAnchorCertificatesOnly(
-      peer_trust, !cert_context_->trust_builtin());
+      peer_trust, !cert_context_.get()->trust_builtin());
   if (status != noErr) {
     CFRelease(trusted_certs);
     CFRelease(peer_trust);
@@ -982,7 +1177,7 @@
     return noErr;
   } else {
     if (SSL_LOG_STATUS) {
-      Log::Print("Trust eval failed: trust_restul = %d\n", trust_result);
+      Log::PrintErr("Trust eval failed: trust_result = %d\n", trust_result);
     }
     bad_cert_ = true;
     return errSSLBadCert;
@@ -991,15 +1186,15 @@
 
 
 OSStatus SSLFilter::Handshake() {
-  ASSERT(cert_context_ != NULL);
+  ASSERT(cert_context_.get() != NULL);
   ASSERT(ssl_context_ != NULL);
   // Try and push handshake along.
   if (SSL_LOG_STATUS) {
-    Log::Print("Doing SSLHandshake\n");
+    Log::PrintErr("Doing SSLHandshake\n");
   }
   OSStatus status = SSLHandshake(ssl_context_);
   if (SSL_LOG_STATUS) {
-    Log::Print("SSLHandshake returned %ld\n", static_cast<intptr_t>(status));
+    Log::PrintErr("SSLHandshake returned %ld\n", static_cast<intptr_t>(status));
   }
 
   if ((status == errSSLServerAuthCompleted) ||
@@ -1024,7 +1219,7 @@
   // Handshake succeeded.
   if ((in_handshake_) && (status == noErr)) {
     if (SSL_LOG_STATUS) {
-      Log::Print("Finished with the Handshake\n");
+      Log::PrintErr("Finished with the Handshake\n");
     }
     connected_ = true;
   }
@@ -1058,7 +1253,7 @@
 OSStatus SSLFilter::CheckHandshake() {
   if (bad_cert_ && in_handshake_) {
     if (SSL_LOG_STATUS) {
-      Log::Print("Invoking bad certificate callback\n");
+      Log::PrintErr("Invoking bad certificate callback\n");
     }
     ASSERT(peer_certs_ != NULL);
     CFIndex peer_certs_len = CFArrayGetCount(peer_certs_);
@@ -1081,7 +1276,7 @@
 
   if (connected_ && in_handshake_) {
     if (SSL_LOG_STATUS) {
-      Log::Print("Invoking handshake complete callback\n");
+      Log::PrintErr("Invoking handshake complete callback\n");
     }
     ThrowIfError(Dart_InvokeClosure(
         Dart_HandleFromPersistent(handshake_complete_), 0, NULL));
@@ -1104,8 +1299,6 @@
 
 
 SSLFilter::~SSLFilter() {
-  // cert_context_ deleted by finalizer. Don't delete here.
-  cert_context_ = NULL;
   if (ssl_context_ != NULL) {
     CFRelease(ssl_context_);
     ssl_context_ = NULL;
@@ -1202,7 +1395,7 @@
   }
 
   if (SSL_LOG_DATA) {
-    Log::Print("SSLReadCallback: requested: %ld, read %ld bytes\n",
+    Log::PrintErr("SSLReadCallback: requested: %ld, read %ld bytes\n",
         *data_requested, data_read);
   }
 
@@ -1228,7 +1421,7 @@
         length,
         &bytes);
     if (SSL_LOG_STATUS) {
-      Log::Print("SSLRead: status = %ld\n", static_cast<intptr_t>(status));
+      Log::PrintErr("SSLRead: status = %ld\n", static_cast<intptr_t>(status));
     }
     if ((status != noErr) && (status != errSSLWouldBlock)) {
       *bytes_processed = 0;
@@ -1236,7 +1429,8 @@
     }
   }
   if (SSL_LOG_DATA) {
-    Log::Print("ProcessReadPlaintextBuffer: requested: %ld, read %ld bytes\n",
+    Log::PrintErr(
+        "ProcessReadPlaintextBuffer: requested: %ld, read %ld bytes\n",
         length, bytes);
   }
   *bytes_processed = static_cast<intptr_t>(bytes);
@@ -1293,7 +1487,7 @@
   }
 
   if (SSL_LOG_DATA) {
-    Log::Print("SSLWriteCallback: provided: %ld, written %ld bytes\n",
+    Log::PrintErr("SSLWriteCallback: provided: %ld, written %ld bytes\n",
         *data_provided, data_written);
   }
 
@@ -1317,7 +1511,7 @@
         length,
         &bytes);
     if (SSL_LOG_STATUS) {
-      Log::Print("SSLWrite: status = %ld\n", static_cast<intptr_t>(status));
+      Log::PrintErr("SSLWrite: status = %ld\n", static_cast<intptr_t>(status));
     }
     if ((status != noErr) && (status != errSSLWouldBlock)) {
       *bytes_processed = 0;
@@ -1325,7 +1519,7 @@
     }
   }
   if (SSL_LOG_DATA) {
-    Log::Print("ProcessWritePlaintextBuffer: requested: %ld, written: %ld\n",
+    Log::PrintErr("ProcessWritePlaintextBuffer: requested: %ld, written: %ld\n",
         length, bytes);
   }
   *bytes_processed = static_cast<intptr_t>(bytes);
diff --git a/runtime/bin/secure_socket_ios.h b/runtime/bin/secure_socket_ios.h
new file mode 100644
index 0000000..d67de71
--- /dev/null
+++ b/runtime/bin/secure_socket_ios.h
@@ -0,0 +1,240 @@
+// 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.
+
+#ifndef BIN_SECURE_SOCKET_IOS_H_
+#define BIN_SECURE_SOCKET_IOS_H_
+
+#if !defined(BIN_SECURE_SOCKET_H_)
+#error Do not include secure_socket_macos.h directly. Use secure_socket.h.
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/SecureTransport.h>
+#include <Security/Security.h>
+
+#include "bin/builtin.h"
+#include "bin/dartutils.h"
+#include "bin/lockers.h"
+#include "bin/reference_counting.h"
+#include "bin/socket.h"
+#include "bin/thread.h"
+#include "bin/utils.h"
+
+namespace dart {
+namespace bin {
+
+// SSLCertContext wraps the certificates needed for a SecureTransport
+// connection. Fields are protected by the mutex_ field, and may only be set
+// once. This is to allow access by both the Dart thread and the IOService
+// thread. Setters return false if the field was already set.
+class SSLCertContext : public ReferenceCounted<SSLCertContext> {
+ public:
+  SSLCertContext() :
+      ReferenceCounted(),
+      mutex_(new Mutex()),
+      trusted_certs_(NULL),
+      identity_(NULL),
+      cert_chain_(NULL),
+      trust_builtin_(false) {}
+
+  ~SSLCertContext() {
+    {
+      MutexLocker m(mutex_);
+      if (trusted_certs_ != NULL) {
+        CFRelease(trusted_certs_);
+      }
+      if (identity_ != NULL) {
+        CFRelease(identity_);
+      }
+      if (cert_chain_ != NULL) {
+        CFRelease(cert_chain_);
+      }
+    }
+    delete mutex_;
+  }
+
+  CFMutableArrayRef trusted_certs() {
+    MutexLocker m(mutex_);
+    return trusted_certs_;
+  }
+  void add_trusted_cert(SecCertificateRef trusted_cert) {
+    // Takes ownership of trusted_cert.
+    MutexLocker m(mutex_);
+    if (trusted_certs_ == NULL) {
+      trusted_certs_ = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+    }
+    CFArrayAppendValue(trusted_certs_, trusted_cert);
+    CFRelease(trusted_cert);  // trusted_cert is retained by the array.
+  }
+
+  SecIdentityRef identity() {
+    MutexLocker m(mutex_);
+    return identity_;
+  }
+  bool set_identity(SecIdentityRef identity) {
+    MutexLocker m(mutex_);
+    if (identity_ == NULL) {
+      identity_ = identity;
+      return true;
+    }
+    return false;
+  }
+
+  CFArrayRef cert_chain() {
+    MutexLocker m(mutex_);
+    return cert_chain_;
+  }
+  bool set_cert_chain(CFArrayRef cert_chain) {
+    MutexLocker m(mutex_);
+    if (cert_chain_ == NULL) {
+      cert_chain_ = cert_chain;
+      return true;
+    }
+    return false;
+  }
+
+  bool trust_builtin() {
+    MutexLocker m(mutex_);
+    return trust_builtin_;
+  }
+  void set_trust_builtin(bool trust_builtin) {
+    MutexLocker m(mutex_);
+    trust_builtin_ = trust_builtin;
+  }
+
+ private:
+  // The context is accessed both by Dart code and the IOService. This mutex
+  // protects all fields.
+  Mutex* mutex_;
+  CFMutableArrayRef trusted_certs_;
+  SecIdentityRef identity_;
+  CFArrayRef cert_chain_;
+  bool trust_builtin_;
+
+  DISALLOW_COPY_AND_ASSIGN(SSLCertContext);
+};
+
+// SSLFilter encapsulates the SecureTransport code in a filter that communicates
+// with the containing _SecureFilterImpl Dart object through four shared
+// ExternalByteArray buffers, for reading and writing plaintext, and
+// reading and writing encrypted text.  The filter handles handshaking
+// and certificate verification.
+class SSLFilter : public ReferenceCounted<SSLFilter> {
+ public:
+  // These enums must agree with those in sdk/lib/io/secure_socket.dart.
+  enum BufferIndex {
+    kReadPlaintext,
+    kWritePlaintext,
+    kReadEncrypted,
+    kWriteEncrypted,
+    kNumBuffers,
+    kFirstEncrypted = kReadEncrypted
+  };
+
+  SSLFilter()
+      : ReferenceCounted(),
+        cert_context_(NULL),
+        ssl_context_(NULL),
+        peer_certs_(NULL),
+        string_start_(NULL),
+        string_length_(NULL),
+        handshake_complete_(NULL),
+        bad_certificate_callback_(NULL),
+        in_handshake_(false),
+        connected_(false),
+        bad_cert_(false),
+        is_server_(false),
+        hostname_(NULL) {
+  }
+
+  ~SSLFilter();
+
+  // Callback called by the IOService.
+  static CObject* ProcessFilterRequest(const CObjectArray& request);
+
+  Dart_Handle Init(Dart_Handle dart_this);
+  void Connect(Dart_Handle dart_this,
+               const char* hostname,
+               SSLCertContext* context,
+               bool is_server,
+               bool request_client_certificate,
+               bool require_client_certificate);
+  void Destroy();
+  OSStatus CheckHandshake();
+  void Renegotiate(bool use_session_cache,
+                   bool request_client_certificate,
+                   bool require_client_certificate);
+  void RegisterHandshakeCompleteCallback(Dart_Handle handshake_complete);
+  void RegisterBadCertificateCallback(Dart_Handle callback);
+  Dart_Handle PeerCertificate();
+
+ private:
+  static OSStatus SSLReadCallback(SSLConnectionRef connection,
+                                  void* data,
+                                  size_t* data_length);
+  static OSStatus SSLWriteCallback(SSLConnectionRef connection,
+                                   const void* data,
+                                   size_t* data_length);
+
+  static bool isBufferEncrypted(intptr_t i) {
+    return static_cast<BufferIndex>(i) >= kFirstEncrypted;
+  }
+  Dart_Handle InitializeBuffers(Dart_Handle dart_this);
+
+  intptr_t GetBufferStart(intptr_t idx) const;
+  intptr_t GetBufferEnd(intptr_t idx) const;
+  void SetBufferStart(intptr_t idx, intptr_t value);
+  void SetBufferEnd(intptr_t idx, intptr_t value);
+
+  OSStatus ProcessAllBuffers(intptr_t starts[kNumBuffers],
+                             intptr_t ends[kNumBuffers],
+                             bool in_handshake);
+  OSStatus ProcessReadPlaintextBuffer(intptr_t start,
+                                      intptr_t end,
+                                      intptr_t* bytes_processed);
+  OSStatus ProcessWritePlaintextBuffer(intptr_t start,
+                                       intptr_t end,
+                                       intptr_t* bytes_processed);
+
+  // These calls can block on IO, and should only be invoked from
+  // from ProcessAllBuffers from ProcessFilterRequest.
+  OSStatus EvaluatePeerTrust();
+  OSStatus Handshake();
+  Dart_Handle InvokeBadCertCallback(SecCertificateRef peer_cert);
+
+  RetainedPointer<SSLCertContext> cert_context_;
+  SSLContextRef ssl_context_;
+  CFArrayRef peer_certs_;
+
+  // starts and ends filled in at the start of ProcessAllBuffers.
+  // If these are NULL, then try to get the pointers out of
+  // dart_buffer_objects_.
+  uint8_t* buffers_[kNumBuffers];
+  intptr_t* buffer_starts_[kNumBuffers];
+  intptr_t* buffer_ends_[kNumBuffers];
+  intptr_t buffer_size_;
+  intptr_t encrypted_buffer_size_;
+  Dart_PersistentHandle string_start_;
+  Dart_PersistentHandle string_length_;
+  Dart_PersistentHandle dart_buffer_objects_[kNumBuffers];
+  Dart_PersistentHandle handshake_complete_;
+  Dart_PersistentHandle bad_certificate_callback_;
+  bool in_handshake_;
+  bool connected_;
+  bool bad_cert_;
+  bool is_server_;
+  char* hostname_;
+
+  DISALLOW_COPY_AND_ASSIGN(SSLFilter);
+};
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // BIN_SECURE_SOCKET_IOS_H_
diff --git a/runtime/bin/secure_socket_macos.cc b/runtime/bin/secure_socket_macos.cc
index 84b10c0..6b564df 100644
--- a/runtime/bin/secure_socket_macos.cc
+++ b/runtime/bin/secure_socket_macos.cc
@@ -66,134 +66,6 @@
 static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 1000;
 static const intptr_t PEM_BUFSIZE = 1024;
 
-// SSLCertContext wraps the certificates needed for a SecureTransport
-// connection. Fields are protected by the mutex_ field, and may only be set
-// once. This is to allow access by both the Dart thread and the IOService
-// thread. Setters return false if the field was already set.
-class SSLCertContext {
- public:
-  SSLCertContext() :
-      mutex_(new Mutex()),
-      private_key_(NULL),
-      keychain_(NULL),
-      cert_chain_(NULL),
-      trusted_certs_(NULL),
-      cert_authorities_(NULL),
-      trust_builtin_(false) {}
-
-  ~SSLCertContext() {
-    if (private_key_ != NULL) {
-      CFRelease(private_key_);
-    }
-    if (keychain_ != NULL) {
-      SecKeychainDelete(keychain_);
-      CFRelease(keychain_);
-    }
-    if (cert_chain_ != NULL) {
-      CFRelease(cert_chain_);
-    }
-    if (trusted_certs_ != NULL) {
-      CFRelease(trusted_certs_);
-    }
-    if (cert_authorities_ != NULL) {
-      CFRelease(cert_authorities_);
-    }
-    delete mutex_;
-  }
-
-  SecKeyRef private_key() {
-    MutexLocker m(mutex_);
-    return private_key_;
-  }
-  bool set_private_key(SecKeyRef private_key) {
-    MutexLocker m(mutex_);
-    if (private_key_ != NULL) {
-      return false;
-    }
-    private_key_ = private_key;
-    return true;
-  }
-
-  SecKeychainRef keychain() {
-    MutexLocker m(mutex_);
-    return keychain_;
-  }
-  bool set_keychain(SecKeychainRef keychain) {
-    MutexLocker m(mutex_);
-    if (keychain_ != NULL) {
-      return false;
-    }
-    keychain_ = keychain;
-    return true;
-  }
-
-  CFArrayRef cert_chain() {
-    MutexLocker m(mutex_);
-    return cert_chain_;
-  }
-  bool set_cert_chain(CFArrayRef cert_chain) {
-    MutexLocker m(mutex_);
-    if (cert_chain_ != NULL) {
-      return false;
-    }
-    cert_chain_ = cert_chain;
-    return true;
-  }
-
-  CFArrayRef trusted_certs() {
-    MutexLocker m(mutex_);
-    return trusted_certs_;
-  }
-  bool set_trusted_certs(CFArrayRef trusted_certs) {
-    MutexLocker m(mutex_);
-    if (trusted_certs_ != NULL) {
-      return false;
-    }
-    trusted_certs_ = trusted_certs;
-    return true;
-  }
-
-  CFArrayRef cert_authorities() {
-    MutexLocker m(mutex_);
-    return cert_authorities_;
-  }
-  bool set_cert_authorities(CFArrayRef cert_authorities) {
-    MutexLocker m(mutex_);
-    if (cert_authorities_ != NULL) {
-      return false;
-    }
-    cert_authorities_ = cert_authorities;
-    return true;
-  }
-
-  bool trust_builtin() {
-    MutexLocker m(mutex_);
-    return trust_builtin_;
-  }
-  void set_trust_builtin(bool trust_builtin) {
-    MutexLocker m(mutex_);
-    trust_builtin_ = trust_builtin;
-  }
-
- private:
-  // The context is accessed both by Dart code and the IOService. This mutex
-  // protects all fields.
-  Mutex* mutex_;
-
-  SecKeyRef private_key_;
-  SecKeychainRef keychain_;
-
-  // CFArrays of SecCertificateRef.
-  CFArrayRef cert_chain_;
-  CFArrayRef trusted_certs_;
-  CFArrayRef cert_authorities_;
-
-  bool trust_builtin_;
-
-  DISALLOW_COPY_AND_ASSIGN(SSLCertContext);
-};
-
-
 static char* CFStringRefToCString(CFStringRef cfstring) {
   CFIndex len = CFStringGetLength(cfstring);
   CFIndex max_len =
@@ -257,7 +129,7 @@
                          Dart_WeakPersistentHandle handle,
                          void* context_pointer) {
   SSLFilter* filter = reinterpret_cast<SSLFilter*>(context_pointer);
-  delete filter;
+  filter->Release();
 }
 
 
@@ -296,7 +168,7 @@
                               Dart_WeakPersistentHandle handle,
                               void* context_pointer) {
   SSLCertContext* context = static_cast<SSLCertContext*>(context_pointer);
-  delete context;
+  context->Release();
 }
 
 
@@ -679,7 +551,7 @@
   SSLFilter* filter = new SSLFilter();  // Deleted in DeleteFilter finalizer.
   Dart_Handle err = SetFilter(args, filter);
   if (Dart_IsError(err)) {
-    delete filter;
+    filter->Release();
     Dart_PropagateError(err);
   }
   err = filter->Init(dart_this);
@@ -791,7 +663,11 @@
 
 
 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) {
-  intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args));
+  SSLFilter* filter = GetFilter(args);
+  // This filter pointer is passed to the IO Service thread. The IO Service
+  // thread must Release() the pointer when it is done with it.
+  filter->Retain();
+  intptr_t filter_pointer = reinterpret_cast<intptr_t>(filter);
   Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer));
 }
 
@@ -801,7 +677,7 @@
   // cert_context deleted in DeleteCertContext finalizer.
   Dart_Handle err = SetSecurityContext(args, cert_context);
   if (Dart_IsError(err)) {
-    delete cert_context;
+    cert_context->Release();
     Dart_PropagateError(err);
   }
 }
@@ -995,7 +871,7 @@
       reinterpret_cast<CFStringRef>(kSecOIDCommonName));
   if (subject_name == NULL) {
     Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "X509.subject failed to find issuer's common name."));
+        "X509.subject failed to find subject's common name."));
   } else {
     Dart_SetReturnValue(args, Dart_NewStringFromCString(subject_name));
   }
@@ -1086,6 +962,8 @@
 CObject* SSLFilter::ProcessFilterRequest(const CObjectArray& request) {
   CObjectIntptr filter_object(request[0]);
   SSLFilter* filter = reinterpret_cast<SSLFilter*>(filter_object.Value());
+  RefCntReleaseScope<SSLFilter> rs(filter);
+
   bool in_handshake = CObjectBool(request[1]).Value();
   intptr_t starts[SSLFilter::kNumBuffers];
   intptr_t ends[SSLFilter::kNumBuffers];
@@ -1514,7 +1392,7 @@
   }
 
   // Add the contexts to our wrapper.
-  cert_context_ = context;
+  cert_context_.set(context);
   ssl_context_ = ssl_context;
   is_server_ = is_server;
 
@@ -1553,8 +1431,9 @@
   }
 
   CFArrayRef trusted_certs = NULL;
-  if (cert_context_->trusted_certs() != NULL) {
-    trusted_certs = CFArrayCreateCopy(NULL, cert_context_->trusted_certs());
+  if (cert_context_.get()->trusted_certs() != NULL) {
+    trusted_certs =
+      CFArrayCreateCopy(NULL, cert_context_.get()->trusted_certs());
   } else {
     trusted_certs = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
   }
@@ -1572,11 +1451,11 @@
 
   if (SSL_LOG_STATUS) {
     Log::Print("Handshake %s built in root certs\n",
-        cert_context_->trust_builtin() ? "trusting" : "not trusting");
+        cert_context_.get()->trust_builtin() ? "trusting" : "not trusting");
   }
 
   status = SecTrustSetAnchorCertificatesOnly(
-      peer_trust, !cert_context_->trust_builtin());
+      peer_trust, !cert_context_.get()->trust_builtin());
   if (status != noErr) {
     CFRelease(trusted_certs);
     CFRelease(peer_trust);
@@ -1619,7 +1498,7 @@
 
 
 OSStatus SSLFilter::Handshake() {
-  ASSERT(cert_context_ != NULL);
+  ASSERT(cert_context_.get() != NULL);
   ASSERT(ssl_context_ != NULL);
   // Try and push handshake along.
   if (SSL_LOG_STATUS) {
@@ -1732,8 +1611,6 @@
 
 
 SSLFilter::~SSLFilter() {
-  // cert_context_ deleted by finalizer. Don't delete here.
-  cert_context_ = NULL;
   if (ssl_context_ != NULL) {
     CFRelease(ssl_context_);
     ssl_context_ = NULL;
diff --git a/runtime/bin/secure_socket_macos.h b/runtime/bin/secure_socket_macos.h
index c088d8c..b4fe635 100644
--- a/runtime/bin/secure_socket_macos.h
+++ b/runtime/bin/secure_socket_macos.h
@@ -20,6 +20,8 @@
 
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
+#include "bin/lockers.h"
+#include "bin/reference_counting.h"
 #include "bin/socket.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
@@ -27,15 +29,144 @@
 namespace dart {
 namespace bin {
 
-// Forward declaration of SSLContext.
-class SSLCertContext;
+// SSLCertContext wraps the certificates needed for a SecureTransport
+// connection. Fields are protected by the mutex_ field, and may only be set
+// once. This is to allow access by both the Dart thread and the IOService
+// thread. Setters return false if the field was already set.
+class SSLCertContext : public ReferenceCounted<SSLCertContext> {
+ public:
+  SSLCertContext() :
+      ReferenceCounted(),
+      mutex_(new Mutex()),
+      private_key_(NULL),
+      keychain_(NULL),
+      cert_chain_(NULL),
+      trusted_certs_(NULL),
+      cert_authorities_(NULL),
+      trust_builtin_(false) {
+  }
+
+  ~SSLCertContext() {
+    {
+      MutexLocker m(mutex_);
+      if (private_key_ != NULL) {
+        CFRelease(private_key_);
+      }
+      if (keychain_ != NULL) {
+        SecKeychainDelete(keychain_);
+        CFRelease(keychain_);
+      }
+      if (cert_chain_ != NULL) {
+        CFRelease(cert_chain_);
+      }
+      if (trusted_certs_ != NULL) {
+        CFRelease(trusted_certs_);
+      }
+      if (cert_authorities_ != NULL) {
+        CFRelease(cert_authorities_);
+      }
+    }
+    delete mutex_;
+  }
+
+  SecKeyRef private_key() {
+    MutexLocker m(mutex_);
+    return private_key_;
+  }
+  bool set_private_key(SecKeyRef private_key) {
+    MutexLocker m(mutex_);
+    if (private_key_ != NULL) {
+      return false;
+    }
+    private_key_ = private_key;
+    return true;
+  }
+
+  SecKeychainRef keychain() {
+    MutexLocker m(mutex_);
+    return keychain_;
+  }
+  bool set_keychain(SecKeychainRef keychain) {
+    MutexLocker m(mutex_);
+    if (keychain_ != NULL) {
+      return false;
+    }
+    keychain_ = keychain;
+    return true;
+  }
+
+  CFArrayRef cert_chain() {
+    MutexLocker m(mutex_);
+    return cert_chain_;
+  }
+  bool set_cert_chain(CFArrayRef cert_chain) {
+    MutexLocker m(mutex_);
+    if (cert_chain_ != NULL) {
+      return false;
+    }
+    cert_chain_ = cert_chain;
+    return true;
+  }
+
+  CFArrayRef trusted_certs() {
+    MutexLocker m(mutex_);
+    return trusted_certs_;
+  }
+  bool set_trusted_certs(CFArrayRef trusted_certs) {
+    MutexLocker m(mutex_);
+    if (trusted_certs_ != NULL) {
+      return false;
+    }
+    trusted_certs_ = trusted_certs;
+    return true;
+  }
+
+  CFArrayRef cert_authorities() {
+    MutexLocker m(mutex_);
+    return cert_authorities_;
+  }
+  bool set_cert_authorities(CFArrayRef cert_authorities) {
+    MutexLocker m(mutex_);
+    if (cert_authorities_ != NULL) {
+      return false;
+    }
+    cert_authorities_ = cert_authorities;
+    return true;
+  }
+
+  bool trust_builtin() {
+    MutexLocker m(mutex_);
+    return trust_builtin_;
+  }
+  void set_trust_builtin(bool trust_builtin) {
+    MutexLocker m(mutex_);
+    trust_builtin_ = trust_builtin;
+  }
+
+ private:
+  // The context is accessed both by Dart code and the IOService. This mutex
+  // protects all fields.
+  Mutex* mutex_;
+
+  SecKeyRef private_key_;
+  SecKeychainRef keychain_;
+
+  // CFArrays of SecCertificateRef.
+  CFArrayRef cert_chain_;
+  CFArrayRef trusted_certs_;
+  CFArrayRef cert_authorities_;
+
+  bool trust_builtin_;
+
+  DISALLOW_COPY_AND_ASSIGN(SSLCertContext);
+};
 
 // SSLFilter encapsulates the SecureTransport code in a filter that communicates
 // with the containing _SecureFilterImpl Dart object through four shared
 // ExternalByteArray buffers, for reading and writing plaintext, and
 // reading and writing encrypted text.  The filter handles handshaking
 // and certificate verification.
-class SSLFilter {
+class SSLFilter : public ReferenceCounted<SSLFilter> {
  public:
   // These enums must agree with those in sdk/lib/io/secure_socket.dart.
   enum BufferIndex {
@@ -48,7 +179,8 @@
   };
 
   SSLFilter()
-      : cert_context_(NULL),
+      : ReferenceCounted(),
+        cert_context_(NULL),
         ssl_context_(NULL),
         peer_certs_(NULL),
         string_start_(NULL),
@@ -117,7 +249,7 @@
   OSStatus Handshake();
   Dart_Handle InvokeBadCertCallback(SecCertificateRef peer_cert);
 
-  SSLCertContext* cert_context_;
+  RetainedPointer<SSLCertContext> cert_context_;
   SSLContextRef ssl_context_;
   CFArrayRef peer_certs_;
 
@@ -143,64 +275,6 @@
   DISALLOW_COPY_AND_ASSIGN(SSLFilter);
 };
 
-// Where the argument to the constructor is the handle for an object
-// implementing List<int>, this class creates a scope in which the memory
-// backing the list can be accessed.
-//
-// Do not make Dart_ API calls while in a ScopedMemBuffer.
-// Do not call Dart_PropagateError while in a ScopedMemBuffer.
-class ScopedMemBuffer {
- public:
-  explicit ScopedMemBuffer(Dart_Handle object) {
-    if (!Dart_IsTypedData(object) && !Dart_IsList(object)) {
-      Dart_ThrowException(DartUtils::NewDartArgumentError(
-          "Argument is not a List<int>"));
-    }
-
-    uint8_t* bytes = NULL;
-    intptr_t bytes_len = 0;
-    bool is_typed_data = false;
-    if (Dart_IsTypedData(object)) {
-      is_typed_data = true;
-      Dart_TypedData_Type typ;
-      ThrowIfError(Dart_TypedDataAcquireData(
-          object,
-          &typ,
-          reinterpret_cast<void**>(&bytes),
-          &bytes_len));
-    } else {
-      ASSERT(Dart_IsList(object));
-      ThrowIfError(Dart_ListLength(object, &bytes_len));
-      bytes = Dart_ScopeAllocate(bytes_len);
-      ASSERT(bytes != NULL);
-      ThrowIfError(Dart_ListGetAsBytes(object, 0, bytes, bytes_len));
-    }
-
-    object_ = object;
-    bytes_ = bytes;
-    bytes_len_ = bytes_len;
-    is_typed_data_ = is_typed_data;
-  }
-
-  ~ScopedMemBuffer() {
-    if (is_typed_data_) {
-      ThrowIfError(Dart_TypedDataReleaseData(object_));
-    }
-  }
-
-  uint8_t* get() const { return bytes_; }
-  intptr_t length() const { return bytes_len_; }
-
- private:
-  Dart_Handle object_;
-  uint8_t* bytes_;
-  intptr_t bytes_len_;
-  bool is_typed_data_;
-
-  DISALLOW_ALLOCATION();
-  DISALLOW_COPY_AND_ASSIGN(ScopedMemBuffer);
-};
-
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc
index fb9704b..7b6f95a 100644
--- a/runtime/bin/socket.cc
+++ b/runtime/bin/socket.cc
@@ -194,6 +194,11 @@
 }
 
 
+void FUNCTION_NAME(NetworkInterface_ListSupported)(Dart_NativeArguments args) {
+  Dart_SetReturnValue(args, Dart_NewBoolean(Socket::ListInterfacesSupported()));
+}
+
+
 void FUNCTION_NAME(Socket_CreateConnect)(Dart_NativeArguments args) {
   RawAddr addr;
   SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
diff --git a/runtime/bin/socket.h b/runtime/bin/socket.h
index 2cf940c..bd8ed4b 100644
--- a/runtime/bin/socket.h
+++ b/runtime/bin/socket.h
@@ -315,6 +315,9 @@
   static bool ParseAddress(int type, const char* address, RawAddr* addr);
   static bool FormatNumericAddress(const RawAddr& addr, char* address, int len);
 
+  // Whether ListInterfaces is supported.
+  static bool ListInterfacesSupported();
+
   // List interfaces. Returns a AddressList of InterfaceSocketAddress's.
   static AddressList<InterfaceSocketAddress>* ListInterfaces(
       int type,
diff --git a/runtime/bin/socket_android.cc b/runtime/bin/socket_android.cc
index fd96a9a..b3e3fc4 100644
--- a/runtime/bin/socket_android.cc
+++ b/runtime/bin/socket_android.cc
@@ -331,11 +331,21 @@
 }
 
 
+bool Socket::ListInterfacesSupported() {
+  return false;
+}
+
+
 AddressList<InterfaceSocketAddress>* Socket::ListInterfaces(
     int type,
     OSError** os_error) {
   // The ifaddrs.h header is not provided on Android.  An Android
   // implementation would have to use IOCTL or netlink.
+  ASSERT(*os_error == NULL);
+  *os_error = new OSError(-1,
+                          "Listing interfaces is not supported "
+                          "on this platform",
+                          OSError::kSystem);
   return NULL;
 }
 
diff --git a/runtime/bin/socket_linux.cc b/runtime/bin/socket_linux.cc
index 1befb69..6393567 100644
--- a/runtime/bin/socket_linux.cc
+++ b/runtime/bin/socket_linux.cc
@@ -338,6 +338,11 @@
 }
 
 
+bool Socket::ListInterfacesSupported() {
+  return true;
+}
+
+
 AddressList<InterfaceSocketAddress>* Socket::ListInterfaces(
     int type,
     OSError** os_error) {
diff --git a/runtime/bin/socket_macos.cc b/runtime/bin/socket_macos.cc
index 624da8e..708cd3c 100644
--- a/runtime/bin/socket_macos.cc
+++ b/runtime/bin/socket_macos.cc
@@ -336,6 +336,11 @@
 }
 
 
+bool Socket::ListInterfacesSupported() {
+  return true;
+}
+
+
 AddressList<InterfaceSocketAddress>* Socket::ListInterfaces(
     int type,
     OSError** os_error) {
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index 1ec51b7..8025ab4 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -49,6 +49,10 @@
 }
 
 patch class NetworkInterface {
+  /* patch */ static bool get listSupported {
+    return _listSupported();
+  }
+
   /* patch */ static Future<List<NetworkInterface>> list({
       bool includeLoopback: false,
       bool includeLinkLocal: false,
@@ -57,6 +61,8 @@
                                         includeLinkLocal: includeLinkLocal,
                                         type: type);
   }
+
+  static bool _listSupported() native "NetworkInterface_ListSupported";
 }
 
 class _InternetAddress implements InternetAddress {
diff --git a/runtime/bin/socket_unsupported.cc b/runtime/bin/socket_unsupported.cc
index 933df53..0ea27f1 100644
--- a/runtime/bin/socket_unsupported.cc
+++ b/runtime/bin/socket_unsupported.cc
@@ -17,6 +17,12 @@
 }
 
 
+void FUNCTION_NAME(NetworkInterface_ListSupported)(Dart_NativeArguments args) {
+  Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Sockets unsupported on this platform"));
+}
+
+
 void FUNCTION_NAME(Socket_CreateConnect)(Dart_NativeArguments args) {
   Dart_ThrowException(DartUtils::NewDartArgumentError(
       "Sockets unsupported on this platform"));
diff --git a/runtime/bin/socket_win.cc b/runtime/bin/socket_win.cc
index 4534c8c..e3d366d 100644
--- a/runtime/bin/socket_win.cc
+++ b/runtime/bin/socket_win.cc
@@ -411,6 +411,11 @@
 }
 
 
+bool Socket::ListInterfacesSupported() {
+  return true;
+}
+
+
 AddressList<InterfaceSocketAddress>* Socket::ListInterfaces(
     int type,
     OSError** os_error) {
diff --git a/runtime/dart-runtime.gyp b/runtime/dart-runtime.gyp
index f976190..dfe7307 100644
--- a/runtime/dart-runtime.gyp
+++ b/runtime/dart-runtime.gyp
@@ -17,8 +17,6 @@
 
     'libdart_deps': ['libdart_lib_nosnapshot', 'libdart_lib',
                      'libdart_vm_nosnapshot', 'libdart_vm',
-                     'libdart_vm_noopt',
-                     'libdart_vm_precompiled_runtime',
                      'libdouble_conversion',],
   },
   'targets': [
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index a67f9e1..5835660 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -2957,13 +2957,24 @@
     bool reset_fields);
 
 
-DART_EXPORT Dart_Handle Dart_CreatePrecompiledSnapshot(
+DART_EXPORT Dart_Handle Dart_CreatePrecompiledSnapshotAssembly(
     uint8_t** vm_isolate_snapshot_buffer,
     intptr_t* vm_isolate_snapshot_size,
     uint8_t** isolate_snapshot_buffer,
     intptr_t* isolate_snapshot_size,
-    uint8_t** instructions_snapshot_buffer,
-    intptr_t* instructions_snapshot_size);
+    uint8_t** instructions_assembly_buffer,
+    intptr_t* instructions_assembly_size);
+
+
+DART_EXPORT Dart_Handle Dart_CreatePrecompiledSnapshotBlob(
+    uint8_t** vm_isolate_snapshot_buffer,
+    intptr_t* vm_isolate_snapshot_size,
+    uint8_t** isolate_snapshot_buffer,
+    intptr_t* isolate_snapshot_size,
+    uint8_t** instructions_blob_buffer,
+    intptr_t* instructions_blob_size,
+    uint8_t** rodata_blob_buffer,
+    intptr_t* rodata_blob_size);
 
 
 DART_EXPORT bool Dart_IsRunningPrecompiledCode();
diff --git a/runtime/lib/bigint.dart b/runtime/lib/bigint.dart
index ae941b7..bc9b8f4 100644
--- a/runtime/lib/bigint.dart
+++ b/runtime/lib/bigint.dart
@@ -1336,16 +1336,6 @@
     return str;
   }
 
-  _leftShiftWithMask32(int count, int mask) {
-    if (_used == 0) return 0;
-    if (count is! _Smi) {
-      _shlFromInt(count);  // Throws out of memory exception.
-    }
-    assert(_DIGIT_BITS == 32);  // Otherwise this code needs to be revised.
-    if (count > 31) return 0;
-    return (_digits[0] << count) & mask;
-  }
-
   int _bitAndFromInteger(int other) {
     return other._toBigint()._and(this)._toValidInt();
   }
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index e75ecab..a1aa3bd 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -244,7 +244,7 @@
       if (result.IsSmi()) {
         return result.raw();
       }
-      return result.CheckAndCanonicalize(NULL);
+      return result.CheckAndCanonicalize(thread, NULL);
     }
   }
   return default_value.raw();
@@ -290,28 +290,6 @@
 }
 
 
-DEFINE_NATIVE_ENTRY(Integer_leftShiftWithMask32, 3) {
-  const Integer& value = Integer::CheckedHandle(arguments->NativeArgAt(0));
-  GET_NON_NULL_NATIVE_ARGUMENT(Integer, shift_count, arguments->NativeArgAt(1));
-  GET_NON_NULL_NATIVE_ARGUMENT(Integer, mask, arguments->NativeArgAt(2));
-  ASSERT(CheckInteger(value));
-  ASSERT(CheckInteger(shift_count));
-  ASSERT(CheckInteger(mask));
-  if (!shift_count.IsSmi()) {
-    // Shift count is too large..
-    const Instance& exception =
-        Instance::Handle(isolate->object_store()->out_of_memory());
-    Exceptions::Throw(thread, exception);
-  }
-  const Smi& smi_shift_count = Smi::Cast(shift_count);
-  const Integer& shift_result = Integer::Handle(
-      ShiftOperationHelper(Token::kSHL, value, smi_shift_count));
-  const Integer& result =
-      Integer::Handle(shift_result.BitOp(Token::kBIT_AND, mask));
-  return result.AsValidInteger();
-}
-
-
 DEFINE_NATIVE_ENTRY(Smi_shrFromInt, 2) {
   const Smi& amount = Smi::CheckedHandle(arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1));
diff --git a/runtime/lib/integers.dart b/runtime/lib/integers.dart
index a28491c..a103f23 100644
--- a/runtime/lib/integers.dart
+++ b/runtime/lib/integers.dart
@@ -263,8 +263,6 @@
     return string;
   }
 
-  _leftShiftWithMask32(count, mask)  native "Integer_leftShiftWithMask32";
-
   // Returns pow(this, e) % m.
   int modPow(int e, int m) {
     if (e is! int) {
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 40efc28..d10e066 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -2068,18 +2068,7 @@
   ASSERT(cls.IsTypedefClass());
   const Function& sig_func = Function::Handle(cls.signature_function());
   Type& referent_type = Type::Handle(sig_func.SignatureType());
-  // If the scope class of the function type is not generic, replace it with
-  // Closure class (Function::SignatureType() keeps it).
   ASSERT(cls.raw() == referent_type.type_class());
-  if (!cls.IsGeneric()) {
-    referent_type = Type::New(
-        Class::Handle(Isolate::Current()->object_store()->closure_class()),
-        TypeArguments::Handle(referent_type.arguments()),
-        referent_type.token_pos());
-    referent_type.set_signature(sig_func);
-    referent_type ^= ClassFinalizer::FinalizeType(
-        cls, referent_type, ClassFinalizer::kCanonicalize);
-  }
   referent_type ^= InstantiateType(referent_type, type);
   return CreateFunctionTypeMirror(referent_type);
 }
diff --git a/runtime/lib/object_patch.dart b/runtime/lib/object_patch.dart
index b61b6a6..7c4f5f5 100644
--- a/runtime/lib/object_patch.dart
+++ b/runtime/lib/object_patch.dart
@@ -73,8 +73,4 @@
     });
     return result;
   }
-
-  _leftShiftWithMask32(count, mask)  {
-    return (this << count) & mask;
-  }
 }
diff --git a/runtime/lib/string_buffer_patch.dart b/runtime/lib/string_buffer_patch.dart
index d087550..401d258 100644
--- a/runtime/lib/string_buffer_patch.dart
+++ b/runtime/lib/string_buffer_patch.dart
@@ -148,7 +148,8 @@
     _partsCodeUnitsSinceCompaction += length;
 
     if (_parts == null) {
-      _parts = [ str ];
+      // Empirically this is a good capacity to minimize total bytes allocated.
+      _parts = new _GrowableList.withCapacity(10)..add(str);
     } else {
       _parts.add(str);
       int partsSinceCompaction = _parts.length - _partsCompactionIndex;
diff --git a/runtime/observatory/lib/src/elements/code_view.dart b/runtime/observatory/lib/src/elements/code_view.dart
index d8fa1c7..037a9aa 100644
--- a/runtime/observatory/lib/src/elements/code_view.dart
+++ b/runtime/observatory/lib/src/elements/code_view.dart
@@ -28,6 +28,8 @@
   DisassemblyTable disassemblyTable;
   InlineTable inlineTable;
 
+  static const kDisassemblyColumnIndex = 3;
+
   CodeViewElement.created() : super.created() {
     // Create table models.
     var columns = [
@@ -212,7 +214,20 @@
         element.ref = content;
         cell.children = [element];
       } else if (content != null) {
-        cell.text = content.toString();
+        String text = '$content';
+        if (i == kDisassemblyColumnIndex) {
+          // Disassembly might be a comment. Reduce indentation, change styling,
+          // widen to span next column (which should be empty).
+          if (text.startsWith('        ;;')) {
+            cell.attributes['colspan'] = '2';
+            cell.classes.add('code-comment');
+            text = text.substring(6);
+          } else {
+            cell.attributes['colspan'] = '1';
+            cell.classes.remove('code-comment');
+          }
+        }
+        cell.text = text;
       }
     }
   }
diff --git a/runtime/observatory/lib/src/elements/code_view.html b/runtime/observatory/lib/src/elements/code_view.html
index ba4cac0..95f71e2 100644
--- a/runtime/observatory/lib/src/elements/code_view.html
+++ b/runtime/observatory/lib/src/elements/code_view.html
@@ -34,6 +34,7 @@
         overflow: visible;
         white-space: pre;
         padding-right: 1em;
+        width: 1px;
       }
 
       th:nth-of-type(5), td:nth-of-type(5) {
@@ -45,6 +46,11 @@
         background-color: #F4C7C3;
       }
 
+      .code-comment {
+        color: grey;
+        font-style: italic;
+      }
+
     </style>
     <nav-bar>
       <top-nav-menu></top-nav-menu>
diff --git a/runtime/observatory/tests/service/get_isolate_after_async_error_test.dart b/runtime/observatory/tests/service/get_isolate_after_async_error_test.dart
new file mode 100644
index 0000000..a0c531d
--- /dev/null
+++ b/runtime/observatory/tests/service/get_isolate_after_async_error_test.dart
@@ -0,0 +1,28 @@
+// 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 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+doThrow() async {
+  throw "oh no"; // Line 13.
+}
+
+var tests = [
+  hasStoppedAtExit,
+
+  (Isolate isolate) async {
+    await isolate.reload();
+    expect(isolate.error, isNotNull);
+    expect(isolate.error.message.contains('oh no'), isTrue);
+  }
+];
+
+main(args) async => runIsolateTests(args,
+                                    tests,
+                                    pause_on_exit: true,
+                                    testeeConcurrent: doThrow);
\ No newline at end of file
diff --git a/runtime/observatory/tests/service/get_isolate_after_language_error_test.dart b/runtime/observatory/tests/service/get_isolate_after_language_error_test.dart
new file mode 100644
index 0000000..dc763a0
--- /dev/null
+++ b/runtime/observatory/tests/service/get_isolate_after_language_error_test.dart
@@ -0,0 +1,32 @@
+// 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:async';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+var x;
+
+doThrow() {
+  if (x) while {
+  };
+}
+
+var tests = [
+  hasStoppedAtExit,
+
+  (Isolate isolate) async {
+    await isolate.reload();
+    expect(isolate.error, isNotNull);
+    expect(isolate.error.message.contains("'(' expected"), isTrue);
+  }
+];
+
+main(args) => runIsolateTestsSynchronous(args,
+                                         tests,
+                                         pause_on_exit: true,
+                                         testeeConcurrent: doThrow);
\ No newline at end of file
diff --git a/runtime/observatory/tests/service/get_isolate_after_sync_error_test.dart b/runtime/observatory/tests/service/get_isolate_after_sync_error_test.dart
new file mode 100644
index 0000000..bf2684a
--- /dev/null
+++ b/runtime/observatory/tests/service/get_isolate_after_sync_error_test.dart
@@ -0,0 +1,28 @@
+// 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 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+doThrow() {
+  throw "oh no"; // Line 13.
+}
+
+var tests = [
+  hasStoppedAtExit,
+
+  (Isolate isolate) async {
+    await isolate.reload();
+    expect(isolate.error, isNotNull);
+    expect(isolate.error.message.contains('oh no'), isTrue);
+  }
+];
+
+main(args) => runIsolateTestsSynchronous(args,
+                                         tests,
+                                         pause_on_exit: true,
+                                         testeeConcurrent: doThrow);
\ No newline at end of file
diff --git a/runtime/observatory/tests/service/instance_field_order_rpc_test.dart b/runtime/observatory/tests/service/instance_field_order_rpc_test.dart
new file mode 100644
index 0000000..0323f8c
--- /dev/null
+++ b/runtime/observatory/tests/service/instance_field_order_rpc_test.dart
@@ -0,0 +1,54 @@
+// 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
+
+library get_object_rpc_test;
+
+import 'dart:typed_data';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+class Super {
+  var z = 1;
+  var y = 2;
+}
+class Sub extends Super {
+  var y = 3;
+  var x = 4;
+}
+
+eval(Isolate isolate, String expression) async {
+  Map params = {
+    'targetId': isolate.rootLibrary.id,
+    'expression': expression,
+  };
+  return await isolate.invokeRpcNoUpgrade('evaluate', params);
+}
+
+var tests = [
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await eval(isolate, 'new Sub()');
+    var params = {
+      'objectId': evalResult['id'],
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    print(result);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('PlainInstance'));
+    expect(result['class']['name'], equals('Sub'));
+    expect(result['size'], isPositive);
+    expect(result['fields'][0]['decl']['name'], 'z');
+    expect(result['fields'][0]['value']['valueAsString'], '1');
+    expect(result['fields'][1]['decl']['name'], 'y');
+    expect(result['fields'][1]['value']['valueAsString'], '2');
+    expect(result['fields'][2]['decl']['name'], 'y');
+    expect(result['fields'][2]['value']['valueAsString'], '3');
+    expect(result['fields'][3]['decl']['name'], 'x');
+    expect(result['fields'][3]['value']['valueAsString'], '4');
+  },
+];
+
+main(args) async => runIsolateTests(args, tests);
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index 8003189..bb742ac 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -5,6 +5,7 @@
 [ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) ]
 evaluate_activation_test/instance: RuntimeError # http://dartbug.com/20047
 evaluate_activation_test/scope: RuntimeError # http://dartbug.com/20047
+isolate_lifecycle_test: Pass, RuntimeError # Issue 24174
 
 # Disable on simulators.
 [ $arch == simarm || $arch == simmips || $arch == simarm64]
@@ -21,6 +22,7 @@
 address_mapper_test: Pass # https://github.com/dart-lang/observe/issues/85
 command_test: Pass # https://github.com/dart-lang/observe/issues/85
 read_stream_test: Pass # https://github.com/dart-lang/observe/issues/85
+get_isolate_after_language_error_test: SkipByDesign
 
 [ $arch == arm ]
 process_service_test: Pass, Fail # Issue 24344
@@ -36,8 +38,13 @@
 *: SkipByDesign
 
 # Service protocol is not supported when running a full application snapshot.
-[ ($runtime == dart_product) ]
+[ $runtime == dart_product ]
 *: SkipByDesign
 
 [ $compiler == dart2analyzer ]
 evaluate_activation_in_method_class_test: CompileTimeError # Issue 24478
+
+[ $arch == simdbc || $arch == simdbc64 ]
+# TODO(vegorov) re-enable when debugger, coverage and profiling is completely
+# fixed for SIMDBC.
+*: Skip
diff --git a/runtime/observatory/tests/service/service_test_common.dart b/runtime/observatory/tests/service/service_test_common.dart
index 108316c..4a42290 100644
--- a/runtime/observatory/tests/service/service_test_common.dart
+++ b/runtime/observatory/tests/service/service_test_common.dart
@@ -140,6 +140,10 @@
   return hasPausedFor(isolate, ServiceEvent.kPauseException);
 }
 
+Future<Isolate> hasStoppedAtExit(Isolate isolate) {
+  return hasPausedFor(isolate, ServiceEvent.kPauseExit);
+}
+
 Future<Isolate> hasPausedAtStart(Isolate isolate) {
   return hasPausedFor(isolate, ServiceEvent.kPauseStart);
 }
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 7e11bb3..a0dfdd0 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -2,8 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-#ifndef PLATFORM_GLOBALS_H_
-#define PLATFORM_GLOBALS_H_
+#ifndef RUNTIME_PLATFORM_GLOBALS_H_
+#define RUNTIME_PLATFORM_GLOBALS_H_
 
 // __STDC_FORMAT_MACROS has to be defined before including <inttypes.h> to
 // enable platform independent printf format specifiers.
@@ -136,6 +136,10 @@
 #endif  // defined(PRODUCT)
 
 
+#if defined(DART_PRECOMPILED_RUNTIME) && defined(DART_PRECOMPILER)
+#error DART_PRECOMPILED_RUNTIME and DART_PRECOMPILER are mutually exclusive
+#endif  // defined(DART_PRECOMPILED_RUNTIME) && defined(DART_PRECOMPILER)
+
 namespace dart {
 
 struct simd128_value_t {
@@ -257,6 +261,15 @@
 #error Automatic compiler detection failed.
 #endif
 
+// DART_NOINLINE tells compiler to never inline a particular function.
+#ifdef _MSC_VER
+#define DART_NOINLINE __declspec(noinline)
+#elif __GNUC__
+#define DART_NOINLINE __attribute__((noinline))
+#else
+#error Automatic compiler detection failed.
+#endif
+
 // DART_UNUSED inidicates to the compiler that a variable/typedef is expected
 // to be unused and disables the related warning.
 #ifdef __GNUC__
@@ -282,6 +295,7 @@
 #if !defined(TARGET_ARCH_X64)
 #if !defined(TARGET_ARCH_IA32)
 #if !defined(TARGET_ARCH_ARM64)
+#if !defined(TARGET_ARCH_DBC)
 // No target architecture specified pick the one matching the host architecture.
 #if defined(HOST_ARCH_MIPS)
 #define TARGET_ARCH_MIPS 1
@@ -301,6 +315,7 @@
 #endif
 #endif
 #endif
+#endif
 
 // Verify that host and target architectures match, we cannot
 // have a 64 bit Dart VM generating 32 bit code or vice-versa.
@@ -337,6 +352,9 @@
 #define USING_SIMULATOR 1
 #endif
 
+#elif defined(TARGET_ARCH_DBC)
+#define USING_SIMULATOR 1
+
 #else
 #error Unknown architecture.
 #endif
@@ -660,4 +678,4 @@
 
 }  // namespace dart
 
-#endif  // PLATFORM_GLOBALS_H_
+#endif  // RUNTIME_PLATFORM_GLOBALS_H_
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 62cc6da..8de2b3b 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -33,7 +33,7 @@
 cc/Dart2JSCompilerStats: Skip
 cc/CorelibCompilerStats: Skip
 
-[ $arch == simarm || $arch == simarmv6 || $arch == simarmv5te || $arch == simarm64 || $arch == simmips ]
+[ $arch == simarm || $arch == simarmv6 || $arch == simarmv5te || $arch == simarm64 || $arch == simmips || $arch == simdbc  || $arch == simdbc64 ]
 cc/Service_Profile: Skip
 
 [ $compiler == dart2js ]
@@ -97,3 +97,83 @@
 cc/IsolateSetCheckedMode: Fail,OK  # Expects exact type name.
 cc/LibraryGetClassNames: Fail,OK  # Expects exact type name.
 cc/StackTraceFormat: Fail,OK  # Expects exact type name.
+
+[ $arch == simdbc || $arch == simdbc64 ]
+# TODO(vegorov) Profiler is completely disabled in SIMDBC builds.
+cc/Profiler_AllocationSampleTest: Skip
+cc/Profiler_ArrayAllocation: Skip
+cc/Profiler_BasicSourcePosition: Skip
+cc/Profiler_BasicSourcePositionOptimized: Skip
+cc/Profiler_BinaryOperatorSourcePosition: Skip
+cc/Profiler_BinaryOperatorSourcePositionOptimized: Skip
+cc/Profiler_ChainedSamples: Skip
+cc/Profiler_ClosureAllocation: Skip
+cc/Profiler_CodeTicks: Skip
+cc/Profiler_ContextAllocation: Skip
+cc/Profiler_FunctionInline: Skip
+cc/Profiler_FunctionTicks: Skip
+cc/Profiler_InliningIntervalBoundry: Skip
+cc/Profiler_IntrinsicAllocation: Skip
+cc/Profiler_SampleBufferIterateTest: Skip
+cc/Profiler_SampleBufferWrapTest: Skip
+cc/Profiler_SourcePosition: Skip
+cc/Profiler_SourcePositionOptimized: Skip
+cc/Profiler_StringAllocation: Skip
+cc/Profiler_StringInterpolation: Skip
+cc/Profiler_ToggleRecordAllocation: Skip
+cc/Profiler_TrivialRecordAllocation: Skip
+cc/Profiler_TypedArrayAllocation: Skip
+cc/Profiler_GetSourceReport: Skip
+
+# TODO(vegorov) These tests are crashing because ICData objects can't be found
+cc/SourceReport_CallSites_PolymorphicCall: Skip
+cc/SourceReport_CallSites_SimpleCall: Skip
+cc/SourceReport_Coverage_AllFunctions: Skip
+cc/SourceReport_Coverage_ForceCompile: Skip
+cc/SourceReport_Coverage_NestedFunctions: Skip
+cc/SourceReport_Coverage_SimpleCall: Skip
+cc/SourceReport_MultipleReports: Skip
+cc/Coverage_Empty: Skip
+cc/Coverage_FilterFunction: Skip
+cc/Coverage_MainWithClass: Skip
+
+# TODO(vegorov) DisassembleToJSONStream requires
+# DecodeLoadObjectFromPoolOrThread which is unimplemented.
+cc/Service_Code: Skip
+cc/PrintJSON: Skip
+
+# TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp
+# is switched on by default because they attempt to call regexp functions
+# directly instead of going through JSSyntaxRegExp_ExecuteMatch.
+cc/RegExp_ExternalOneByteString: Skip
+cc/RegExp_ExternalTwoByteString: Skip
+cc/RegExp_OneByteString: Skip
+cc/RegExp_TwoByteString: Skip
+
+# TODO(vegorov) Optimizing compiler is disabled for the SIMDBC
+cc/CompileFunctionOnHelperThread: Skip
+
+# TODO(vegorov) Field guards are disabled for SIMDBC
+cc/GuardFieldConstructor2Test: Skip
+cc/GuardFieldConstructorTest: Skip
+cc/GuardFieldFinalListTest: Skip
+cc/GuardFieldFinalVariableLengthListTest: Skip
+cc/GuardFieldSimpleTest: Skip
+
+# TODO(vegorov) Not all bytecodes have appropriate debug breaks.
+cc/Debug_BreakpointStubPatching: Skip
+cc/Debug_ExprClosureBreakpoint: Skip
+cc/Debug_StackTraceDump1: Skip
+cc/Debug_StepInto: Skip
+
+# TODO(vegorov) These parser tests rely on debugger.
+cc/Parser_AllocateVariables_CapturedVar: Skip
+cc/Parser_AllocateVariables_MiddleChain: Skip
+
+# This test is meaningless for DBC as allocation stubs are not used.
+cc/RegenerateAllocStubs: Skip
+
+# TODO(vegorov) Enable when DBC supports optimizing compiler.
+cc/Debug_InspectStack_Optimized: Skip
+cc/Debug_InspectStackWithClosure_Optimized: Skip
+
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index b19dfc8..b6e64db 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -18,7 +18,7 @@
 
 
 static_library("libdart_platform") {
-  configs += ["..:dart_config"]
+  configs += ["..:dart_config", "..:dart_product_config"]
   public_configs = [":libdart_vm_config"]
 
   platform_headers_gypi =
@@ -43,9 +43,10 @@
   ]
 }
 
-
 static_library("libdart_vm") {
-  configs += ["..:dart_config"]
+  configs += ["..:dart_config",
+              "..:dart_product_config",
+              "..:dart_precompiled_runtime_config"]
   public_configs = [":libdart_vm_config"]
 
   vm_sources_list = exec_script("../../tools/gypi_to_gn.py",
@@ -61,25 +62,29 @@
 }
 
 
-static_library("libdart_vm_precompiled_runtime") {
-  configs += ["..:dart_config_no_precompiler"]
-  public_configs = [":libdart_vm_config"]
-  defines = ["DART_PRECOMPILED_RUNTIME"]
-  vm_sources_list = exec_script("../../tools/gypi_to_gn.py",
-                                [rebase_path("vm_sources.gypi")],
-                                "scope",
-                                ["vm_sources.gypi"])
-
-  set_sources_assignment_filter(["*_test.cc", "*_test.h"])
-  sources = vm_sources_list.sources
-  include_dirs = [
-    "..",
-  ]
-}
-
-
 static_library("libdart_vm_nosnapshot") {
-  configs += ["..:dart_config"]
+  configs += ["..:dart_config",
+              "..:dart_product_config",
+              "..:dart_precompiled_runtime_config"]
+  public_configs = [":libdart_vm_config"]
+  defines = [ "DART_NO_SNAPSHOT" ]
+  vm_sources_list = exec_script("../../tools/gypi_to_gn.py",
+                                [rebase_path("vm_sources.gypi")],
+                                "scope",
+                                ["vm_sources.gypi"])
+
+  set_sources_assignment_filter(["*_test.cc", "*_test.h"])
+  sources = vm_sources_list.sources
+  include_dirs = [
+    "..",
+  ]
+}
+
+
+static_library("libdart_vm_nosnapshot_with_precompiler") {
+  configs += ["..:dart_config",
+              "..:dart_product_config",
+              "..:dart_precompiler_config"]
   public_configs = [":libdart_vm_config"]
   defines = [ "DART_NO_SNAPSHOT" ]
   vm_sources_list = exec_script("../../tools/gypi_to_gn.py",
@@ -185,24 +190,30 @@
   }
 
   static_library("libdart_lib_nosnapshot") {
-    configs += ["..:dart_config"]
+    configs += ["..:dart_config",
+                "..:dart_product_config",
+                "..:dart_precompiled_runtime_config"]
     deps = libdeps
     sources = libsources + ["bootstrap.cc"] + liboutputs
     include_dirs = [
       "..",
     ]
   }
-  static_library("libdart_lib") {
-    configs += ["..:dart_config"]
-    sources = libsources + [ "bootstrap_nocore.cc", ]
+  static_library("libdart_lib_nosnapshot_with_precompiler") {
+    configs += ["..:dart_config",
+                "..:dart_product_config",
+                "..:dart_precompiler_config" ]
+    deps = libdeps
+    sources = libsources + [ "bootstrap.cc"] + liboutputs
     include_dirs = [
       "..",
     ]
   }
-  static_library("libdart_lib_precompiled_runtime") {
-    configs += ["..:dart_config_no_precompiler"]
-    defines = ["DART_PRECOMPILED_RUNTIME"]
-    sources = libsources + [ "bootstrap_nocore.cc", ]
+  static_library("libdart_lib") {
+    configs += ["..:dart_config",
+                "..:dart_product_config",
+                "..:dart_precompiled_runtime_config"]
+    sources = libsources + [ "bootstrap_nocore.cc"]
     include_dirs = [
       "..",
     ]
diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc
index 7d005b1..bc3bf8b 100644
--- a/runtime/vm/aot_optimizer.cc
+++ b/runtime/vm/aot_optimizer.cc
@@ -1904,71 +1904,6 @@
     return TryInlineFloat64x2Method(call, recognized_kind);
   }
 
-  if (recognized_kind == MethodRecognizer::kIntegerLeftShiftWithMask32) {
-    ASSERT(call->ArgumentCount() == 3);
-    ASSERT(ic_data.NumArgsTested() == 2);
-    Definition* value = call->ArgumentAt(0);
-    Definition* count = call->ArgumentAt(1);
-    Definition* int32_mask = call->ArgumentAt(2);
-    if (HasOnlyTwoOf(ic_data, kSmiCid)) {
-      if (ic_data.HasDeoptReason(ICData::kDeoptBinaryMintOp)) {
-        return false;
-      }
-      // We cannot overflow. The input value must be a Smi
-      AddCheckSmi(value, call->deopt_id(), call->env(), call);
-      AddCheckSmi(count, call->deopt_id(), call->env(), call);
-      ASSERT(int32_mask->IsConstant());
-      const Integer& mask_literal = Integer::Cast(
-          int32_mask->AsConstant()->value());
-      const int64_t mask_value = mask_literal.AsInt64Value();
-      ASSERT(mask_value >= 0);
-      if (mask_value > Smi::kMaxValue) {
-        // The result will not be Smi.
-        return false;
-      }
-      BinarySmiOpInstr* left_shift =
-          new(Z) BinarySmiOpInstr(Token::kSHL,
-                                  new(Z) Value(value),
-                                  new(Z) Value(count),
-                                  call->deopt_id());
-      left_shift->mark_truncating();
-      if ((kBitsPerWord == 32) && (mask_value == 0xffffffffLL)) {
-        // No BIT_AND operation needed.
-        ReplaceCall(call, left_shift);
-      } else {
-        InsertBefore(call, left_shift, call->env(), FlowGraph::kValue);
-        BinarySmiOpInstr* bit_and =
-            new(Z) BinarySmiOpInstr(Token::kBIT_AND,
-                                    new(Z) Value(left_shift),
-                                    new(Z) Value(int32_mask),
-                                    call->deopt_id());
-        ReplaceCall(call, bit_and);
-      }
-      return true;
-    }
-
-    if (HasTwoMintOrSmi(ic_data) &&
-        HasOnlyOneSmi(ICData::Handle(Z,
-                                     ic_data.AsUnaryClassChecksForArgNr(1)))) {
-      if (!FlowGraphCompiler::SupportsUnboxedMints() ||
-          ic_data.HasDeoptReason(ICData::kDeoptBinaryMintOp)) {
-        return false;
-      }
-      ShiftMintOpInstr* left_shift =
-          new(Z) ShiftMintOpInstr(Token::kSHL,
-                                  new(Z) Value(value),
-                                  new(Z) Value(count),
-                                  call->deopt_id());
-      InsertBefore(call, left_shift, call->env(), FlowGraph::kValue);
-      BinaryMintOpInstr* bit_and =
-          new(Z) BinaryMintOpInstr(Token::kBIT_AND,
-                                   new(Z) Value(left_shift),
-                                   new(Z) Value(int32_mask),
-                                   call->deopt_id());
-      ReplaceCall(call, bit_and);
-      return true;
-    }
-  }
   return false;
 }
 
diff --git a/runtime/vm/assembler.h b/runtime/vm/assembler.h
index 65820fe..ceaadaa 100644
--- a/runtime/vm/assembler.h
+++ b/runtime/vm/assembler.h
@@ -340,6 +340,8 @@
 #include "vm/assembler_arm64.h"
 #elif defined(TARGET_ARCH_MIPS)
 #include "vm/assembler_mips.h"
+#elif defined(TARGET_ARCH_DBC)
+#include "vm/assembler_dbc.h"
 #else
 #error Unknown architecture.
 #endif
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index 41ba7f5..db3314d 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -1601,11 +1601,7 @@
                  : object_pool_wrapper_.FindObject(object));
     LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, pp, cond);
   } else {
-    ASSERT(FLAG_allow_absolute_addresses);
-    ASSERT(object.IsOld());
-    // Make sure that class CallPattern is able to decode this load immediate.
-    const int32_t object_raw = reinterpret_cast<int32_t>(object.raw());
-    LoadImmediate(rd, object_raw, cond);
+    UNREACHABLE();
   }
 }
 
@@ -3408,38 +3404,23 @@
 
 
 void Assembler::LoadAllocationStatsAddress(Register dest,
-                                           intptr_t cid,
-                                           bool inline_isolate) {
+                                           intptr_t cid) {
   ASSERT(dest != kNoRegister);
   ASSERT(dest != TMP);
   ASSERT(cid > 0);
   const intptr_t class_offset = ClassTable::ClassOffsetFor(cid);
-  if (inline_isolate) {
-    ASSERT(FLAG_allow_absolute_addresses);
-    ClassTable* class_table = Isolate::Current()->class_table();
-    ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
-    if (cid < kNumPredefinedCids) {
-      LoadImmediate(dest, reinterpret_cast<uword>(*table_ptr) + class_offset);
-    } else {
-      LoadImmediate(dest, reinterpret_cast<uword>(table_ptr));
-      ldr(dest, Address(dest, 0));
-      AddImmediate(dest, class_offset);
-    }
-  } else {
-    LoadIsolate(dest);
-    intptr_t table_offset =
-        Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
-    ldr(dest, Address(dest, table_offset));
-    AddImmediate(dest, class_offset);
-  }
+  LoadIsolate(dest);
+  intptr_t table_offset =
+      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  ldr(dest, Address(dest, table_offset));
+  AddImmediate(dest, class_offset);
 }
 
 
 void Assembler::MaybeTraceAllocation(intptr_t cid,
                                      Register temp_reg,
-                                     Label* trace,
-                                     bool inline_isolate) {
-  LoadAllocationStatsAddress(temp_reg, cid, inline_isolate);
+                                     Label* trace) {
+  LoadAllocationStatsAddress(temp_reg, cid);
   const uword state_offset = ClassHeapStats::state_offset();
   ldr(temp_reg, Address(temp_reg, state_offset));
   tst(temp_reg, Operand(ClassHeapStats::TraceAllocationMask()));
@@ -3498,8 +3479,7 @@
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cls.id(), temp_reg, failure,
-                         /* inline_isolate = */ false);
+    MaybeTraceAllocation(cls.id(), temp_reg, failure);
     Heap::Space space = Heap::SpaceForAllocation(cls.id());
     ldr(temp_reg, Address(THR, Thread::heap_offset()));
     ldr(instance_reg, Address(temp_reg, Heap::TopOffset(space)));
@@ -3516,8 +3496,7 @@
     // next object start and store the class in the class field of object.
     str(instance_reg, Address(temp_reg, Heap::TopOffset(space)));
 
-    LoadAllocationStatsAddress(temp_reg, cls.id(),
-                               /* inline_isolate = */ false);
+    LoadAllocationStatsAddress(temp_reg, cls.id());
 
     ASSERT(instance_size >= kHeapObjectTag);
     AddImmediate(instance_reg, -instance_size + kHeapObjectTag);
@@ -3547,7 +3526,7 @@
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cid, temp1, failure, /* inline_isolate = */ false);
+    MaybeTraceAllocation(cid, temp1, failure);
     Heap::Space space = Heap::SpaceForAllocation(cid);
     ldr(temp1, Address(THR, Thread::heap_offset()));
     // Potential new object start.
@@ -3562,7 +3541,7 @@
     cmp(end_address, Operand(temp2));
     b(failure, CS);
 
-    LoadAllocationStatsAddress(temp2, cid, /* inline_isolate = */ false);
+    LoadAllocationStatsAddress(temp2, cid);
 
     // Successfully allocated the object(s), now update top to point to
     // next object start and initialize the object.
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index a85dd43..66e7c13 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -976,8 +976,7 @@
   // allocation stats. These are separate assembler macros so we can
   // avoid a dependent load too nearby the load of the table address.
   void LoadAllocationStatsAddress(Register dest,
-                                  intptr_t cid,
-                                  bool inline_isolate = true);
+                                  intptr_t cid);
   void IncrementAllocationStats(Register stats_addr,
                                 intptr_t cid,
                                 Heap::Space space);
@@ -1004,8 +1003,7 @@
   // which will allocate in the runtime where tracing occurs.
   void MaybeTraceAllocation(intptr_t cid,
                             Register temp_reg,
-                            Label* trace,
-                            bool inline_isolate = true);
+                            Label* trace);
 
   // Inlined allocation of an instance of class 'cls', code has no runtime
   // calls. Jump to 'failure' if the instance cannot be allocated here.
diff --git a/runtime/vm/assembler_arm64.cc b/runtime/vm/assembler_arm64.cc
index 28dc872..eeb831d 100644
--- a/runtime/vm/assembler_arm64.cc
+++ b/runtime/vm/assembler_arm64.cc
@@ -413,8 +413,7 @@
                   : object_pool_wrapper_.FindObject(object));
     LoadWordFromPoolOffset(dst, offset);
   } else {
-    ASSERT(object.IsSmi() || object.InVMHeap());
-    ASSERT(object.IsSmi() || FLAG_allow_absolute_addresses);
+    ASSERT(object.IsSmi());
     LoadDecodableImmediate(dst, reinterpret_cast<int64_t>(object.raw()));
   }
 }
@@ -452,7 +451,7 @@
     LoadObject(TMP, object);
     CompareRegisters(reg, TMP);
   } else {
-    ASSERT(object.IsSmi() || FLAG_allow_absolute_addresses);
+    ASSERT(object.IsSmi());
     CompareImmediate(reg, reinterpret_cast<int64_t>(object.raw()));
   }
 }
@@ -1264,30 +1263,15 @@
 
 
 void Assembler::UpdateAllocationStats(intptr_t cid,
-                                      Heap::Space space,
-                                      bool inline_isolate) {
+                                      Heap::Space space) {
   ASSERT(cid > 0);
   intptr_t counter_offset =
       ClassTable::CounterOffsetFor(cid, space == Heap::kNew);
-  if (inline_isolate) {
-    ASSERT(FLAG_allow_absolute_addresses);
-    ClassTable* class_table = Isolate::Current()->class_table();
-    ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
-    if (cid < kNumPredefinedCids) {
-      LoadImmediate(
-          TMP2, reinterpret_cast<uword>(*table_ptr) + counter_offset);
-    } else {
-      LoadImmediate(TMP2, reinterpret_cast<uword>(table_ptr));
-      ldr(TMP, Address(TMP2));
-      AddImmediate(TMP2, TMP, counter_offset);
-    }
-  } else {
-    LoadIsolate(TMP2);
-    intptr_t table_offset =
-        Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
-    ldr(TMP, Address(TMP2, table_offset));
-    AddImmediate(TMP2, TMP, counter_offset);
-  }
+  LoadIsolate(TMP2);
+  intptr_t table_offset =
+      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  ldr(TMP, Address(TMP2, table_offset));
+  AddImmediate(TMP2, TMP, counter_offset);
   ldr(TMP, Address(TMP2, 0));
   AddImmediate(TMP, TMP, 1);
   str(TMP, Address(TMP2, 0));
@@ -1296,8 +1280,7 @@
 
 void Assembler::UpdateAllocationStatsWithSize(intptr_t cid,
                                               Register size_reg,
-                                              Heap::Space space,
-                                              bool inline_isolate) {
+                                              Heap::Space space) {
   ASSERT(cid > 0);
   const uword class_offset = ClassTable::ClassOffsetFor(cid);
   const uword count_field_offset = (space == Heap::kNew) ?
@@ -1306,24 +1289,11 @@
   const uword size_field_offset = (space == Heap::kNew) ?
     ClassHeapStats::allocated_size_since_gc_new_space_offset() :
     ClassHeapStats::allocated_size_since_gc_old_space_offset();
-  if (inline_isolate) {
-    ClassTable* class_table = Isolate::Current()->class_table();
-    ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
-    if (cid < kNumPredefinedCids) {
-      LoadImmediate(TMP2,
-                    reinterpret_cast<uword>(*table_ptr) + class_offset);
-    } else {
-      LoadImmediate(TMP2, reinterpret_cast<uword>(table_ptr));
-      ldr(TMP, Address(TMP2));
-      AddImmediate(TMP2, TMP, class_offset);
-    }
-  } else {
-    LoadIsolate(TMP2);
-    intptr_t table_offset =
-        Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
-    ldr(TMP, Address(TMP2, table_offset));
-    AddImmediate(TMP2, TMP, class_offset);
-  }
+  LoadIsolate(TMP2);
+  intptr_t table_offset =
+      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  ldr(TMP, Address(TMP2, table_offset));
+  AddImmediate(TMP2, TMP, class_offset);
   ldr(TMP, Address(TMP2, count_field_offset));
   AddImmediate(TMP, TMP, 1);
   str(TMP, Address(TMP2, count_field_offset));
@@ -1335,29 +1305,14 @@
 
 void Assembler::MaybeTraceAllocation(intptr_t cid,
                                      Register temp_reg,
-                                     Label* trace,
-                                     bool inline_isolate) {
+                                     Label* trace) {
   ASSERT(cid > 0);
   intptr_t state_offset = ClassTable::StateOffsetFor(cid);
-  if (inline_isolate) {
-    ASSERT(FLAG_allow_absolute_addresses);
-    ClassTable* class_table = Isolate::Current()->class_table();
-    ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
-    if (cid < kNumPredefinedCids) {
-      LoadImmediate(
-          temp_reg, reinterpret_cast<uword>(*table_ptr) + state_offset);
-    } else {
-      LoadImmediate(temp_reg, reinterpret_cast<uword>(table_ptr));
-      ldr(temp_reg, Address(temp_reg, 0));
-      AddImmediate(temp_reg, temp_reg, state_offset);
-    }
-  } else {
-    LoadIsolate(temp_reg);
-    intptr_t table_offset =
-        Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
-    ldr(temp_reg, Address(temp_reg, table_offset));
-    AddImmediate(temp_reg, temp_reg, state_offset);
-  }
+  LoadIsolate(temp_reg);
+  intptr_t table_offset =
+      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  ldr(temp_reg, Address(temp_reg, table_offset));
+  AddImmediate(temp_reg, temp_reg, state_offset);
   ldr(temp_reg, Address(temp_reg, 0));
   tsti(temp_reg, Immediate(ClassHeapStats::TraceAllocationMask()));
   b(trace, NE);
@@ -1373,8 +1328,7 @@
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cls.id(), temp_reg, failure,
-                         /* inline_isolate = */ false);
+    MaybeTraceAllocation(cls.id(), temp_reg, failure);
     const intptr_t instance_size = cls.instance_size();
     Heap::Space space = Heap::SpaceForAllocation(cls.id());
     ldr(temp_reg, Address(THR, Thread::heap_offset()));
@@ -1395,7 +1349,7 @@
     ASSERT(instance_size >= kHeapObjectTag);
     AddImmediate(
         instance_reg, instance_reg, -instance_size + kHeapObjectTag);
-    UpdateAllocationStats(cls.id(), space, /* inline_isolate = */ false);
+    UpdateAllocationStats(cls.id(), space);
 
     uword tags = 0;
     tags = RawObject::SizeTag::update(instance_size, tags);
@@ -1420,7 +1374,7 @@
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cid, temp1, failure, /* inline_isolate = */ false);
+    MaybeTraceAllocation(cid, temp1, failure);
     Heap::Space space = Heap::SpaceForAllocation(cid);
     ldr(temp1, Address(THR, Thread::heap_offset()));
     // Potential new object start.
@@ -1440,8 +1394,7 @@
     str(end_address, Address(temp1, Heap::TopOffset(space)));
     add(instance, instance, Operand(kHeapObjectTag));
     LoadImmediate(temp2, instance_size);
-    UpdateAllocationStatsWithSize(cid, temp2, space,
-                                  /* inline_isolate = */ false);
+    UpdateAllocationStatsWithSize(cid, temp2, space);
 
     // Initialize the tags.
     // instance: new object start as a tagged pointer.
diff --git a/runtime/vm/assembler_arm64.h b/runtime/vm/assembler_arm64.h
index ee8eb70..735e07e 100644
--- a/runtime/vm/assembler_arm64.h
+++ b/runtime/vm/assembler_arm64.h
@@ -1378,20 +1378,17 @@
   void LeaveStubFrame();
 
   void UpdateAllocationStats(intptr_t cid,
-                             Heap::Space space,
-                             bool inline_isolate = true);
+                             Heap::Space space);
 
   void UpdateAllocationStatsWithSize(intptr_t cid,
                                      Register size_reg,
-                                     Heap::Space space,
-                                     bool inline_isolate = true);
+                                     Heap::Space space);
 
   // If allocation tracing for |cid| is enabled, will jump to |trace| label,
   // which will allocate in the runtime where tracing occurs.
   void MaybeTraceAllocation(intptr_t cid,
                             Register temp_reg,
-                            Label* trace,
-                            bool inline_isolate = true);
+                            Label* trace);
 
   // Inlined allocation of an instance of class 'cls', code has no runtime
   // calls. Jump to 'failure' if the instance cannot be allocated here.
diff --git a/runtime/vm/assembler_dbc.cc b/runtime/vm/assembler_dbc.cc
new file mode 100644
index 0000000..f35d1d5
--- /dev/null
+++ b/runtime/vm/assembler_dbc.cc
@@ -0,0 +1,141 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h"  // NOLINT
+#if defined(TARGET_ARCH_DBC)
+
+#include "vm/assembler.h"
+#include "vm/cpu.h"
+#include "vm/longjump.h"
+#include "vm/runtime_entry.h"
+#include "vm/simulator.h"
+#include "vm/stack_frame.h"
+#include "vm/stub_code.h"
+
+namespace dart {
+
+DECLARE_FLAG(bool, check_code_pointer);
+DECLARE_FLAG(bool, inline_alloc);
+
+void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) {
+  const uword end = data + length;
+  while (data < end) {
+    *reinterpret_cast<int32_t*>(data) = Bytecode::kTrap;
+    data += sizeof(int32_t);
+  }
+}
+
+#define DEFINE_EMIT(Name, Signature, Fmt0, Fmt1, Fmt2)  \
+  void Assembler::Name(PARAMS_##Signature) {            \
+    Emit(Bytecode::FENCODE_##Signature(                 \
+        Bytecode::k##Name ENCODE_##Signature));         \
+  }                                                     \
+
+
+#define PARAMS_0
+#define PARAMS_A_D uintptr_t ra, uintptr_t rd
+#define PARAMS_D uintptr_t rd
+#define PARAMS_A_B_C uintptr_t ra, uintptr_t rb, uintptr_t rc
+#define PARAMS_A uintptr_t ra
+#define PARAMS_T intptr_t x
+#define PARAMS_A_X uintptr_t ra, intptr_t x
+#define PARAMS_X intptr_t x
+
+#define ENCODE_0
+#define ENCODE_A_D , ra, rd
+#define ENCODE_D , 0, rd
+#define ENCODE_A_B_C , ra, rb, rc
+#define ENCODE_A , ra, 0
+#define ENCODE_T , x
+#define ENCODE_A_X , ra, x
+#define ENCODE_X , 0, x
+
+#define FENCODE_0 Encode
+#define FENCODE_A_D Encode
+#define FENCODE_D Encode
+#define FENCODE_A_B_C Encode
+#define FENCODE_A Encode
+#define FENCODE_T EncodeSigned
+#define FENCODE_A_X EncodeSigned
+#define FENCODE_X EncodeSigned
+
+
+BYTECODES_LIST(DEFINE_EMIT)
+
+
+#undef DEFINE_EMIT
+
+
+void Assembler::Emit(int32_t value) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  buffer_.Emit<int32_t>(value);
+}
+
+
+const char* Assembler::RegisterName(Register reg) {
+  return Thread::Current()->zone()->PrintToString("R%d", reg);
+}
+
+
+static int32_t EncodeJump(int32_t relative_pc) {
+  return Bytecode::kJump | (relative_pc << 8);
+}
+
+
+static int32_t OffsetToPC(int32_t offset) {
+  return offset >> 2;
+}
+
+
+void Assembler::Jump(Label* label) {
+  if (label->IsBound()) {
+    Emit(EncodeJump(OffsetToPC(label->Position() - buffer_.Size())));
+  } else {
+    const intptr_t position = buffer_.Size();
+    Emit(label->position_);
+    label->LinkTo(position);
+  }
+}
+
+
+void Assembler::Bind(Label* label) {
+  ASSERT(!label->IsBound());
+  ASSERT(!label->IsBound());
+  intptr_t bound_pc = buffer_.Size();
+  while (label->IsLinked()) {
+    const int32_t position = label->Position();
+    const int32_t next_position = buffer_.Load<int32_t>(position);
+    buffer_.Store<int32_t>(position,
+                           EncodeJump(OffsetToPC(bound_pc - position)));
+    label->position_ = next_position;
+  }
+  label->BindTo(bound_pc);
+}
+
+
+void Assembler::Stop(const char* message) {
+  // TODO(vegorov) support passing a message to the bytecode.
+  Emit(Bytecode::kTrap);
+}
+
+
+void Assembler::PushConstant(const Object& obj) {
+  PushConstant(AddConstant(obj));
+}
+
+
+void Assembler::LoadConstant(uintptr_t ra, const Object& obj) {
+  LoadConstant(ra, AddConstant(obj));
+}
+
+
+intptr_t Assembler::AddConstant(const Object& obj) {
+  return object_pool_wrapper().FindObject(
+      Object::ZoneHandle(obj.raw()));
+}
+
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/assembler_dbc.h b/runtime/vm/assembler_dbc.h
new file mode 100644
index 0000000..590dd5c
--- /dev/null
+++ b/runtime/vm/assembler_dbc.h
@@ -0,0 +1,197 @@
+// 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.
+
+#ifndef VM_ASSEMBLER_DBC_H_
+#define VM_ASSEMBLER_DBC_H_
+
+#ifndef VM_ASSEMBLER_H_
+#error Do not include assembler_dbc.h directly; use assembler.h instead.
+#endif
+
+#include "platform/assert.h"
+#include "platform/utils.h"
+#include "vm/constants_dbc.h"
+#include "vm/cpu.h"
+#include "vm/hash_map.h"
+#include "vm/object.h"
+#include "vm/simulator.h"
+
+namespace dart {
+
+
+// Dummy declaration to make things compile.
+class Address : public ValueObject {
+ private:
+  Address();
+};
+
+
+class Label : public ValueObject {
+ public:
+  Label() : position_(0) { }
+
+  ~Label() {
+    // Assert if label is being destroyed with unresolved branches pending.
+    ASSERT(!IsLinked());
+  }
+
+  // Returns the position for bound and linked labels. Cannot be used
+  // for unused labels.
+  intptr_t Position() const {
+    ASSERT(!IsUnused());
+    return IsBound() ? -position_ - kWordSize : position_ - kWordSize;
+  }
+
+  bool IsBound() const { return position_ < 0; }
+  bool IsUnused() const { return position_ == 0; }
+  bool IsLinked() const { return position_ > 0; }
+
+ private:
+  intptr_t position_;
+
+  void Reinitialize() {
+    position_ = 0;
+  }
+
+  void BindTo(intptr_t position) {
+    ASSERT(!IsBound());
+    position_ = -position - kWordSize;
+    ASSERT(IsBound());
+  }
+
+  void LinkTo(intptr_t position) {
+    ASSERT(!IsBound());
+    position_ = position + kWordSize;
+    ASSERT(IsLinked());
+  }
+
+  friend class Assembler;
+  DISALLOW_COPY_AND_ASSIGN(Label);
+};
+
+
+class Assembler : public ValueObject {
+ public:
+  explicit Assembler(bool use_far_branches = false)
+      : buffer_(),
+        comments_() {
+  }
+
+  ~Assembler() { }
+
+  void Bind(Label* label);
+  void Jump(Label* label);
+
+  // Misc. functionality
+  intptr_t CodeSize() const { return buffer_.Size(); }
+  intptr_t prologue_offset() const { return 0; }
+
+  // Count the fixups that produce a pointer offset, without processing
+  // the fixups.
+  intptr_t CountPointerOffsets() const { return 0; }
+
+  const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const {
+    ASSERT(buffer_.pointer_offsets().length() == 0);  // No pointers in code.
+    return buffer_.pointer_offsets();
+  }
+
+  ObjectPoolWrapper& object_pool_wrapper() { return object_pool_wrapper_; }
+
+  RawObjectPool* MakeObjectPool() {
+    return object_pool_wrapper_.MakeObjectPool();
+  }
+
+  void FinalizeInstructions(const MemoryRegion& region) {
+    buffer_.FinalizeInstructions(region);
+  }
+
+  // Debugging and bringup support.
+  void Stop(const char* message);
+  void Unimplemented(const char* message);
+  void Untested(const char* message);
+  void Unreachable(const char* message);
+
+  static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
+
+  void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
+  static bool EmittingComments();
+
+  const Code::Comments& GetCodeComments() const;
+
+  static const char* RegisterName(Register reg);
+
+  static const char* FpuRegisterName(FpuRegister reg) {
+    return "?";
+  }
+
+  static uword GetBreakInstructionFiller() {
+    return Bytecode::kTrap;
+  }
+
+  static bool IsSafe(const Object& value) { return true; }
+  static bool IsSafeSmi(const Object& value) { return false; }
+
+  // Bytecodes.
+
+#define DECLARE_EMIT(Name, Signature, Fmt0, Fmt1, Fmt2) \
+  void Name(PARAMS_##Signature);
+
+#define PARAMS_0
+#define PARAMS_A_D uintptr_t ra, uintptr_t rd
+#define PARAMS_D uintptr_t rd
+#define PARAMS_A_B_C uintptr_t ra, uintptr_t rb, uintptr_t rc
+#define PARAMS_A uintptr_t ra
+#define PARAMS_X intptr_t x
+#define PARAMS_T intptr_t x
+#define PARAMS_A_X uintptr_t ra, intptr_t x
+
+
+  BYTECODES_LIST(DECLARE_EMIT)
+
+#undef PARAMS_0
+#undef PARAMS_A_D
+#undef PARAMS_D
+#undef PARAMS_A_B_C
+#undef PARAMS_A
+#undef PARAMS_X
+#undef PARAMS_T
+#undef PARAMS_A_X
+#undef DECLARE_EMIT
+
+  void Emit(int32_t value);
+
+  void PushConstant(const Object& obj);
+  void LoadConstant(uintptr_t ra, const Object& obj);
+
+  intptr_t AddConstant(const Object& obj);
+
+ private:
+  AssemblerBuffer buffer_;  // Contains position independent code.
+  ObjectPoolWrapper object_pool_wrapper_;
+
+  class CodeComment : public ZoneAllocated {
+   public:
+    CodeComment(intptr_t pc_offset, const String& comment)
+        : pc_offset_(pc_offset), comment_(comment) { }
+
+    intptr_t pc_offset() const { return pc_offset_; }
+    const String& comment() const { return comment_; }
+
+   private:
+    intptr_t pc_offset_;
+    const String& comment_;
+
+    DISALLOW_COPY_AND_ASSIGN(CodeComment);
+  };
+
+  GrowableArray<CodeComment*> comments_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(Assembler);
+};
+
+
+}  // namespace dart
+
+#endif  // VM_ASSEMBLER_DBC_H_
diff --git a/runtime/vm/assembler_ia32.cc b/runtime/vm/assembler_ia32.cc
index b9e80d0..e8851ac 100644
--- a/runtime/vm/assembler_ia32.cc
+++ b/runtime/vm/assembler_ia32.cc
@@ -2704,32 +2704,16 @@
 void Assembler::MaybeTraceAllocation(intptr_t cid,
                                      Register temp_reg,
                                      Label* trace,
-                                     bool near_jump,
-                                     bool inline_isolate) {
+                                     bool near_jump) {
   ASSERT(cid > 0);
   Address state_address(kNoRegister, 0);
   intptr_t state_offset = ClassTable::StateOffsetFor(cid);
-  if (inline_isolate) {
-    ClassTable* class_table = Isolate::Current()->class_table();
-    ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
-    if (cid < kNumPredefinedCids) {
-      state_address = Address::Absolute(
-          reinterpret_cast<uword>(*table_ptr) + state_offset);
-    } else {
-      ASSERT(temp_reg != kNoRegister);
-      // temp_reg gets address of class table pointer.
-      movl(temp_reg,
-           Address::Absolute(reinterpret_cast<uword>(table_ptr)));
-      state_address = Address(temp_reg, state_offset);
-    }
-  } else {
-    ASSERT(temp_reg != kNoRegister);
-    LoadIsolate(temp_reg);
-    intptr_t table_offset =
-        Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
-    movl(temp_reg, Address(temp_reg, table_offset));
-    state_address = Address(temp_reg, state_offset);
-  }
+  ASSERT(temp_reg != kNoRegister);
+  LoadIsolate(temp_reg);
+  intptr_t table_offset =
+      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  movl(temp_reg, Address(temp_reg, table_offset));
+  state_address = Address(temp_reg, state_offset);
   testb(state_address, Immediate(ClassHeapStats::TraceAllocationMask()));
   // We are tracing for this class, jump to the trace label which will use
   // the allocation stub.
@@ -2739,71 +2723,40 @@
 
 void Assembler::UpdateAllocationStats(intptr_t cid,
                                       Register temp_reg,
-                                      Heap::Space space,
-                                      bool inline_isolate) {
+                                      Heap::Space space) {
   ASSERT(cid > 0);
   intptr_t counter_offset =
       ClassTable::CounterOffsetFor(cid, space == Heap::kNew);
-  if (inline_isolate) {
-    ClassTable* class_table = Isolate::Current()->class_table();
-    ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
-    if (cid < kNumPredefinedCids) {
-      incl(Address::Absolute(
-          reinterpret_cast<uword>(*table_ptr) + counter_offset));
-    } else {
-      ASSERT(temp_reg != kNoRegister);
-      movl(temp_reg,
-           Address::Absolute(reinterpret_cast<uword>(table_ptr)));
-      incl(Address(temp_reg, counter_offset));
-    }
-  } else {
-    ASSERT(temp_reg != kNoRegister);
-    LoadIsolate(temp_reg);
-    intptr_t table_offset =
-        Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
-    movl(temp_reg, Address(temp_reg, table_offset));
-    incl(Address(temp_reg, counter_offset));
-  }
+  ASSERT(temp_reg != kNoRegister);
+  LoadIsolate(temp_reg);
+  intptr_t table_offset =
+      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  movl(temp_reg, Address(temp_reg, table_offset));
+  incl(Address(temp_reg, counter_offset));
 }
 
 
 void Assembler::UpdateAllocationStatsWithSize(intptr_t cid,
                                               Register size_reg,
                                               Register temp_reg,
-                                              Heap::Space space,
-                                              bool inline_isolate) {
+                                              Heap::Space space) {
   ASSERT(cid > 0);
   ASSERT(cid < kNumPredefinedCids);
-  UpdateAllocationStats(cid, temp_reg, space, inline_isolate);
+  UpdateAllocationStats(cid, temp_reg, space);
   intptr_t size_offset = ClassTable::SizeOffsetFor(cid, space == Heap::kNew);
-  if (inline_isolate) {
-    ClassTable* class_table = Isolate::Current()->class_table();
-    ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
-    addl(Address::Absolute(
-        reinterpret_cast<uword>(*table_ptr) + size_offset), size_reg);
-  } else {
-    addl(Address(temp_reg, size_offset), size_reg);
-  }
+  addl(Address(temp_reg, size_offset), size_reg);
 }
 
 
 void Assembler::UpdateAllocationStatsWithSize(intptr_t cid,
                                               intptr_t size_in_bytes,
                                               Register temp_reg,
-                                              Heap::Space space,
-                                              bool inline_isolate) {
+                                              Heap::Space space) {
   ASSERT(cid > 0);
   ASSERT(cid < kNumPredefinedCids);
-  UpdateAllocationStats(cid, temp_reg, space, inline_isolate);
+  UpdateAllocationStats(cid, temp_reg, space);
   intptr_t size_offset = ClassTable::SizeOffsetFor(cid, space == Heap::kNew);
-  if (inline_isolate) {
-    ClassTable* class_table = Isolate::Current()->class_table();
-    ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
-    addl(Address::Absolute(reinterpret_cast<uword>(*table_ptr) + size_offset),
-         Immediate(size_in_bytes));
-  } else {
-    addl(Address(temp_reg, size_offset), Immediate(size_in_bytes));
-  }
+  addl(Address(temp_reg, size_offset), Immediate(size_in_bytes));
 }
 
 
@@ -2818,8 +2771,7 @@
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cls.id(), temp_reg, failure, near_jump,
-                         /* inline_isolate = */ false);
+    MaybeTraceAllocation(cls.id(), temp_reg, failure, near_jump);
     const intptr_t instance_size = cls.instance_size();
     Heap::Space space = Heap::SpaceForAllocation(cls.id());
     movl(temp_reg, Address(THR, Thread::heap_offset()));
@@ -2831,8 +2783,7 @@
     // Successfully allocated the object, now update top to point to
     // next object start and store the class in the class field of object.
     movl(Address(temp_reg, Heap::TopOffset(space)), instance_reg);
-    UpdateAllocationStats(cls.id(), temp_reg, space,
-                          /* inline_isolate = */ false);
+    UpdateAllocationStats(cls.id(), temp_reg, space);
     ASSERT(instance_size >= kHeapObjectTag);
     subl(instance_reg, Immediate(instance_size - kHeapObjectTag));
     uword tags = 0;
@@ -2859,8 +2810,7 @@
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cid, temp_reg, failure, near_jump,
-                         /* inline_isolate = */ false);
+    MaybeTraceAllocation(cid, temp_reg, failure, near_jump);
     Heap::Space space = Heap::SpaceForAllocation(cid);
     movl(temp_reg, Address(THR, Thread::heap_offset()));
     movl(instance, Address(temp_reg, Heap::TopOffset(space)));
@@ -2879,8 +2829,7 @@
     // next object start and initialize the object.
     movl(Address(temp_reg, Heap::TopOffset(space)), end_address);
     addl(instance, Immediate(kHeapObjectTag));
-    UpdateAllocationStatsWithSize(cid, instance_size, temp_reg, space,
-                                  /* inline_isolate = */ false);
+    UpdateAllocationStatsWithSize(cid, instance_size, temp_reg, space);
 
     // Initialize the tags.
     uword tags = 0;
diff --git a/runtime/vm/assembler_ia32.h b/runtime/vm/assembler_ia32.h
index 536a06e..5753792 100644
--- a/runtime/vm/assembler_ia32.h
+++ b/runtime/vm/assembler_ia32.h
@@ -892,24 +892,20 @@
   void MaybeTraceAllocation(intptr_t cid,
                             Register temp_reg,
                             Label* trace,
-                            bool near_jump,
-                            bool inline_isolate = true);
+                            bool near_jump);
 
   void UpdateAllocationStats(intptr_t cid,
                              Register temp_reg,
-                             Heap::Space space,
-                             bool inline_isolate = true);
+                             Heap::Space space);
 
   void UpdateAllocationStatsWithSize(intptr_t cid,
                                      Register size_reg,
                                      Register temp_reg,
-                                     Heap::Space space,
-                                     bool inline_isolate = true);
+                                     Heap::Space space);
   void UpdateAllocationStatsWithSize(intptr_t cid,
                                      intptr_t instance_size,
                                      Register temp_reg,
-                                     Heap::Space space,
-                                     bool inline_isolate = true);
+                                     Heap::Space space);
 
   // Inlined allocation of an instance of class 'cls', code has no runtime
   // calls. Jump to 'failure' if the instance cannot be allocated here.
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc
index 68794ed..c9c6549 100644
--- a/runtime/vm/assembler_mips.cc
+++ b/runtime/vm/assembler_mips.cc
@@ -588,14 +588,7 @@
                   : object_pool_wrapper_.FindObject(object));
     LoadWordFromPoolOffset(rd, offset - kHeapObjectTag);
   } else {
-    ASSERT(FLAG_allow_absolute_addresses);
-    ASSERT(object.IsOld());
-    // Make sure that class CallPattern is able to decode this load immediate.
-    int32_t object_raw = reinterpret_cast<int32_t>(object.raw());
-    const uint16_t object_low = Utils::Low16Bits(object_raw);
-    const uint16_t object_high = Utils::High16Bits(object_raw);
-    lui(rd, Immediate(object_high));
-    ori(rd, rd, Immediate(object_low));
+    UNREACHABLE();
   }
 }
 
@@ -912,34 +905,18 @@
 
 void Assembler::UpdateAllocationStats(intptr_t cid,
                                       Register temp_reg,
-                                      Heap::Space space,
-                                      bool inline_isolate) {
+                                      Heap::Space space) {
   ASSERT(!in_delay_slot_);
   ASSERT(temp_reg != kNoRegister);
   ASSERT(temp_reg != TMP);
   ASSERT(cid > 0);
   intptr_t counter_offset =
       ClassTable::CounterOffsetFor(cid, space == Heap::kNew);
-  if (inline_isolate) {
-    ASSERT(FLAG_allow_absolute_addresses);
-    ClassTable* class_table = Isolate::Current()->class_table();
-    ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
-    if (cid < kNumPredefinedCids) {
-      LoadImmediate(
-          temp_reg, reinterpret_cast<uword>(*table_ptr) + counter_offset);
-    } else {
-      ASSERT(temp_reg != kNoRegister);
-      LoadImmediate(temp_reg, reinterpret_cast<uword>(table_ptr));
-      lw(temp_reg, Address(temp_reg, 0));
-      AddImmediate(temp_reg, counter_offset);
-    }
-  } else {
-    LoadIsolate(temp_reg);
-    intptr_t table_offset =
-        Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
-    lw(temp_reg, Address(temp_reg, table_offset));
-    AddImmediate(temp_reg, counter_offset);
-  }
+  LoadIsolate(temp_reg);
+  intptr_t table_offset =
+      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  lw(temp_reg, Address(temp_reg, table_offset));
+  AddImmediate(temp_reg, counter_offset);
   lw(TMP, Address(temp_reg, 0));
   AddImmediate(TMP, 1);
   sw(TMP, Address(temp_reg, 0));
@@ -949,8 +926,7 @@
 void Assembler::UpdateAllocationStatsWithSize(intptr_t cid,
                                               Register size_reg,
                                               Register temp_reg,
-                                              Heap::Space space,
-                                              bool inline_isolate) {
+                                              Heap::Space space) {
   ASSERT(!in_delay_slot_);
   ASSERT(temp_reg != kNoRegister);
   ASSERT(cid > 0);
@@ -962,25 +938,11 @@
   const uword size_field_offset = (space == Heap::kNew) ?
     ClassHeapStats::allocated_size_since_gc_new_space_offset() :
     ClassHeapStats::allocated_size_since_gc_old_space_offset();
-  if (inline_isolate) {
-    ClassTable* class_table = Isolate::Current()->class_table();
-    ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
-    if (cid < kNumPredefinedCids) {
-      LoadImmediate(temp_reg,
-                    reinterpret_cast<uword>(*table_ptr) + class_offset);
-    } else {
-      ASSERT(temp_reg != kNoRegister);
-      LoadImmediate(temp_reg, reinterpret_cast<uword>(table_ptr));
-      lw(temp_reg, Address(temp_reg, 0));
-      AddImmediate(temp_reg, class_offset);
-    }
-  } else {
-    LoadIsolate(temp_reg);
-    intptr_t table_offset =
-        Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
-    lw(temp_reg, Address(temp_reg, table_offset));
-    AddImmediate(temp_reg, class_offset);
-  }
+  LoadIsolate(temp_reg);
+  intptr_t table_offset =
+      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  lw(temp_reg, Address(temp_reg, table_offset));
+  AddImmediate(temp_reg, class_offset);
   lw(TMP, Address(temp_reg, count_field_offset));
   AddImmediate(TMP, 1);
   sw(TMP, Address(temp_reg, count_field_offset));
@@ -992,32 +954,17 @@
 
 void Assembler::MaybeTraceAllocation(intptr_t cid,
                                      Register temp_reg,
-                                     Label* trace,
-                                     bool inline_isolate) {
+                                     Label* trace) {
   ASSERT(cid > 0);
   ASSERT(!in_delay_slot_);
   ASSERT(temp_reg != kNoRegister);
   ASSERT(temp_reg != TMP);
   intptr_t state_offset = ClassTable::StateOffsetFor(cid);
-  if (inline_isolate) {
-    ASSERT(FLAG_allow_absolute_addresses);
-    ClassTable* class_table = Isolate::Current()->class_table();
-    ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
-    if (cid < kNumPredefinedCids) {
-      LoadImmediate(temp_reg,
-                    reinterpret_cast<uword>(*table_ptr) + state_offset);
-    } else {
-      LoadImmediate(temp_reg, reinterpret_cast<uword>(table_ptr));
-      lw(temp_reg, Address(temp_reg, 0));
-      AddImmediate(temp_reg, state_offset);
-    }
-  } else {
-    LoadIsolate(temp_reg);
-    intptr_t table_offset =
-        Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
-    lw(temp_reg, Address(temp_reg, table_offset));
-    AddImmediate(temp_reg, state_offset);
-  }
+  LoadIsolate(temp_reg);
+  intptr_t table_offset =
+    Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  lw(temp_reg, Address(temp_reg, table_offset));
+  AddImmediate(temp_reg, state_offset);
   lw(temp_reg, Address(temp_reg, 0));
   andi(CMPRES1, temp_reg, Immediate(ClassHeapStats::TraceAllocationMask()));
   bne(CMPRES1, ZR, trace);
@@ -1034,8 +981,7 @@
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cls.id(), temp_reg, failure,
-                         /* inline_isolate = */ false);
+    MaybeTraceAllocation(cls.id(), temp_reg, failure);
     const intptr_t instance_size = cls.instance_size();
     Heap::Space space = Heap::SpaceForAllocation(cls.id());
     lw(temp_reg, Address(THR, Thread::heap_offset()));
@@ -1054,8 +1000,7 @@
 
     ASSERT(instance_size >= kHeapObjectTag);
     AddImmediate(instance_reg, -instance_size + kHeapObjectTag);
-    UpdateAllocationStats(cls.id(), temp_reg, space,
-                          /* inline_isolate = */ false);
+    UpdateAllocationStats(cls.id(), temp_reg, space);
     uword tags = 0;
     tags = RawObject::SizeTag::update(instance_size, tags);
     ASSERT(cls.id() != kIllegalCid);
@@ -1079,7 +1024,7 @@
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cid, temp1, failure, /* inline_isolate = */ false);
+    MaybeTraceAllocation(cid, temp1, failure);
     Isolate* isolate = Isolate::Current();
     Heap* heap = isolate->heap();
     Heap::Space space = heap->SpaceForAllocation(cid);
@@ -1102,8 +1047,7 @@
     sw(end_address, Address(temp1, Heap::TopOffset(space)));
     addiu(instance, instance, Immediate(kHeapObjectTag));
     LoadImmediate(temp1, instance_size);
-    UpdateAllocationStatsWithSize(cid, temp1, temp2, space,
-                                  /* inline_isolate = */ false);
+    UpdateAllocationStatsWithSize(cid, temp1, temp2, space);
 
     // Initialize the tags.
     // instance: new object start as a tagged pointer.
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index 4e4f7f3..39b06a4 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -297,20 +297,17 @@
 
   void UpdateAllocationStats(intptr_t cid,
                              Register temp_reg,
-                             Heap::Space space,
-                             bool inline_isolate = true);
+                             Heap::Space space);
 
   void UpdateAllocationStatsWithSize(intptr_t cid,
                                      Register size_reg,
                                      Register temp_reg,
-                                     Heap::Space space,
-                                     bool inline_isolate = true);
+                                     Heap::Space space);
 
 
   void MaybeTraceAllocation(intptr_t cid,
                             Register temp_reg,
-                            Label* trace,
-                            bool inline_isolate = true);
+                            Label* trace);
 
   // Inlined allocation of an instance of class 'cls', code has no runtime
   // calls. Jump to 'failure' if the instance cannot be allocated here.
diff --git a/runtime/vm/assembler_test.cc b/runtime/vm/assembler_test.cc
index fbbd994..88ff667 100644
--- a/runtime/vm/assembler_test.cc
+++ b/runtime/vm/assembler_test.cc
@@ -11,6 +11,8 @@
 
 namespace dart {
 
+// TODO(vegorov) assembler part of this test is not implemented.
+#if !defined(TARGET_ARCH_DBC)
 ASSEMBLER_TEST_EXTERN(StoreIntoObject);
 
 ASSEMBLER_TEST_RUN(StoreIntoObject, test) {
@@ -60,5 +62,6 @@
   EXPECT(old_array.raw() == grow_new_array.data());
   EXPECT(!thread->StoreBufferContains(grow_new_array.raw()));
 }
+#endif
 
 }  // namespace dart
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc
index 478c2ae..67bc237 100644
--- a/runtime/vm/assembler_x64.cc
+++ b/runtime/vm/assembler_x64.cc
@@ -2803,8 +2803,7 @@
     const int32_t offset = ObjectPool::element_offset(idx);
     LoadWordFromPoolOffset(dst, offset - kHeapObjectTag);
   } else {
-    ASSERT(object.IsSmi() || object.InVMHeap());
-    ASSERT(object.IsSmi() || FLAG_allow_absolute_addresses);
+    ASSERT(object.IsSmi());
     LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())));
   }
 }
@@ -2841,7 +2840,7 @@
     LoadObject(TMP, object);
     movq(dst, TMP);
   } else {
-    ASSERT(object.IsSmi() || FLAG_allow_absolute_addresses);
+    ASSERT(object.IsSmi());
     MoveImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())));
   }
 }
@@ -2856,7 +2855,7 @@
     LoadObject(TMP, object);
     pushq(TMP);
   } else {
-    ASSERT(object.IsSmi() || FLAG_allow_absolute_addresses);
+    ASSERT(object.IsSmi());
     PushImmediate(Immediate(reinterpret_cast<int64_t>(object.raw())));
   }
 }
@@ -2872,7 +2871,7 @@
     const int32_t offset =  ObjectPool::element_offset(idx);
     cmpq(reg, Address(PP, offset-kHeapObjectTag));
   } else {
-    ASSERT(object.IsSmi() || FLAG_allow_absolute_addresses);
+    ASSERT(object.IsSmi());
     CompareImmediate(
         reg, Immediate(reinterpret_cast<int64_t>(object.raw())));
   }
@@ -3458,27 +3457,14 @@
 
 void Assembler::MaybeTraceAllocation(intptr_t cid,
                                      Label* trace,
-                                     bool near_jump,
-                                     bool inline_isolate) {
+                                     bool near_jump) {
   ASSERT(cid > 0);
   intptr_t state_offset = ClassTable::StateOffsetFor(cid);
   Register temp_reg = TMP;
-  if (inline_isolate) {
-    ASSERT(FLAG_allow_absolute_addresses);
-    ClassTable* class_table = Isolate::Current()->class_table();
-    ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
-    if (cid < kNumPredefinedCids) {
-      movq(temp_reg, Immediate(reinterpret_cast<uword>(*table_ptr)));
-    } else {
-      movq(temp_reg, Immediate(reinterpret_cast<uword>(table_ptr)));
-      movq(temp_reg, Address(temp_reg, 0));
-    }
-  } else {
-    LoadIsolate(temp_reg);
-    intptr_t table_offset =
-        Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
-    movq(temp_reg, Address(temp_reg, table_offset));
-  }
+  LoadIsolate(temp_reg);
+  intptr_t table_offset =
+      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  movq(temp_reg, Address(temp_reg, table_offset));
   testb(Address(temp_reg, state_offset),
         Immediate(ClassHeapStats::TraceAllocationMask()));
   // We are tracing for this class, jump to the trace label which will use
@@ -3488,39 +3474,25 @@
 
 
 void Assembler::UpdateAllocationStats(intptr_t cid,
-                                      Heap::Space space,
-                                      bool inline_isolate) {
+                                      Heap::Space space) {
   ASSERT(cid > 0);
   intptr_t counter_offset =
       ClassTable::CounterOffsetFor(cid, space == Heap::kNew);
   Register temp_reg = TMP;
-  if (inline_isolate) {
-    ASSERT(FLAG_allow_absolute_addresses);
-    ClassTable* class_table = Isolate::Current()->class_table();
-    ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
-    if (cid < kNumPredefinedCids) {
-      movq(temp_reg, Immediate(reinterpret_cast<uword>(*table_ptr)));
-    } else {
-      movq(temp_reg, Immediate(reinterpret_cast<uword>(table_ptr)));
-      movq(temp_reg, Address(temp_reg, 0));
-    }
-  } else {
-    LoadIsolate(temp_reg);
-    intptr_t table_offset =
-        Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
-    movq(temp_reg, Address(temp_reg, table_offset));
-  }
+  LoadIsolate(temp_reg);
+  intptr_t table_offset =
+      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  movq(temp_reg, Address(temp_reg, table_offset));
   incq(Address(temp_reg, counter_offset));
 }
 
 
 void Assembler::UpdateAllocationStatsWithSize(intptr_t cid,
                                               Register size_reg,
-                                              Heap::Space space,
-                                              bool inline_isolate) {
+                                              Heap::Space space) {
   ASSERT(cid > 0);
   ASSERT(cid < kNumPredefinedCids);
-  UpdateAllocationStats(cid, space, inline_isolate);
+  UpdateAllocationStats(cid, space);
   Register temp_reg = TMP;
   intptr_t size_offset = ClassTable::SizeOffsetFor(cid, space == Heap::kNew);
   addq(Address(temp_reg, size_offset), size_reg);
@@ -3529,11 +3501,10 @@
 
 void Assembler::UpdateAllocationStatsWithSize(intptr_t cid,
                                               intptr_t size_in_bytes,
-                                              Heap::Space space,
-                                              bool inline_isolate) {
+                                              Heap::Space space) {
   ASSERT(cid > 0);
   ASSERT(cid < kNumPredefinedCids);
-  UpdateAllocationStats(cid, space, inline_isolate);
+  UpdateAllocationStats(cid, space);
   Register temp_reg = TMP;
   intptr_t size_offset = ClassTable::SizeOffsetFor(cid, space == Heap::kNew);
   addq(Address(temp_reg, size_offset), Immediate(size_in_bytes));
@@ -3550,8 +3521,7 @@
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cls.id(), failure, near_jump,
-                         /* inline_isolate = */ false);
+    MaybeTraceAllocation(cls.id(), failure, near_jump);
     const intptr_t instance_size = cls.instance_size();
     Heap::Space space = Heap::SpaceForAllocation(cls.id());
     movq(temp, Address(THR, Thread::heap_offset()));
@@ -3563,7 +3533,7 @@
     // Successfully allocated the object, now update top to point to
     // next object start and store the class in the class field of object.
     movq(Address(temp, Heap::TopOffset(space)), instance_reg);
-    UpdateAllocationStats(cls.id(), space, /* inline_isolate = */ false);
+    UpdateAllocationStats(cls.id(), space);
     ASSERT(instance_size >= kHeapObjectTag);
     AddImmediate(instance_reg, Immediate(kHeapObjectTag - instance_size));
     uword tags = 0;
@@ -3590,7 +3560,7 @@
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    MaybeTraceAllocation(cid, failure, near_jump, /* inline_isolate = */ false);
+    MaybeTraceAllocation(cid, failure, near_jump);
     Heap::Space space = Heap::SpaceForAllocation(cid);
     movq(temp, Address(THR, Thread::heap_offset()));
     movq(instance, Address(temp, Heap::TopOffset(space)));
@@ -3609,8 +3579,7 @@
     // next object start and initialize the object.
     movq(Address(temp, Heap::TopOffset(space)), end_address);
     addq(instance, Immediate(kHeapObjectTag));
-    UpdateAllocationStatsWithSize(cid, instance_size, space,
-                                  /* inline_isolate = */ false);
+    UpdateAllocationStatsWithSize(cid, instance_size, space);
 
     // Initialize the tags.
     // instance: new object start as a tagged pointer.
diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h
index 4f6eac3..5f5aea4 100644
--- a/runtime/vm/assembler_x64.h
+++ b/runtime/vm/assembler_x64.h
@@ -975,24 +975,20 @@
   void LeaveStubFrame();
 
   void UpdateAllocationStats(intptr_t cid,
-                             Heap::Space space,
-                             bool inline_isolate = true);
+                             Heap::Space space);
 
   void UpdateAllocationStatsWithSize(intptr_t cid,
                                      Register size_reg,
-                                     Heap::Space space,
-                                     bool inline_isolate = true);
+                                     Heap::Space space);
   void UpdateAllocationStatsWithSize(intptr_t cid,
                                      intptr_t instance_size,
-                                     Heap::Space space,
-                                     bool inline_isolate = true);
+                                     Heap::Space space);
 
   // If allocation tracing for |cid| is enabled, will jump to |trace| label,
   // which will allocate in the runtime where tracing occurs.
   void MaybeTraceAllocation(intptr_t cid,
                             Label* trace,
-                            bool near_jump,
-                            bool inline_isolate = true);
+                            bool near_jump);
 
   // Inlined allocation of an instance of class 'cls', code has no runtime
   // calls. Jump to 'failure' if the instance cannot be allocated here.
diff --git a/runtime/vm/ast.cc b/runtime/vm/ast.cc
index 8ac98c2..2ba8dc1 100644
--- a/runtime/vm/ast.cc
+++ b/runtime/vm/ast.cc
@@ -337,11 +337,6 @@
 }
 
 
-const char* BinaryOpWithMask32Node::TokenName() const {
-  return Token::Str(kind());
-}
-
-
 bool BinaryOpNode::IsPotentiallyConst() const {
   switch (kind_) {
     case Token::kOR:
diff --git a/runtime/vm/ast.h b/runtime/vm/ast.h
index 4ca2372..13184af 100644
--- a/runtime/vm/ast.h
+++ b/runtime/vm/ast.h
@@ -24,7 +24,6 @@
   V(Type)                                                                      \
   V(Assignable)                                                                \
   V(BinaryOp)                                                                  \
-  V(BinaryOpWithMask32)                                                        \
   V(Comparison)                                                                \
   V(UnaryOp)                                                                   \
   V(ConditionalExpr)                                                           \
@@ -769,36 +768,6 @@
 };
 
 
-class BinaryOpWithMask32Node : public BinaryOpNode {
- public:
-  BinaryOpWithMask32Node(TokenPosition token_pos,
-                         Token::Kind kind_value,
-                         AstNode* left,
-                         AstNode* right,
-                         int64_t mask32)
-      : BinaryOpNode(token_pos, kind_value, left, right), mask32_(mask32) {
-    ASSERT(mask32 >= 0 && Utils::IsUint(32, mask32));
-    ASSERT((kind_value != Token::kAND) && (kind_value != Token::kOR));
-  }
-
-  // The optional 32-bit mask must be a an unsigned 32-bit value.
-  virtual bool has_mask32() const { return true; }
-  virtual int64_t mask32() const {
-    ASSERT(has_mask32());
-    return mask32_;
-  }
-
-  const char* TokenName() const;
-  DECLARE_COMMON_NODE_FUNCTIONS(BinaryOpWithMask32Node);
-
- private:
-  // Optional unsigned 32 bit mask applied on result. No mask: -1.
-  const int64_t mask32_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(BinaryOpWithMask32Node);
-};
-
-
 class UnaryOpNode : public AstNode {
  public:
   // Returns optimized version, e.g., for ('-' '1') ('-1') literal is returned.
diff --git a/runtime/vm/ast_printer.cc b/runtime/vm/ast_printer.cc
index e438827..eb5dd3b 100644
--- a/runtime/vm/ast_printer.cc
+++ b/runtime/vm/ast_printer.cc
@@ -228,14 +228,6 @@
 }
 
 
-void AstPrinter::VisitBinaryOpWithMask32Node(BinaryOpWithMask32Node* node) {
-  THR_Print("(%s %s ", node->Name(), node->TokenName());
-  node->VisitChildren(this);
-  THR_Print(" & \"0x%" Px64 "", node->mask32());
-  THR_Print("\")");
-}
-
-
 void AstPrinter::VisitUnaryOpNode(UnaryOpNode* node) {
   THR_Print("(%s %s ", node->Name(), node->TokenName());
   node->VisitChildren(this);
diff --git a/runtime/vm/ast_transformer.cc b/runtime/vm/ast_transformer.cc
index a81babb..28861ef 100644
--- a/runtime/vm/ast_transformer.cc
+++ b/runtime/vm/ast_transformer.cc
@@ -298,19 +298,6 @@
 }
 
 
-void AwaitTransformer::VisitBinaryOpWithMask32Node(
-    BinaryOpWithMask32Node* node) {
-  ASSERT((node->kind() != Token::kAND) && (node->kind() != Token::kOR));
-  AstNode* new_left = Transform(node->left());
-  AstNode* new_right = Transform(node->right());
-  result_ = MakeName(new(Z) BinaryOpWithMask32Node(node->token_pos(),
-      node->kind(),
-      new_left,
-      new_right,
-      node->mask32()));
-}
-
-
 void AwaitTransformer::VisitComparisonNode(ComparisonNode* node) {
   AstNode* new_left = Transform(node->left());
   AstNode* new_right = Transform(node->right());
diff --git a/runtime/vm/atomic.h b/runtime/vm/atomic.h
index 026762f..c182a84 100644
--- a/runtime/vm/atomic.h
+++ b/runtime/vm/atomic.h
@@ -65,9 +65,15 @@
 
 }  // namespace dart
 
+#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
+#define USING_SIMULATOR_ATOMICS
+#endif
+
+#if defined(USING_SIMULATOR_ATOMICS)
 // We need to use the simulator to ensure that atomic operations are observed
 // both in C++ and in generated code if the simulator is active.
 #include "vm/atomic_simulator.h"
+#endif
 
 #if defined(TARGET_OS_ANDROID)
 #include "vm/atomic_android.h"
diff --git a/runtime/vm/atomic_android.h b/runtime/vm/atomic_android.h
index b994343..689173a 100644
--- a/runtime/vm/atomic_android.h
+++ b/runtime/vm/atomic_android.h
@@ -41,7 +41,7 @@
 }
 
 
-#if !defined(USING_SIMULATOR)
+#if !defined(USING_SIMULATOR_ATOMICS)
 inline uword AtomicOperations::CompareAndSwapWord(uword* ptr,
                                                   uword old_value,
                                                   uword new_value) {
@@ -54,7 +54,7 @@
                                                        uint32_t new_value) {
   return __sync_val_compare_and_swap(ptr, old_value, new_value);
 }
-#endif  // !defined(USING_SIMULATOR)
+#endif  // !defined(USING_SIMULATOR_ATOMICS)
 
 }  // namespace dart
 
diff --git a/runtime/vm/atomic_linux.h b/runtime/vm/atomic_linux.h
index 615004a..18456cf 100644
--- a/runtime/vm/atomic_linux.h
+++ b/runtime/vm/atomic_linux.h
@@ -27,7 +27,12 @@
 
 
 inline void AtomicOperations::IncrementInt64By(int64_t* p, int64_t value) {
+#if defined(TARGET_ARCH_MIPS)
+  // No double-word atomics on MIPS32.
+  *p += value;
+#else
   __sync_fetch_and_add(p, value);
+#endif
 }
 
 
@@ -41,7 +46,7 @@
 }
 
 
-#if !defined(USING_SIMULATOR)
+#if !defined(USING_SIMULATOR_ATOMICS)
 inline uword AtomicOperations::CompareAndSwapWord(uword* ptr,
                                                   uword old_value,
                                                   uword new_value) {
@@ -54,7 +59,7 @@
                                                        uint32_t new_value) {
   return __sync_val_compare_and_swap(ptr, old_value, new_value);
 }
-#endif  // !defined(USING_SIMULATOR)
+#endif  // !defined(USING_SIMULATOR_ATOMICS)
 
 }  // namespace dart
 
diff --git a/runtime/vm/atomic_macos.h b/runtime/vm/atomic_macos.h
index ae5da3a..479ca30 100644
--- a/runtime/vm/atomic_macos.h
+++ b/runtime/vm/atomic_macos.h
@@ -41,7 +41,7 @@
 }
 
 
-#if !defined(USING_SIMULATOR)
+#if !defined(USING_SIMULATOR_ATOMICS)
 inline uword AtomicOperations::CompareAndSwapWord(uword* ptr,
                                                   uword old_value,
                                                   uword new_value) {
@@ -54,7 +54,7 @@
                                                        uint32_t new_value) {
   return __sync_val_compare_and_swap(ptr, old_value, new_value);
 }
-#endif  // !defined(USING_SIMULATOR)
+#endif  // !defined(USING_SIMULATOR_ATOMICS)
 
 }  // namespace dart
 
diff --git a/runtime/vm/atomic_simulator.h b/runtime/vm/atomic_simulator.h
index 2b52a22..78e7f88 100644
--- a/runtime/vm/atomic_simulator.h
+++ b/runtime/vm/atomic_simulator.h
@@ -11,7 +11,7 @@
 
 namespace dart {
 
-#if defined(USING_SIMULATOR)
+#if defined(USING_SIMULATOR_ATOMICS)
 // Forward atomic operations to the simulator if the simulator is active.
 inline uword AtomicOperations::CompareAndSwapWord(uword* ptr,
                                                   uword old_value,
@@ -25,7 +25,7 @@
                                                        uint32_t new_value) {
   return Simulator::CompareExchangeUint32(ptr, old_value, new_value);
 }
-#endif  // defined(USING_SIMULATOR)
+#endif  // defined(USING_SIMULATOR_ATOMICS)
 
 }  // namespace dart
 
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index 7750375..d4fb651 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -526,8 +526,8 @@
   // Write snapshot with object content.
   FullSnapshotWriter writer(&vm_isolate_snapshot_buffer,
                             &isolate_snapshot_buffer,
-                            NULL, /* instructions_snapshot_buffer */
                             &malloc_allocator,
+                            NULL, /* instructions_writer */
                             false, /* snapshot_code */
                             true /* vm_isolate_is_symbolic */);
   writer.WriteFullSnapshot();
@@ -563,8 +563,8 @@
   // Write snapshot with object content.
   FullSnapshotWriter writer(&vm_isolate_snapshot_buffer,
                             &isolate_snapshot_buffer,
-                            NULL, /* instructions_snapshot_buffer */
                             &malloc_allocator,
+                            NULL, /* instructions_writer */
                             false, /* snapshot_code */
                             true /* vm_isolate_is_symbolic */);
   writer.WriteFullSnapshot();
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 777f1f9..81d46ec 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -45,7 +45,6 @@
   V(Integer_equalToInteger, 2)                                                 \
   V(Integer_fromEnvironment, 3)                                                \
   V(Integer_parse, 1)                                                          \
-  V(Integer_leftShiftWithMask32, 3)                                            \
   V(Bool_fromEnvironment, 3)                                                   \
   V(CapabilityImpl_factory, 1)                                                 \
   V(CapabilityImpl_equals, 2)                                                  \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 1db0305..81cd85c 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -993,13 +993,16 @@
           !(type_arg.Equals(type_param) &&
             instantiated_bound.Equals(declared_bound))) {
         // If type_arg is a type parameter, its declared bound may not be
-        // resolved yet.
+        // finalized yet.
         if (type_arg.IsTypeParameter()) {
           const Class& type_arg_cls = Class::Handle(
               TypeParameter::Cast(type_arg).parameterized_class());
           AbstractType& bound = AbstractType::Handle(
               TypeParameter::Cast(type_arg).bound());
-          ResolveType(type_arg_cls, bound);
+          if (!bound.IsFinalized() && !bound.IsBeingFinalized()) {
+            bound = FinalizeType(type_arg_cls, bound, kCanonicalize);
+            TypeParameter::Cast(type_arg).set_bound(bound);
+          }
         }
         // This may be called only if type needs to be finalized, therefore
         // seems OK to allocate finalized types in old space.
@@ -2516,20 +2519,22 @@
 // values field. We also don't have to generate the code for these getters
 // from thin air (no source code is available).
 void ClassFinalizer::AllocateEnumValues(const Class &enum_cls) {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
   const Field& index_field =
-      Field::Handle(enum_cls.LookupInstanceField(Symbols::Index()));
+      Field::Handle(zone, enum_cls.LookupInstanceField(Symbols::Index()));
   ASSERT(!index_field.IsNull());
   const Field& values_field =
-      Field::Handle(enum_cls.LookupStaticField(Symbols::Values()));
+      Field::Handle(zone, enum_cls.LookupStaticField(Symbols::Values()));
   ASSERT(!values_field.IsNull());
-  ASSERT(Instance::Handle(values_field.StaticValue()).IsArray());
+  ASSERT(Instance::Handle(zone, values_field.StaticValue()).IsArray());
   Array& values_list = Array::Handle(
-      Array::RawCast(values_field.StaticValue()));
+      zone, Array::RawCast(values_field.StaticValue()));
 
-  const Array& fields = Array::Handle(enum_cls.fields());
-  Field& field = Field::Handle();
-  Instance& ordinal_value = Instance::Handle();
-  Instance& enum_value = Instance::Handle();
+  const Array& fields = Array::Handle(zone, enum_cls.fields());
+  Field& field = Field::Handle(zone);
+  Instance& ordinal_value = Instance::Handle(zone);
+  Instance& enum_value = Instance::Handle(zone);
 
   for (intptr_t i = 0; i < fields.Length(); i++) {
     field = Field::RawCast(fields.At(i));
@@ -2542,7 +2547,7 @@
     enum_value = Instance::New(enum_cls, Heap::kOld);
     enum_value.SetField(index_field, ordinal_value);
     const char* error_msg = "";
-    enum_value = enum_value.CheckAndCanonicalize(&error_msg);
+    enum_value = enum_value.CheckAndCanonicalize(thread, &error_msg);
     ASSERT(!enum_value.IsNull());
     ASSERT(enum_value.IsCanonical());
     field.SetStaticValue(enum_value, true);
@@ -2553,7 +2558,7 @@
   }
   values_list.MakeImmutable();
   const char* error_msg = NULL;
-  values_list ^= values_list.CheckAndCanonicalize(&error_msg);
+  values_list ^= values_list.CheckAndCanonicalize(thread, &error_msg);
   ASSERT(!values_list.IsNull());
 }
 
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 1aa9dda..97b8fc8 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -31,16 +31,11 @@
     "Maximum number of subtype cache entries (number of checks cached).");
 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");
 DEFINE_FLAG(int, reoptimization_counter_threshold, 4000,
     "Counter threshold before a function gets reoptimized.");
-DEFINE_FLAG(bool, stop_on_excessive_deoptimization, false,
-    "Debugging: stops program if deoptimizing same function too often");
 DEFINE_FLAG(bool, trace_deoptimization, false, "Trace deoptimization");
 DEFINE_FLAG(bool, trace_deoptimization_verbose, false,
     "Trace deoptimization verbose");
-DEFINE_FLAG(bool, trace_failed_optimization_attempts, false,
-    "Traces all failed optimization attempts");
 DEFINE_FLAG(bool, trace_ic, false, "Trace IC handling");
 DEFINE_FLAG(bool, trace_ic_miss_in_optimized, false,
     "Trace IC miss in optimized code");
@@ -659,6 +654,7 @@
 }
 
 
+#if !defined(TARGET_ARCH_DBC)
 // Gets called from debug stub when code reaches a breakpoint
 // set on a runtime stub call.
 DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) {
@@ -679,6 +675,20 @@
   }
   arguments.SetReturn(orig_stub);
 }
+#else
+// Gets called from the simulator when the breakpoint is reached.
+DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) {
+  if (!FLAG_support_debugger) {
+    UNREACHABLE();
+    return;
+  }
+  const Error& error = Error::Handle(isolate->debugger()->SignalBpReached());
+  if (!error.IsNull()) {
+    Exceptions::PropagateError(error);
+    UNREACHABLE();
+  }
+}
+#endif  // !defined(TARGET_ARCH_DBC)
 
 
 DEFINE_RUNTIME_ENTRY(SingleStepHandler, 0) {
@@ -961,6 +971,8 @@
 //   Arg2: Arguments descriptor array.
 //   Returns: target function to call.
 DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) {
+// DBC does not use megamorphic calls right now.
+#if !defined(TARGET_ARCH_DBC)
   const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
   const Object& ic_data_or_cache = Object::Handle(zone, arguments.ArgAt(1));
   const Array& descriptor = Array::CheckedHandle(zone, arguments.ArgAt(2));
@@ -1018,6 +1030,9 @@
     cache.Insert(class_id, target_function);
   }
   arguments.SetReturn(target_function);
+#else
+  UNREACHABLE();
+#endif  // !defined(TARGET_ARCH_DBC)
 }
 
 
@@ -1195,72 +1210,9 @@
 }
 
 
-static bool CanOptimizeFunction(const Function& function, Thread* thread) {
-  if (FLAG_support_debugger) {
-    Isolate* isolate = thread->isolate();
-    if (isolate->debugger()->IsStepping() ||
-        isolate->debugger()->HasBreakpoint(function, thread->zone())) {
-      // We cannot set breakpoints and single step in optimized code,
-      // so do not optimize the function.
-      function.set_usage_counter(0);
-      return false;
-    }
-  }
-  if (function.deoptimization_counter() >=
-      FLAG_max_deoptimization_counter_threshold) {
-    if (FLAG_trace_failed_optimization_attempts ||
-        FLAG_stop_on_excessive_deoptimization) {
-      THR_Print("Too many deoptimizations: %s\n",
-          function.ToFullyQualifiedCString());
-      if (FLAG_stop_on_excessive_deoptimization) {
-        FATAL("Stop on excessive deoptimization");
-      }
-    }
-    // The function will not be optimized any longer. This situation can occur
-    // mostly with small optimization counter thresholds.
-    function.SetIsOptimizable(false);
-    function.set_usage_counter(INT_MIN);
-    return false;
-  }
-  if (FLAG_optimization_filter != NULL) {
-    // FLAG_optimization_filter is a comma-separated list of strings that are
-    // matched against the fully-qualified function name.
-    char* save_ptr;  // Needed for strtok_r.
-    const char* function_name = function.ToFullyQualifiedCString();
-    intptr_t len = strlen(FLAG_optimization_filter) + 1;  // Length with \0.
-    char* filter = new char[len];
-    strncpy(filter, FLAG_optimization_filter, len);  // strtok modifies arg 1.
-    char* token = strtok_r(filter, ",", &save_ptr);
-    bool found = false;
-    while (token != NULL) {
-      if (strstr(function_name, token) != NULL) {
-        found = true;
-        break;
-      }
-      token = strtok_r(NULL, ",", &save_ptr);
-    }
-    delete[] filter;
-    if (!found) {
-      function.set_usage_counter(INT_MIN);
-      return false;
-    }
-  }
-  if (!function.IsOptimizable()) {
-    // Huge methods (code size above --huge_method_cutoff_in_code_size) become
-    // non-optimizable only after the code has been generated.
-    if (FLAG_trace_failed_optimization_attempts) {
-      THR_Print("Not optimizable: %s\n", function.ToFullyQualifiedCString());
-    }
-    function.set_usage_counter(INT_MIN);
-    return false;
-  }
-  return true;
-}
-
-
 DEFINE_RUNTIME_ENTRY(StackOverflow, 0) {
 #if defined(USING_SIMULATOR)
-  uword stack_pos = Simulator::Current()->get_register(SPREG);
+  uword stack_pos = Simulator::Current()->get_sp();
 #else
   uword stack_pos = Thread::GetCurrentStackPointer();
 #endif
@@ -1272,7 +1224,7 @@
   // If an interrupt happens at the same time as a stack overflow, we
   // process the stack overflow now and leave the interrupt for next
   // time.
-  if (stack_pos < thread->saved_stack_limit()) {
+  if (IsCalleeFrameOf(thread->saved_stack_limit(), stack_pos)) {
     // Use the preallocated stack overflow exception to avoid calling
     // into dart code.
     const Instance& exception =
@@ -1364,7 +1316,8 @@
     ASSERT(function.HasCode());
     // Don't do OSR on intrinsified functions: The intrinsic code expects to be
     // called like a regular function and can't be entered via OSR.
-    if (!CanOptimizeFunction(function, thread) || function.is_intrinsic()) {
+    if (!Compiler::CanOptimizeFunction(thread, function) ||
+        function.is_intrinsic()) {
       return;
     }
 
@@ -1434,7 +1387,7 @@
   ASSERT(!function.IsNull());
   ASSERT(function.HasCode());
 
-  if (CanOptimizeFunction(function, thread)) {
+  if (Compiler::CanOptimizeFunction(thread, function)) {
     if (FLAG_background_compilation) {
       Field& field = Field::Handle(zone, isolate->GetDeoptimizingBoxedField());
       while (!field.IsNull()) {
@@ -1452,6 +1405,9 @@
       if (FLAG_enable_inlining_annotations) {
         FATAL("Cannot enable inlining annotations and background compilation");
       }
+      if (FLAG_background_compilation_stop_alot) {
+        BackgroundCompiler::Stop(isolate);
+      }
       // Reduce the chance of triggering optimization while the function is
       // being optimized in the background. INT_MIN should ensure that it takes
       // long time to trigger optimization.
diff --git a/runtime/vm/code_patcher_dbc.cc b/runtime/vm/code_patcher_dbc.cc
new file mode 100644
index 0000000..e0010ab
--- /dev/null
+++ b/runtime/vm/code_patcher_dbc.cc
@@ -0,0 +1,106 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h"  // Needed here to get TARGET_ARCH_DBC.
+#if defined(TARGET_ARCH_DBC)
+
+#include "vm/code_patcher.h"
+
+#include "vm/flow_graph_compiler.h"
+#include "vm/instructions.h"
+#include "vm/object.h"
+
+namespace dart {
+
+RawCode* CodePatcher::GetStaticCallTargetAt(uword return_address,
+                                            const Code& code) {
+  ASSERT(code.ContainsInstructionAt(return_address));
+  CallPattern call(return_address, code);
+  return call.TargetCode();
+}
+
+
+void CodePatcher::PatchStaticCallAt(uword return_address,
+                                    const Code& code,
+                                    const Code& new_target) {
+  ASSERT(code.ContainsInstructionAt(return_address));
+  CallPattern call(return_address, code);
+  call.SetTargetCode(new_target);
+}
+
+
+void CodePatcher::InsertDeoptimizationCallAt(uword start, uword target) {
+  // The inserted call should not overlap the lazy deopt jump code.
+  ASSERT(start + CallPattern::DeoptCallPatternLengthInBytes() <= target);
+  CallPattern::InsertDeoptCallAt(start, target);
+}
+
+
+RawCode* CodePatcher::GetInstanceCallAt(uword return_address,
+                                        const Code& code,
+                                        ICData* ic_data) {
+  ASSERT(code.ContainsInstructionAt(return_address));
+  CallPattern call(return_address, code);
+  if (ic_data != NULL) {
+    *ic_data = call.IcData();
+  }
+  return call.TargetCode();
+}
+
+
+intptr_t CodePatcher::InstanceCallSizeInBytes() {
+  UNREACHABLE();
+  return 0;
+}
+
+
+RawFunction* CodePatcher::GetUnoptimizedStaticCallAt(
+    uword return_address, const Code& code, ICData* ic_data_result) {
+  ASSERT(code.ContainsInstructionAt(return_address));
+  CallPattern static_call(return_address, code);
+  ICData& ic_data = ICData::Handle();
+  ic_data ^= static_call.IcData();
+  if (ic_data_result != NULL) {
+    *ic_data_result = ic_data.raw();
+  }
+  return ic_data.GetTargetAt(0);
+}
+
+
+void CodePatcher::PatchSwitchableCallAt(uword return_address,
+                                        const Code& code,
+                                        const ICData& ic_data,
+                                        const MegamorphicCache& cache,
+                                        const Code& lookup_stub) {
+  ASSERT(code.ContainsInstructionAt(return_address));
+  SwitchableCallPattern call(return_address, code);
+  ASSERT(call.cache() == ic_data.raw());
+  call.SetLookupStub(lookup_stub);
+  call.SetCache(cache);
+}
+
+
+void CodePatcher::PatchNativeCallAt(uword return_address,
+                                    const Code& code,
+                                    NativeFunction target,
+                                    const Code& trampoline) {
+  ASSERT(code.ContainsInstructionAt(return_address));
+  NativeCallPattern call(return_address, code);
+  call.set_target(trampoline);
+  call.set_native_function(target);
+}
+
+
+RawCode* CodePatcher::GetNativeCallAt(uword return_address,
+                                     const Code& code,
+                                     NativeFunction* target) {
+  ASSERT(code.ContainsInstructionAt(return_address));
+  NativeCallPattern call(return_address, code);
+  *target = call.native_function();
+  return call.target();
+}
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/code_patcher_x64.cc b/runtime/vm/code_patcher_x64.cc
index 2e6ec02..b8863dc 100644
--- a/runtime/vm/code_patcher_x64.cc
+++ b/runtime/vm/code_patcher_x64.cc
@@ -35,6 +35,12 @@
 }
 
 
+intptr_t IndexFromPPLoadDisp8(uword start) {
+  int8_t offset = *reinterpret_cast<int8_t*>(start);
+  return ObjectPool::IndexFromOffset(offset);
+}
+
+
 class UnoptimizedCall : public ValueObject {
  public:
   UnoptimizedCall(uword return_address, const Code& code)
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index fd0e748..55afac1 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -55,6 +55,7 @@
     "How many times we allow deoptimization before we disallow optimization.");
 DEFINE_FLAG(bool, loop_invariant_code_motion, true,
     "Do loop invariant code motion.");
+DEFINE_FLAG(charp, optimization_filter, NULL, "Optimize only named function");
 DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph.");
 DEFINE_FLAG(bool, print_flow_graph_optimized, false,
     "Print the IR flow graph when optimizing.");
@@ -62,7 +63,13 @@
     "Print the deopt-id to ICData map in optimizing compiler.");
 DEFINE_FLAG(bool, print_code_source_map, false, "Print code source map.");
 DEFINE_FLAG(bool, range_analysis, true, "Enable range analysis");
+DEFINE_FLAG(bool, stress_test_background_compilation, false,
+    "Keep background compiler running all the time");
+DEFINE_FLAG(bool, stop_on_excessive_deoptimization, false,
+    "Debugging: stops program if deoptimizing same function too often");
 DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations.");
+DEFINE_FLAG(bool, trace_failed_optimization_attempts, false,
+    "Traces all failed optimization attempts");
 DEFINE_FLAG(bool, trace_optimizing_compiler, false,
     "Trace only optimizing compiler operations.");
 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler.");
@@ -163,6 +170,69 @@
 }
 
 
+bool Compiler::CanOptimizeFunction(Thread* thread, const Function& function) {
+  if (FLAG_support_debugger) {
+    Isolate* isolate = thread->isolate();
+    if (isolate->debugger()->IsStepping() ||
+        isolate->debugger()->HasBreakpoint(function, thread->zone())) {
+      // We cannot set breakpoints and single step in optimized code,
+      // so do not optimize the function.
+      function.set_usage_counter(0);
+      return false;
+    }
+  }
+  if (function.deoptimization_counter() >=
+      FLAG_max_deoptimization_counter_threshold) {
+    if (FLAG_trace_failed_optimization_attempts ||
+        FLAG_stop_on_excessive_deoptimization) {
+      THR_Print("Too many deoptimizations: %s\n",
+          function.ToFullyQualifiedCString());
+      if (FLAG_stop_on_excessive_deoptimization) {
+        FATAL("Stop on excessive deoptimization");
+      }
+    }
+    // The function will not be optimized any longer. This situation can occur
+    // mostly with small optimization counter thresholds.
+    function.SetIsOptimizable(false);
+    function.set_usage_counter(INT_MIN);
+    return false;
+  }
+  if (FLAG_optimization_filter != NULL) {
+    // FLAG_optimization_filter is a comma-separated list of strings that are
+    // matched against the fully-qualified function name.
+    char* save_ptr;  // Needed for strtok_r.
+    const char* function_name = function.ToFullyQualifiedCString();
+    intptr_t len = strlen(FLAG_optimization_filter) + 1;  // Length with \0.
+    char* filter = new char[len];
+    strncpy(filter, FLAG_optimization_filter, len);  // strtok modifies arg 1.
+    char* token = strtok_r(filter, ",", &save_ptr);
+    bool found = false;
+    while (token != NULL) {
+      if (strstr(function_name, token) != NULL) {
+        found = true;
+        break;
+      }
+      token = strtok_r(NULL, ",", &save_ptr);
+    }
+    delete[] filter;
+    if (!found) {
+      function.set_usage_counter(INT_MIN);
+      return false;
+    }
+  }
+  if (!function.IsOptimizable()) {
+    // Huge methods (code size above --huge_method_cutoff_in_code_size) become
+    // non-optimizable only after the code has been generated.
+    if (FLAG_trace_failed_optimization_attempts) {
+      THR_Print("Not optimizable: %s\n", function.ToFullyQualifiedCString());
+    }
+    function.set_usage_counter(INT_MIN);
+    return false;
+  }
+  return true;
+}
+
+
 bool Compiler::IsBackgroundCompilation() {
   // For now: compilation in non mutator thread is the background compoilation.
   return !Thread::Current()->IsMutatorThread();
@@ -403,6 +473,7 @@
   void FinalizeCompilation(Assembler* assembler,
                            FlowGraphCompiler* graph_compiler,
                            FlowGraph* flow_graph);
+  void CheckIfBackgroundCompilerIsBeingStopped();
 
   ParsedFunction* parsed_function_;
   const bool optimized_;
@@ -542,7 +613,8 @@
           THR_Print("--> FAIL: Loading invalidation.");
         }
       }
-      if (code_is_valid) {
+      // Setting breakpoints at runtime could make a function non-optimizable.
+      if (code_is_valid && Compiler::CanOptimizeFunction(thread(), function)) {
         const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
         ASSERT(!is_osr);  // OSR is not compiled in background.
         function.InstallOptimizedCode(code, is_osr);
@@ -595,6 +667,16 @@
 }
 
 
+void CompileParsedFunctionHelper::CheckIfBackgroundCompilerIsBeingStopped() {
+  ASSERT(Compiler::IsBackgroundCompilation());
+  if (!isolate()->background_compiler()->is_running()) {
+    // The background compiler is being stopped.
+    Compiler::AbortBackgroundCompilation(Thread::kNoDeoptId,
+        "Background compilation is being stopped");
+  }
+}
+
+
 // Return false if bailed out.
 // If optimized_result_code is not NULL then it is caller's responsibility
 // to install code.
@@ -1062,20 +1144,20 @@
           // changes code page access permissions (makes them temporary not
           // executable).
           {
+            CheckIfBackgroundCompilerIsBeingStopped();
             SafepointOperationScope safepoint_scope(thread());
             // Do not Garbage collect during this stage and instead allow the
             // heap to grow.
             NoHeapGrowthControlScope no_growth_control;
-            if (!isolate()->background_compiler()->is_running()) {
-              // The background compiler is being stopped.
-              Compiler::AbortBackgroundCompilation(Thread::kNoDeoptId,
-                  "Background compilation is being stopped");
-            }
+            CheckIfBackgroundCompilerIsBeingStopped();
             FinalizeCompilation(&assembler, &graph_compiler, flow_graph);
           }
-          if (isolate()->heap()->NeedsGarbageCollection()) {
-            isolate()->heap()->CollectAllGarbage();
-          }
+          // TODO(srdjan): Enable this and remove the one from
+          // 'BackgroundCompiler::CompileOptimized' once cause of time-outs
+          // is resolved.
+          // if (isolate()->heap()->NeedsGarbageCollection()) {
+          //   isolate()->heap()->CollectAllGarbage();
+          // }
         }
       }
       // Mark that this isolate now has compiled code.
@@ -1586,6 +1668,7 @@
   if (FLAG_trace_compiler) {
     THR_Print("ABORT background compilation: %s\n", msg);
   }
+NOT_IN_PRODUCT(
   TimelineStream* stream = Timeline::GetCompilerStream();
   ASSERT(stream != NULL);
   TimelineEvent* event = stream->StartEvent();
@@ -1595,6 +1678,7 @@
     event->CopyArgument(0, "reason", msg);
     event->Complete();
   }
+)  // !PRODUCT
   ASSERT(Compiler::IsBackgroundCompilation());
   Thread::Current()->long_jump_base()->Jump(
       deopt_id, Object::background_compilation_error());
@@ -1607,7 +1691,6 @@
   explicit QueueElement(const Function& function)
       : next_(NULL),
         function_(function.raw()) {
-    ASSERT(Thread::Current()->IsMutatorThread());
   }
 
   virtual ~QueueElement() {
@@ -1752,7 +1835,7 @@
       { MonitorLocker ml(queue_monitor_);
         function = function_queue()->PeekFunction();
       }
-      while (running_ && !function.IsNull()) {
+      while (running_ && !function.IsNull() && !isolate_->IsTopLevelParsing()) {
         // Check that we have aggregated and cleared the stats.
         ASSERT(thread->compiler_stats()->IsCleared());
         const Error& error = Error::Handle(zone,
@@ -1780,6 +1863,13 @@
             function = Function::null();
           } else {
             qelem = function_queue()->Remove();
+            if (FLAG_stress_test_background_compilation) {
+              const Function& old = Function::Handle(qelem->Function());
+              if (Compiler::CanOptimizeFunction(thread, old)) {
+                QueueElement* repeat_qelem = new QueueElement(old);
+                function_queue()->Add(repeat_qelem);
+              }
+            }
             function = function_queue()->PeekFunction();
           }
         }
@@ -1792,7 +1882,8 @@
     {
       // Wait to be notified when the work queue is not empty.
       MonitorLocker ml(queue_monitor_);
-      while (function_queue()->IsEmpty() && running_) {
+      while ((function_queue()->IsEmpty() || isolate_->IsTopLevelParsing())
+              && running_) {
         ml.Wait();
       }
     }
@@ -1809,14 +1900,21 @@
 
 void BackgroundCompiler::CompileOptimized(const Function& function) {
   ASSERT(Thread::Current()->IsMutatorThread());
-  MonitorLocker ml(queue_monitor_);
-  ASSERT(running_);
-  if (function_queue()->ContainsObj(function)) {
-    return;
+  // TODO(srdjan): Checking different strategy for collecting garbage
+  // accumulated by background compiler.
+  if (isolate_->heap()->NeedsGarbageCollection()) {
+    isolate_->heap()->CollectAllGarbage();
   }
-  QueueElement* elem = new QueueElement(function);
-  function_queue()->Add(elem);
-  ml.Notify();
+  {
+    MonitorLocker ml(queue_monitor_);
+    ASSERT(running_);
+    if (function_queue()->ContainsObj(function)) {
+      return;
+    }
+    QueueElement* elem = new QueueElement(function);
+    function_queue()->Add(elem);
+    ml.Notify();
+  }
 }
 
 
@@ -1827,7 +1925,10 @@
 
 void BackgroundCompiler::Stop(Isolate* isolate) {
   BackgroundCompiler* task = isolate->background_compiler();
-  ASSERT(task != NULL);
+  if (task == NULL) {
+    // Nothing to stop.
+    return;
+  }
   BackgroundCompilationQueue* function_queue = task->function_queue();
 
   Monitor* queue_monitor = task->queue_monitor_;
@@ -1908,6 +2009,11 @@
 
 
 bool Compiler::IsBackgroundCompilation() {
+  return false;
+}
+
+
+bool Compiler::CanOptimizeFunction(Thread* thread, const Function& function) {
   UNREACHABLE();
   return false;
 }
diff --git a/runtime/vm/compiler.h b/runtime/vm/compiler.h
index 2f2eb1c..4e2a550 100644
--- a/runtime/vm/compiler.h
+++ b/runtime/vm/compiler.h
@@ -81,6 +81,8 @@
   static const intptr_t kNoOSRDeoptId = Thread::kNoDeoptId;
 
   static bool IsBackgroundCompilation();
+  // The result for a function may change if debugging gets turned on/off.
+  static bool CanOptimizeFunction(Thread* thread, const Function& function);
 
   // Extracts top level entities from the script and populates
   // the class dictionary of the library.
@@ -146,8 +148,7 @@
   // because the mutator thread changed the state (e.g., deoptimization,
   // deferred loading). The background compilation may retry to compile
   // the same function later.
-  static void AbortBackgroundCompilation(intptr_t deopt_id,
-                                         const char* msg = "");
+  static void AbortBackgroundCompilation(intptr_t deopt_id, const char* msg);
 };
 
 
diff --git a/runtime/vm/constant_propagator.cc b/runtime/vm/constant_propagator.cc
index b8e7c2a..0b8d617 100644
--- a/runtime/vm/constant_propagator.cc
+++ b/runtime/vm/constant_propagator.cc
@@ -533,6 +533,7 @@
 
 
 void ConstantPropagator::VisitTestCids(TestCidsInstr* instr) {
+  // TODO(sra): Constant fold test.
   SetValue(instr, non_constant_);
 }
 
diff --git a/runtime/vm/constants_dbc.h b/runtime/vm/constants_dbc.h
new file mode 100644
index 0000000..4eb7b1b
--- /dev/null
+++ b/runtime/vm/constants_dbc.h
@@ -0,0 +1,494 @@
+// 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.
+
+#ifndef VM_CONSTANTS_DBC_H_
+#define VM_CONSTANTS_DBC_H_
+
+#include "platform/globals.h"
+#include "platform/assert.h"
+#include "platform/utils.h"
+
+
+namespace dart {
+
+// List of Dart Bytecode instructions.
+//
+// INTERPRETER STATE
+//
+//      current frame info (see stack_frame_dbc.h for layout)
+//        v-----^-----v
+//   ~----+----~ ~----+-------+-------+-~ ~-+-------+-------+-~
+//   ~    |    ~ ~    | FP[0] | FP[1] | ~ ~ | SP[-1]| SP[0] |
+//   ~----+----~ ~----+-------+-------+-~ ~-+-------+-------+-~
+//                    ^                             ^
+//                    FP                            SP
+//
+//
+// The state of execution is captured in few interpreter registers:
+//
+//   FP - base of the current frame
+//   SP - top of the stack (TOS) for the current frame
+//   PP - object pool for the currently execution function
+//
+// Frame info stored below FP additionally contains pointers to the currently
+// executing function and code (see stack_frame_dbc.h for more information).
+//
+// In the unoptimized code most of bytecodes take operands implicitly from
+// stack and store results again on the stack. Constant operands are usually
+// taken from the object pool by index.
+//
+// ENCODING
+//
+// Each instruction is a 32-bit integer with opcode stored in the least
+// significant byte. The following operand encodings are used:
+//
+//   0........8.......16.......24.......32
+//   +--------+--------+--------+--------+
+//   | opcode |~~~~~~~~~~~~~~~~~~~~~~~~~~|   0: no operands
+//   +--------+--------+--------+--------+
+//
+//   +--------+--------+--------+--------+
+//   | opcode |    A   |~~~~~~~~~~~~~~~~~|   A: single unsigned 8-bit operand
+//   +--------+--------+--------+--------+
+//
+//   +--------+--------+--------+--------+
+//   | opcode |    A   |        D        | A_D: unsigned 8-bit operand and
+//   +--------+--------+--------+--------+      unsigned 16-bit operand
+//
+//   +--------+--------+--------+--------+
+//   | opcode |    A   |        X        | A_X: unsigned 8-bit operand and
+//   +--------+--------+--------+--------+      signed 16-bit operand
+//
+//   +--------+--------+--------+--------+
+//   | opcode |~~~~~~~~|        D        |   D: unsigned 16-bit operand
+//   +--------+--------+--------+--------+
+//
+//   +--------+--------+--------+--------+
+//   | opcode |~~~~~~~~|        X        |   X: signed 16-bit operand
+//   +--------+--------+--------+--------+
+//
+//   +--------+--------+--------+--------+
+//   | opcode |    A   |    B   |    C   | A_B_C: 3 unsigned 8-bit operands
+//   +--------+--------+--------+--------+
+//
+//   +--------+--------+--------+--------+
+//   | opcode |             T            |   T: signed 24-bit operand
+//   +--------+--------+--------+--------+
+//
+//
+// INSTRUCTIONS
+//
+//  - Trap
+//
+//    Unreachable instruction.
+//
+//  - Compile
+//
+//    Compile current function and start executing newly produced code
+//    (used to implement LazyCompileStub);
+//
+//  - Intrinsic id
+//
+//    Execute intrinsic with the given id. If intrinsic returns true then
+//    return from the current function to the caller passing value produced
+//    by the intrinsic as a result;
+//
+//  - Drop1; DropR n; Drop n
+//
+//    Drop 1 or n values from the stack, if instruction is DropR push the first
+//    dropped value to the stack;
+//
+//  - Jump target
+//
+//    Jump to the given target. Target is specified as offset from the PC of the
+//    jump instruction.
+//
+//  - Return R; ReturnTOS
+//
+//    Return to the caller using either a value from the given register or a
+//    value from the top-of-stack as a result.
+//
+//    Note: return instruction knows how many arguments to remove from the
+//    stack because it can look at the call instruction at caller's PC and
+//    take argument count from it.
+//
+//  - Move rA, rX
+//
+//    FP[rA] <- FP[rX]
+//    Note: rX is signed so it can be used to address parameters which are
+//    at negative indices with respect to FP.
+//
+//  - Push rX
+//
+//    Push FP[rX] to the stack.
+//
+//  - LoadConstant rA, D; PushConstant D
+//
+//    Load value at index D from constant pool into FP[rA] or push it onto the
+//    stack.
+//
+//  - StoreLocal rX; PopLocal rX
+//
+//    Store top of the stack into FP[rX] and pop it if needed.
+//
+//  - StaticCall ArgC, D
+//
+//    Invoke function in SP[0] with arguments SP[-(1+ArgC)], ..., SP[-1] and
+//    argument descriptor PP[D].
+//
+//  - InstanceCall ArgC, D; InstanceCall2 ArgC, D; InstanceCall3 ArgC, D
+//
+//    Lookup and invoke method using ICData in PP[D] with arguments
+//    SP[-(1+ArgC)], ..., SP[-1].
+//
+//  - NativeCall, NativeBootstrapCall
+//
+//    Invoke native function SP[-1] with argc_tag SP[0].
+//
+//  - AddTOS; SubTOS; MulTOS; BitOrTOS; BitAndTOS; EqualTOS; LessThanTOS;
+//    GreaterThanTOS;
+//
+//    Smi fast-path for a corresponding method. Checks if SP[0] and SP[-1] are
+//    both smis and result of SP[0] <op> SP[-1] is a smi - if this is true
+//    then pops operands and pushes result on the stack and skips the next
+//    instruction (which implements a slow path fallback).
+//
+//  - StoreStaticTOS D
+//
+//    Stores TOS into the static field PP[D].
+//
+//  - PushStatic
+//
+//    Pushes value of the static field PP[D] on to the stack.
+//
+//  - InitStaticTOS
+//
+//    Takes static field from TOS and ensures that it is initialized.
+//
+//  - IfNeStrictTOS; IfEqStrictTOS; IfNeStrictNumTOS; IfEqStrictNumTOS
+//
+//    Skips the next instruction unless the given condition holds. 'Num'
+//    variants perform number check while non-Num variants just compare
+//    RawObject pointers.
+//
+//    Used to implement conditional jump:
+//
+//        IfNeStrictTOS
+//        Jump T         ;; jump if not equal
+//
+//  - CreateArrayTOS
+//
+//    Allocate array of length SP[0] with type arguments SP[-1].
+//
+//  - Allocate D
+//
+//    Allocate object of class PP[D] with no type arguments.
+//
+//  - AllocateT
+//
+//    Allocate object of class SP[0] with type arguments SP[-1].
+//
+//  - StoreIndexedTOS
+//
+//    Store SP[0] into array SP[-2] at index SP[-1]. No typechecking is done.
+//    SP[-2] is assumed to be a RawArray, SP[-1] to be a smi.
+//
+//  - StoreField rA, B, rC
+//
+//    Store value FP[rC] into object FP[rA] at offset (in words) B.
+//
+//  - StoreFieldTOS D
+//
+//    Store value SP[0] into object SP[-1] at offset (in words) D.
+//
+//  - LoadField rA, rB, C
+//
+//    Load value at offset (in words) C from object FP[rB] into FP[rA].
+//
+//  - LoadFieldTOS D
+//
+//    Push value at offset (in words) D from object SP[0].
+//
+//  - BooleanNegateTOS
+//
+//    SP[0] = !SP[0]
+//
+//  - Throw A
+//
+//    Throw (Rethrow if A != 0) exception. Exception object and stack object
+//    are taken from TOS.
+//
+//  - Entry A, B, rC
+//
+//    Function prologue for the function with no optional or named arguments:
+//        A - expected number of positional arguments;
+//        B - number of local slots to reserve;
+//        rC - specifies context register to initialize with empty context.
+//
+//  - EntryOpt A, B, C
+//
+//    Function prologue for the function with optional or named arguments:
+//        A - expected number of positional arguments;
+//        B - number of optional arguments;
+//        C - number of named arguments;
+//
+//    Only one of B and C can be not 0.
+//
+//    If B is not 0 then EntryOpt bytecode is followed by B LoadConstant
+//    bytecodes specifying default values for optional arguments.
+//
+//    If C is not 0 then EntryOpt is followed by 2 * B LoadConstant bytecodes.
+//    Bytecode at 2 * i specifies name of the i-th named argument and at
+//    2 * i + 1 default value. rA part of the LoadConstant bytecode specifies
+//    the location of the parameter on the stack. Here named arguments are
+//    sorted alphabetically to enable linear matching similar to how function
+//    prologues are implemented on other architectures.
+//
+//    Note: Unlike Entry bytecode EntryOpt does not setup the frame for
+//    local variables this is done by a separate bytecode Frame.
+//
+//  - Frame D
+//
+//    Reserve and initialize with null space for D local variables.
+//
+//  - SetFrame A
+//
+//    Reinitialize SP assuming that current frame has size A.
+//    Used to drop temporaries from the stack in the exception handler.
+//
+//  - AllocateContext D
+//
+//    Allocate Context object assuming for D context variables.
+//
+//  - CloneContext
+//
+//    Clone context stored in TOS.
+//
+//  - MoveSpecial rA, D
+//
+//    Copy special values from inside interpreter to FP[rA]. Currently only
+//    used to pass exception object (D = 0) and stack trace object (D = 1) to
+//    catch handler.
+//
+//  - InstantiateType D
+//
+//    Instantiate type PP[D] with instantiator type arguments SP[0].
+//
+//  - InstantiateTypeArgumentsTOS D
+//
+//    Instantiate type arguments PP[D] with instantiator SP[0].
+//
+//  - AssertAssignable D
+//
+//    Assert that SP[-3] is assignable to variable named SP[0] of type
+//    SP[-1] with type arguments SP[-2] using SubtypeTestCache PP[D].
+//
+//  - AssertBoolean A
+//
+//    Assert that TOS is a boolean (A = 1) or that TOS is not null (A = 0).
+//
+//  - CheckStack
+//
+//    Compare SP against isolate stack limit and call StackOverflow handler if
+//    necessary.
+//
+//  - DebugStep, DebugBreak A
+//
+//    Debugger support. DebugBreak is bytecode that can be patched into the
+//    instruction stream to trigger in place breakpoint.
+//
+//    When patching instance or static call with DebugBreak we set A to
+//    match patched call's argument count so that Return instructions continue
+//    to work.
+//
+// TODO(vegorov) the way we replace calls with DebugBreak does not work
+//               with our smi fast paths because DebugBreak is simply skipped.
+//
+// BYTECODE LIST FORMAT
+//
+// Bytecode list below is specified using the following format:
+//
+//     V(BytecodeName, OperandForm, Op1, Op2, Op3)
+//
+// - OperandForm specifies operand encoding and should be one of 0, A, T, A_D,
+//   A_X, X, D (see ENCODING section above).
+//
+// - Op1, Op2, Op2 specify operand meaning. Possible values:
+//
+//     ___ ignored / non-existent operand
+//     num immediate operand
+//     lit constant literal from object pool
+//     reg register (unsigned FP relative local)
+//     xeg x-register (signed FP relative local)
+//     tgt jump target relative to the PC of the current instruction
+//
+// TODO(vegorov) jump targets should be encoded relative to PC of the next
+//               instruction because PC is incremeted immediately after fetch
+//               and before decoding.
+//
+#define BYTECODES_LIST(V)                              \
+  V(Trap,                            0, ___, ___, ___) \
+  V(Compile,                         0, ___, ___, ___) \
+  V(Intrinsic,                       A, num, ___, ___) \
+  V(Drop1,                           0, ___, ___, ___) \
+  V(DropR,                           A, num, ___, ___) \
+  V(Drop,                            A, num, ___, ___) \
+  V(Jump,                            T, tgt, ___, ___) \
+  V(Return,                          A, num, ___, ___) \
+  V(ReturnTOS,                       0, ___, ___, ___) \
+  V(Move,                          A_X, reg, xeg, ___) \
+  V(Push,                            X, xeg, ___, ___) \
+  V(LoadConstant,                  A_D, reg, lit, ___) \
+  V(PushConstant,                    D, lit, ___, ___) \
+  V(StoreLocal,                      X, xeg, ___, ___) \
+  V(PopLocal,                        X, xeg, ___, ___) \
+  V(StaticCall,                    A_D, num, num, ___) \
+  V(InstanceCall,                  A_D, num, num, ___) \
+  V(InstanceCall2,                 A_D, num, num, ___) \
+  V(InstanceCall3,                 A_D, num, num, ___) \
+  V(NativeCall,                      0, ___, ___, ___) \
+  V(NativeBootstrapCall,             0, ___, ___, ___) \
+  V(AddTOS,                          0, ___, ___, ___) \
+  V(SubTOS,                          0, ___, ___, ___) \
+  V(MulTOS,                          0, ___, ___, ___) \
+  V(BitOrTOS,                        0, ___, ___, ___) \
+  V(BitAndTOS,                       0, ___, ___, ___) \
+  V(EqualTOS,                        0, ___, ___, ___) \
+  V(LessThanTOS,                     0, ___, ___, ___) \
+  V(GreaterThanTOS,                  0, ___, ___, ___) \
+  V(StoreStaticTOS,                  D, lit, ___, ___) \
+  V(PushStatic,                      D, lit, ___, ___) \
+  V(InitStaticTOS,                   0, ___, ___, ___) \
+  V(IfNeStrictTOS,                   0, ___, ___, ___) \
+  V(IfEqStrictTOS,                   0, ___, ___, ___) \
+  V(IfNeStrictNumTOS,                0, ___, ___, ___) \
+  V(IfEqStrictNumTOS,                0, ___, ___, ___) \
+  V(CreateArrayTOS,                  0, ___, ___, ___) \
+  V(Allocate,                        D, lit, ___, ___) \
+  V(AllocateT,                       0, ___, ___, ___) \
+  V(StoreIndexedTOS,                 0, ___, ___, ___) \
+  V(StoreField,                  A_B_C, reg, reg, reg) \
+  V(StoreFieldTOS,                   D, num, ___, ___) \
+  V(LoadField,                   A_B_C, reg, reg, reg) \
+  V(LoadFieldTOS,                    D, num, ___, ___) \
+  V(BooleanNegateTOS,                0, ___, ___, ___) \
+  V(Throw,                           A, num, ___, ___) \
+  V(Entry,                       A_B_C, num, num, num) \
+  V(EntryOpt,                    A_B_C, num, num, num) \
+  V(Frame,                           D, num, ___, ___) \
+  V(SetFrame,                        A, num, ___, num) \
+  V(AllocateContext,                 D, num, ___, ___) \
+  V(CloneContext,                    0, ___, ___, ___) \
+  V(MoveSpecial,                   A_D, reg, num, ___) \
+  V(InstantiateType,                 D, lit, ___, ___) \
+  V(InstantiateTypeArgumentsTOS,   A_D, num, lit, ___) \
+  V(AssertAssignable,                D, num, lit, ___) \
+  V(AssertBoolean,                   A, num, ___, ___) \
+  V(CheckStack,                      0, ___, ___, ___) \
+  V(DebugStep,                       0, ___, ___, ___) \
+  V(DebugBreak,                      A, num, ___, ___) \
+
+typedef uint32_t Instr;
+
+class Bytecode {
+ public:
+  enum Opcode {
+#define DECLARE_BYTECODE(name, encoding, op1, op2, op3) k##name,
+BYTECODES_LIST(DECLARE_BYTECODE)
+#undef DECLARE_BYTECODE
+  };
+
+  static const intptr_t kOpShift = 0;
+  static const intptr_t kAShift = 8;
+  static const intptr_t kAMask = 0xFF;
+  static const intptr_t kBShift = 16;
+  static const intptr_t kBMask = 0xFF;
+  static const intptr_t kCShift = 24;
+  static const intptr_t kCMask = 0xFF;
+  static const intptr_t kDShift = 16;
+  static const intptr_t kDMask = 0xFFFF;
+
+  static Instr Encode(Opcode op, uintptr_t a, uintptr_t b, uintptr_t c) {
+    ASSERT((a & kAMask) == a);
+    ASSERT((b & kBMask) == b);
+    ASSERT((c & kCMask) == c);
+    return op | (a << kAShift) | (b << kBShift) | (c << kCShift);
+  }
+
+  static Instr Encode(Opcode op, uintptr_t a, uintptr_t d) {
+    ASSERT((a & kAMask) == a);
+    ASSERT((d & kDMask) == d);
+    return op | (a << kAShift) | (d << kDShift);
+  }
+
+  static Instr EncodeSigned(Opcode op, uintptr_t a, intptr_t x) {
+    ASSERT((a & kAMask) == a);
+    ASSERT((x << kDShift) >> kDShift == x);
+    return op | (a << kAShift) | (x << kDShift);
+  }
+
+  static Instr EncodeSigned(Opcode op, intptr_t x) {
+    ASSERT((x << kAShift) >> kAShift == x);
+    return op | (x << kAShift);
+  }
+
+  static Instr Encode(Opcode op) {
+    return op;
+  }
+
+  DART_FORCE_INLINE static uint8_t DecodeA(Instr bc) {
+    return (bc >> kAShift) & kAMask;
+  }
+
+  DART_FORCE_INLINE static uint16_t DecodeD(Instr bc) {
+    return (bc >> kDShift) & kDMask;
+  }
+
+  DART_FORCE_INLINE static Opcode DecodeOpcode(Instr bc) {
+    return static_cast<Opcode>(bc & 0xFF);
+  }
+
+  DART_FORCE_INLINE static uint8_t DecodeArgc(Instr call) {
+#if defined(DEBUG)
+    const Opcode op = DecodeOpcode(call);
+    ASSERT((op == Bytecode::kStaticCall) ||
+           (op == Bytecode::kInstanceCall) ||
+           (op == Bytecode::kInstanceCall2) ||
+           (op == Bytecode::kInstanceCall3) ||
+           (op == Bytecode::kDebugBreak));
+#endif
+    return (call >> 8) & 0xFF;
+  }
+};
+
+// Various dummy declarations to make shared code compile.
+// TODO(vegorov) we need to prune away as much dead code as possible instead
+// of just making it compile.
+typedef int16_t Register;
+
+const int16_t FPREG = 0;
+const int16_t SPREG = 1;
+const intptr_t kNumberOfCpuRegisters = 20;
+const intptr_t kDartAvailableCpuRegs = 0;
+const intptr_t kNoRegister = -1;
+const intptr_t kReservedCpuRegisters = 0;
+const intptr_t ARGS_DESC_REG = 0;
+const intptr_t CODE_REG = 0;
+const intptr_t kExceptionObjectReg = 0;
+const intptr_t kStackTraceObjectReg = 0;
+const intptr_t CTX = 0;
+
+enum FpuRegister {
+  kNoFpuRegister = -1,
+  kFakeFpuRegister,
+  kNumberOfDummyFpuRegisters,
+};
+const FpuRegister FpuTMP = kFakeFpuRegister;
+const intptr_t kNumberOfFpuRegisters = 1;
+
+enum Condition { EQ, NE };
+
+}  // namespace dart
+
+#endif  // VM_CONSTANTS_DBC_H_
diff --git a/runtime/vm/cpu.h b/runtime/vm/cpu.h
index 2fffb25..3b93489 100644
--- a/runtime/vm/cpu.h
+++ b/runtime/vm/cpu.h
@@ -33,6 +33,8 @@
 #include "vm/cpu_arm64.h"
 #elif defined(TARGET_ARCH_MIPS)
 #include "vm/cpu_mips.h"
+#elif defined(TARGET_ARCH_DBC)
+#include "vm/cpu_dbc.h"
 #else
 #error Unknown architecture.
 #endif
diff --git a/runtime/vm/cpu_dbc.cc b/runtime/vm/cpu_dbc.cc
new file mode 100644
index 0000000..8fcff5b
--- /dev/null
+++ b/runtime/vm/cpu_dbc.cc
@@ -0,0 +1,26 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h"
+#if defined(TARGET_ARCH_DBC)
+
+#include "vm/cpu.h"
+
+
+namespace dart {
+
+
+void CPU::FlushICache(uword start, uword size) {
+  // Nothing to do.
+}
+
+
+const char* CPU::Id() {
+  return "dbc";
+}
+
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/cpu_dbc.h b/runtime/vm/cpu_dbc.h
new file mode 100644
index 0000000..b437beb
--- /dev/null
+++ b/runtime/vm/cpu_dbc.h
@@ -0,0 +1,30 @@
+// 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.
+
+#ifndef VM_CPU_DBC_H_
+#define VM_CPU_DBC_H_
+
+#include "vm/allocation.h"
+#include "vm/simulator.h"
+
+namespace dart {
+
+class HostCPUFeatures: public AllStatic {
+ public:
+  static const char* hardware() { return "simdbc"; }
+};
+
+class TargetCPUFeatures : public AllStatic {
+ public:
+  static void InitOnce() {}
+  static void Cleanup() {}
+
+  static bool double_truncate_round_supported() {
+    return true;
+  }
+};
+
+}  // namespace dart
+
+#endif  // VM_CPU_DBC_H_
diff --git a/runtime/vm/cpu_test.cc b/runtime/vm/cpu_test.cc
index 6ccdebe..7ffbe6f 100644
--- a/runtime/vm/cpu_test.cc
+++ b/runtime/vm/cpu_test.cc
@@ -32,6 +32,8 @@
 #else  // defined(HOST_ARCH_MIPS)
   EXPECT_STREQ("simmips", CPU::Id());
 #endif  // defined(HOST_ARCH_MIPS)
+#elif defined(TARGET_ARCH_DBC)
+  EXPECT_STREQ("dbc", CPU::Id());
 #else
 #error Architecture was not detected as supported by Dart.
 #endif
diff --git a/runtime/vm/cpuinfo_test.cc b/runtime/vm/cpuinfo_test.cc
index 0b6113b..2b587f1 100644
--- a/runtime/vm/cpuinfo_test.cc
+++ b/runtime/vm/cpuinfo_test.cc
@@ -9,11 +9,13 @@
 
 namespace dart {
 
+#if !defined(TARGET_ARCH_DBC)
 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));
 }
+#endif
 
 }  // namespace dart
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 0041d9a..d005cee 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -80,6 +80,40 @@
 };
 
 
+static void CheckOffsets() {
+#define CHECK_OFFSET(expr, offset)                                             \
+  if ((expr) != (offset)) {                                                    \
+    FATAL2("%s == %" Pd, #expr, (expr));                                       \
+  }                                                                            \
+
+#if defined(TARGET_ARCH_ARM)
+  // These offsets are embedded in precompiled instructions. We need simarm
+  // (compiler) and arm (runtime) to agree.
+  CHECK_OFFSET(Heap::TopOffset(Heap::kNew), 8);
+  CHECK_OFFSET(Isolate::heap_offset(), 8);
+  CHECK_OFFSET(Thread::stack_limit_offset(), 4);
+  CHECK_OFFSET(Thread::object_null_offset(), 36);
+#endif
+#if defined(TARGET_ARCH_MIPS)
+  // These offsets are embedded in precompiled instructions. We need simmips
+  // (compiler) and mips (runtime) to agree.
+  CHECK_OFFSET(Heap::TopOffset(Heap::kNew), 8);
+  CHECK_OFFSET(Isolate::heap_offset(), 8);
+  CHECK_OFFSET(Thread::stack_limit_offset(), 4);
+  CHECK_OFFSET(Thread::object_null_offset(), 36);
+#endif
+#if defined(TARGET_ARCH_ARM64)
+  // These offsets are embedded in precompiled instructions. We need simarm64
+  // (compiler) and arm64 (runtime) to agree.
+  CHECK_OFFSET(Heap::TopOffset(Heap::kNew), 8);
+  CHECK_OFFSET(Isolate::heap_offset(), 16);
+  CHECK_OFFSET(Thread::stack_limit_offset(), 8);
+  CHECK_OFFSET(Thread::object_null_offset(), 72);
+#endif
+#undef CHECK_OFFSET
+}
+
+
 const char* Dart::InitOnce(const uint8_t* vm_isolate_snapshot,
                            const uint8_t* instructions_snapshot,
                            const uint8_t* data_snapshot,
@@ -92,10 +126,20 @@
                            Dart_FileCloseCallback file_close,
                            Dart_EntropySource entropy_source,
                            Dart_GetVMServiceAssetsArchive get_service_assets) {
+  CheckOffsets();
   // TODO(iposva): Fix race condition here.
   if (vm_isolate_ != NULL || !Flags::Initialized()) {
     return "VM already initialized or flags not initialized.";
   }
+#if defined(DART_PRECOMPILED_RUNTIME)
+  if (instructions_snapshot == NULL) {
+    return "Precompiled runtime requires a precompiled snapshot";
+  }
+#else
+  if (instructions_snapshot != NULL) {
+    return "JIT runtime cannot run a precompiled snapshot";
+  }
+#endif
   set_thread_exit_callback(thread_exit);
   SetFileCallbacks(file_open, file_read, file_write, file_close);
   set_entropy_source_callback(entropy_source);
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index e8c31a9..c0a2fc5 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1495,8 +1495,8 @@
 
   FullSnapshotWriter writer(vm_isolate_snapshot_buffer,
                             isolate_snapshot_buffer,
-                            NULL, /* instructions_snapshot_buffer */
                             ApiReallocate,
+                            NULL, /* instructions_writer */
                             false, /* snapshot_code */
                             true /* vm_isolate_is_symbolic */);
   writer.WriteFullSnapshot();
@@ -2152,7 +2152,6 @@
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
   CHECK_ISOLATE(isolate);
-  API_TIMELINE_DURATION;
   if (Api::IsSmi(integer)) {
     *value = Api::SmiValue(integer);
     return Api::Success();
@@ -2181,7 +2180,6 @@
 
 DART_EXPORT Dart_Handle Dart_IntegerToUint64(Dart_Handle integer,
                                              uint64_t* value) {
-  API_TIMELINE_DURATION;
   // Fast path for Smis.
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
@@ -2241,7 +2239,6 @@
 
 
 DART_EXPORT Dart_Handle Dart_NewDouble(double value) {
-  API_TIMELINE_DURATION;
   DARTSCOPE(Thread::Current());
   CHECK_CALLBACK_STATE(T);
   return Api::NewHandle(T, Double::New(value));
@@ -2250,7 +2247,6 @@
 
 DART_EXPORT Dart_Handle Dart_DoubleValue(Dart_Handle double_obj,
                                          double* value) {
-  API_TIMELINE_DURATION;
   DARTSCOPE(Thread::Current());
   const Double& obj = Api::UnwrapDoubleHandle(Z, double_obj);
   if (obj.IsNull()) {
@@ -4823,7 +4819,6 @@
 
 DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args,
                                                int index) {
-  API_TIMELINE_DURATION;
   NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
   if ((index < 0) || (index >= arguments->NativeArgCount())) {
     return Api::NewError(
@@ -4836,7 +4831,6 @@
 
 
 DART_EXPORT int Dart_GetNativeArgumentCount(Dart_NativeArguments args) {
-  API_TIMELINE_DURATION;
   NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
   return arguments->NativeArgCount();
 }
@@ -4895,7 +4889,6 @@
 DART_EXPORT Dart_Handle Dart_GetNativeIntegerArgument(Dart_NativeArguments args,
                                                       int index,
                                                       int64_t* value) {
-  API_TIMELINE_DURATION;
   NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
   if ((index < 0) || (index >= arguments->NativeArgCount())) {
     return Api::NewError(
@@ -4913,7 +4906,6 @@
 DART_EXPORT Dart_Handle Dart_GetNativeBooleanArgument(Dart_NativeArguments args,
                                                       int index,
                                                       bool* value) {
-  API_TIMELINE_DURATION;
   NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
   if ((index < 0) || (index >= arguments->NativeArgCount())) {
     return Api::NewError(
@@ -4931,7 +4923,6 @@
 DART_EXPORT Dart_Handle Dart_GetNativeDoubleArgument(Dart_NativeArguments args,
                                                      int index,
                                                      double* value) {
-  API_TIMELINE_DURATION;
   NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
   if ((index < 0) || (index >= arguments->NativeArgCount())) {
     return Api::NewError(
@@ -5056,7 +5047,6 @@
 // --- Scripts and Libraries ---
 DART_EXPORT void Dart_SetBooleanReturnValue(Dart_NativeArguments args,
                                             bool retval) {
-  API_TIMELINE_DURATION;
   NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
   arguments->SetReturn(Bool::Get(retval));
 }
@@ -5204,11 +5194,20 @@
   CHECK_COMPILATION_ALLOWED(I);
 
   ASSERT(snapshot->kind() == Snapshot::kScript);
+  NOT_IN_PRODUCT(TimelineDurationScope tds2(T,
+      Timeline::GetIsolateStream(), "ScriptSnapshotReader"));
+
   ScriptSnapshotReader reader(snapshot->content(), snapshot->length(), T);
   const Object& tmp = Object::Handle(Z, reader.ReadScriptSnapshot());
   if (tmp.IsError()) {
     return Api::NewHandle(T, tmp.raw());
   }
+  NOT_IN_PRODUCT(if (tds2.enabled()) {
+    tds2.SetNumArguments(2);
+    tds2.FormatArgument(0, "snapshotSize", "%" Pd, snapshot->length());
+    tds2.FormatArgument(1, "heapSize", "%" Pd64,
+                        I->heap()->UsedInWords(Heap::kOld) * kWordSize);
+  });
   library ^= tmp.raw();
   library.set_debuggable(true);
   I->object_store()->set_root_library(library);
@@ -5976,6 +5975,7 @@
   if (event == NULL) {
     return;
   }
+  label = strdup(label);
   switch (type) {
     case Dart_Timeline_Event_Begin:
       event->Begin(label, timestamp0);
@@ -6004,6 +6004,7 @@
     default:
       FATAL("Unknown Dart_Timeline_Event_Type");
   }
+  event->set_owns_label(true);
   event->SetNumArguments(argument_count);
   for (intptr_t i = 0; i < argument_count; i++) {
     event->CopyArgument(i, argument_names[i], argument_values[i]);
@@ -6034,13 +6035,27 @@
 }
 
 
-DART_EXPORT Dart_Handle Dart_CreatePrecompiledSnapshot(
+DART_EXPORT Dart_Handle Dart_CreatePrecompiledSnapshotAssembly(
     uint8_t** vm_isolate_snapshot_buffer,
     intptr_t* vm_isolate_snapshot_size,
     uint8_t** isolate_snapshot_buffer,
     intptr_t* isolate_snapshot_size,
-    uint8_t** instructions_snapshot_buffer,
-    intptr_t* instructions_snapshot_size) {
+    uint8_t** assembly_buffer,
+    intptr_t* assembly_size) {
+  UNREACHABLE();
+  return 0;
+}
+
+
+DART_EXPORT Dart_Handle Dart_CreatePrecompiledSnapshotBlob(
+    uint8_t** vm_isolate_snapshot_buffer,
+    intptr_t* vm_isolate_snapshot_size,
+    uint8_t** isolate_snapshot_buffer,
+    intptr_t* isolate_snapshot_size,
+    uint8_t** instructions_blob_buffer,
+    intptr_t* instructions_blob_size,
+    uint8_t** rodata_blob_buffer,
+    intptr_t* rodata_blob_size) {
   UNREACHABLE();
   return 0;
 }
@@ -6069,13 +6084,13 @@
 }
 
 
-DART_EXPORT Dart_Handle Dart_CreatePrecompiledSnapshot(
+DART_EXPORT Dart_Handle Dart_CreatePrecompiledSnapshotAssembly(
     uint8_t** vm_isolate_snapshot_buffer,
     intptr_t* vm_isolate_snapshot_size,
     uint8_t** isolate_snapshot_buffer,
     intptr_t* isolate_snapshot_size,
-    uint8_t** instructions_snapshot_buffer,
-    intptr_t* instructions_snapshot_size) {
+    uint8_t** assembly_buffer,
+    intptr_t* assembly_size) {
   ASSERT(FLAG_load_deferred_eagerly);
   API_TIMELINE_DURATION;
   DARTSCOPE(Thread::Current());
@@ -6096,26 +6111,84 @@
   if (isolate_snapshot_size == NULL) {
     RETURN_NULL_ERROR(isolate_snapshot_size);
   }
-  if (instructions_snapshot_buffer == NULL) {
-    RETURN_NULL_ERROR(instructions_snapshot_buffer);
+  if (assembly_buffer == NULL) {
+    RETURN_NULL_ERROR(assembly_buffer);
   }
-  if (instructions_snapshot_size == NULL) {
-    RETURN_NULL_ERROR(instructions_snapshot_size);
-  }
-  // Finalize all classes if needed.
-  Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
-  if (::Dart_IsError(state)) {
-    return state;
+  if (assembly_size == NULL) {
+    RETURN_NULL_ERROR(assembly_size);
   }
   I->heap()->CollectAllGarbage();
+  AssemblyInstructionsWriter instructions_writer(assembly_buffer,
+                                                 ApiReallocate,
+                                                 2 * MB /* initial_size */);
   PrecompiledSnapshotWriter writer(vm_isolate_snapshot_buffer,
                                    isolate_snapshot_buffer,
-                                   instructions_snapshot_buffer,
-                                   ApiReallocate);
+                                   ApiReallocate,
+                                   &instructions_writer);
   writer.WriteFullSnapshot();
   *vm_isolate_snapshot_size = writer.VmIsolateSnapshotSize();
   *isolate_snapshot_size = writer.IsolateSnapshotSize();
-  *instructions_snapshot_size = writer.InstructionsSnapshotSize();
+  *assembly_size = instructions_writer.AssemblySize();
+
+  return Api::Success();
+}
+
+
+DART_EXPORT Dart_Handle Dart_CreatePrecompiledSnapshotBlob(
+    uint8_t** vm_isolate_snapshot_buffer,
+    intptr_t* vm_isolate_snapshot_size,
+    uint8_t** isolate_snapshot_buffer,
+    intptr_t* isolate_snapshot_size,
+    uint8_t** instructions_blob_buffer,
+    intptr_t* instructions_blob_size,
+    uint8_t** rodata_blob_buffer,
+    intptr_t* rodata_blob_size) {
+  ASSERT(FLAG_load_deferred_eagerly);
+  API_TIMELINE_DURATION;
+  DARTSCOPE(Thread::Current());
+  Isolate* I = T->isolate();
+  if (I->compilation_allowed()) {
+    return Dart_NewApiError("Isolate is not precompiled. "
+                            "Did you forget to call Dart_Precompile?");
+  }
+  if (vm_isolate_snapshot_buffer == NULL) {
+    RETURN_NULL_ERROR(vm_isolate_snapshot_buffer);
+  }
+  if (vm_isolate_snapshot_size == NULL) {
+    RETURN_NULL_ERROR(vm_isolate_snapshot_size);
+  }
+  if (isolate_snapshot_buffer == NULL) {
+    RETURN_NULL_ERROR(isolate_snapshot_buffer);
+  }
+  if (isolate_snapshot_size == NULL) {
+    RETURN_NULL_ERROR(isolate_snapshot_size);
+  }
+  if (instructions_blob_buffer == NULL) {
+    RETURN_NULL_ERROR(instructions_blob_buffer);
+  }
+  if (instructions_blob_size == NULL) {
+    RETURN_NULL_ERROR(instructions_blob_size);
+  }
+  if (rodata_blob_buffer == NULL) {
+    RETURN_NULL_ERROR(instructions_blob_buffer);
+  }
+  if (rodata_blob_size == NULL) {
+    RETURN_NULL_ERROR(instructions_blob_size);
+  }
+  I->heap()->CollectAllGarbage();
+  BlobInstructionsWriter instructions_writer(instructions_blob_buffer,
+                                             rodata_blob_buffer,
+                                             ApiReallocate,
+                                             2 * MB /* initial_size */);
+  PrecompiledSnapshotWriter writer(vm_isolate_snapshot_buffer,
+                                   isolate_snapshot_buffer,
+                                   ApiReallocate,
+                                   &instructions_writer);
+  writer.WriteFullSnapshot();
+  *vm_isolate_snapshot_size = writer.VmIsolateSnapshotSize();
+  *isolate_snapshot_size = writer.IsolateSnapshotSize();
+  *instructions_blob_size = instructions_writer.InstructionsBlobSize();
+  *rodata_blob_size = instructions_writer.RodataBlobSize();
 
   return Api::Success();
 }
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index ea55b49..c9e7769 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -103,15 +103,22 @@
     }
   }
   // Now Call the invoke stub which will invoke the dart function.
+#if !defined(TARGET_ARCH_DBC)
   invokestub entrypoint = reinterpret_cast<invokestub>(
       StubCode::InvokeDartCode_entry()->EntryPoint());
+#endif
   const Code& code = Code::Handle(zone, function.CurrentCode());
   ASSERT(!code.IsNull());
   ASSERT(thread->no_callback_scope_depth() == 0);
   ScopedIsolateStackLimits stack_limit(thread);
   SuspendLongJumpScope suspend_long_jump_scope(thread);
   TransitionToGenerated transition(thread);
-#if defined(USING_SIMULATOR)
+#if defined(TARGET_ARCH_DBC)
+  return Simulator::Current()->Call(code,
+                                    arguments_descriptor,
+                                    arguments,
+                                    thread);
+#elif defined(USING_SIMULATOR)
   return bit_copy<RawObject*, int64_t>(Simulator::Current()->Call(
       reinterpret_cast<intptr_t>(entrypoint),
       reinterpret_cast<intptr_t>(&code),
@@ -322,23 +329,26 @@
   // argument count; the positional argument count; a sequence of (name,
   // position) pairs, sorted by name, for each named optional argument; and
   // a terminating null to simplify iterating in generated code.
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
   const intptr_t descriptor_len = LengthFor(num_named_args);
-  Array& descriptor = Array::Handle(Array::New(descriptor_len, Heap::kOld));
+  Array& descriptor = Array::Handle(
+      zone, Array::New(descriptor_len, Heap::kOld));
 
   // Set total number of passed arguments.
   descriptor.SetAt(kCountIndex, Smi::Handle(Smi::New(num_arguments)));
   // Set number of positional arguments.
   descriptor.SetAt(kPositionalCountIndex, Smi::Handle(Smi::New(num_pos_args)));
   // Set alphabetically sorted entries for named arguments.
-  String& name = String::Handle();
-  Smi& pos = Smi::Handle();
+  String& name = String::Handle(zone);
+  Smi& pos = Smi::Handle(zone);
+  String& previous_name = String::Handle(zone);
+  Smi& previous_pos = Smi::Handle(zone);
   for (intptr_t i = 0; i < num_named_args; i++) {
     name ^= optional_arguments_names.At(i);
     pos = Smi::New(num_pos_args + i);
     intptr_t insert_index = kFirstNamedEntryIndex + (kNamedEntrySize * i);
     // Shift already inserted pairs with "larger" names.
-    String& previous_name = String::Handle();
-    Smi& previous_pos = Smi::Handle();
     while (insert_index > kFirstNamedEntryIndex) {
       intptr_t previous_index = insert_index - kNamedEntrySize;
       previous_name ^= descriptor.At(previous_index + kNameOffset);
@@ -359,7 +369,7 @@
 
   // Share the immutable descriptor when possible by canonicalizing it.
   descriptor.MakeImmutable();
-  descriptor ^= descriptor.CheckAndCanonicalize(NULL);
+  descriptor ^= descriptor.CheckAndCanonicalize(thread, NULL);
   ASSERT(!descriptor.IsNull());
   return descriptor.raw();
 }
@@ -379,9 +389,12 @@
   // Build the arguments descriptor array, which consists of the total
   // argument count; the positional argument count; and
   // a terminating null to simplify iterating in generated code.
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
   const intptr_t descriptor_len = LengthFor(0);
-  Array& descriptor = Array::Handle(Array::New(descriptor_len, Heap::kOld));
-  const Smi& arg_count = Smi::Handle(Smi::New(num_arguments));
+  Array& descriptor = Array::Handle(
+      zone, Array::New(descriptor_len, Heap::kOld));
+  const Smi& arg_count = Smi::Handle(zone, Smi::New(num_arguments));
 
   // Set total number of passed arguments.
   descriptor.SetAt(kCountIndex, arg_count);
@@ -395,7 +408,7 @@
   // Share the immutable descriptor when possible by canonicalizing it.
   descriptor.MakeImmutable();
   if (canonicalize) {
-    descriptor ^= descriptor.CheckAndCanonicalize(NULL);
+    descriptor ^= descriptor.CheckAndCanonicalize(thread, NULL);
   }
   ASSERT(!descriptor.IsNull());
   return descriptor.raw();
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 0f9597f..8c530ea 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -86,6 +86,19 @@
 
   static RawArray* NewNonCached(intptr_t count, bool canonicalize = true);
 
+  // Used by Simulator to parse argument descriptors.
+  static intptr_t name_index(intptr_t index) {
+    return kFirstNamedEntryIndex +
+           (index * kNamedEntrySize) +
+           kNameOffset;
+  }
+
+  static intptr_t position_index(intptr_t index) {
+    return kFirstNamedEntryIndex +
+           (index * kNamedEntrySize) +
+           kPositionOffset;
+  }
+
   const Array& array_;
 
   // A cache of VM heap allocated arguments descriptors.
@@ -93,6 +106,7 @@
 
   friend class SnapshotReader;
   friend class SnapshotWriter;
+  friend class Simulator;
   DISALLOW_COPY_AND_ASSIGN(ArgumentsDescriptor);
 };
 
diff --git a/runtime/vm/datastream.h b/runtime/vm/datastream.h
index f47e822..58452a0 100644
--- a/runtime/vm/datastream.h
+++ b/runtime/vm/datastream.h
@@ -387,6 +387,16 @@
     current_ += len;
   }
 
+  void WriteWord(uword value) {
+    const intptr_t len = sizeof(uword);
+    if ((end_ - current_) < len) {
+      Resize(len);
+    }
+    ASSERT((end_ - current_) >= len);
+    *reinterpret_cast<uword*>(current_) = value;
+    current_ += len;
+  }
+
   void Print(const char* format, ...) {
     va_list args;
     va_start(args, format);
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index aa66533..6afad63 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -231,7 +231,9 @@
 
 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&code_));
+#if !defined(TARGET_ARCH_DBC)
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&saved_value_));
+#endif
 }
 
 
@@ -859,24 +861,25 @@
 }
 
 
+DART_FORCE_INLINE static RawObject* GetVariableValue(uword addr) {
+  return *reinterpret_cast<RawObject**>(addr);
+}
+
+
 RawObject* ActivationFrame::GetParameter(intptr_t index) {
   intptr_t num_parameters = function().num_fixed_parameters();
   ASSERT(0 <= index && index < num_parameters);
-  intptr_t reverse_index = num_parameters - index;
 
   if (function().NumOptionalParameters() > 0) {
     // If the function has optional parameters, the first positional parameter
     // can be in a number of places in the caller's frame depending on how many
     // were actually supplied at the call site, but they are copied to a fixed
     // place in the callee's frame.
-    uword var_address = fp() + ((kFirstLocalSlotFromFp - index) * kWordSize);
-    return reinterpret_cast<RawObject*>(
-        *reinterpret_cast<uword*>(var_address));
+    return GetVariableValue(LocalVarAddress(fp(),
+                                            (kFirstLocalSlotFromFp - index)));
   } else {
-    uword var_address = fp() + (kParamEndSlotFromFp * kWordSize)
-                             + (reverse_index * kWordSize);
-    return reinterpret_cast<RawObject*>(
-        *reinterpret_cast<uword*>(var_address));
+    intptr_t reverse_index = num_parameters - index;
+    return GetVariableValue(ParamAddress(fp(), reverse_index));
   }
 }
 
@@ -889,9 +892,7 @@
 
 RawObject* ActivationFrame::GetStackVar(intptr_t slot_index) {
   if (deopt_frame_.IsNull()) {
-    uword var_address = fp() + slot_index * kWordSize;
-    return reinterpret_cast<RawObject*>(
-        *reinterpret_cast<uword*>(var_address));
+    return GetVariableValue(LocalVarAddress(fp(), slot_index));
   } else {
     return deopt_frame_.At(deopt_frame_offset_ + slot_index);
   }
@@ -1171,7 +1172,12 @@
       bpt_location_(NULL),
       next_(NULL),
       breakpoint_kind_(kind),
-      saved_value_(Code::null()) {
+#if !defined(TARGET_ARCH_DBC)
+      saved_value_(Code::null())
+#else
+      saved_value_(Bytecode::kTrap)
+#endif
+    {
   ASSERT(!code.IsNull());
   ASSERT(token_pos_.IsReal());
   ASSERT(pc_ != 0);
@@ -2693,11 +2699,11 @@
   if (stepping_fp_ != 0) {
     // There is an "interesting frame" set. Only pause at appropriate
     // locations in this frame.
-    if (stepping_fp_ > frame->fp()) {
+    if (IsCalleeFrameOf(stepping_fp_, frame->fp())) {
       // We are i n a callee of the frame we're interested in.
       // Ignore this stepping break.
       return Error::null();
-    } else if (frame->fp() > stepping_fp_) {
+    } else if (IsCalleeFrameOf(frame->fp(), stepping_fp_)) {
       // We returned from the "interesting frame", there can be no more
       // stepping breaks for it. Pause at the next appropriate location
       // and let the user set the "interesting" frame again.
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index 4d00a34..ab83339 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -227,7 +227,14 @@
   CodeBreakpoint* next_;
 
   RawPcDescriptors::Kind breakpoint_kind_;
+#if !defined(TARGET_ARCH_DBC)
   RawCode* saved_value_;
+#else
+  // When running on the DBC interpreter we patch bytecode in place with
+  // DebugBreak. This is an instruction that was replaced. DebugBreak
+  // will execute it after the breakpoint.
+  Instr saved_value_;
+#endif
 
   friend class Debugger;
   DISALLOW_COPY_AND_ASSIGN(CodeBreakpoint);
diff --git a/runtime/vm/debugger_api_impl_test.cc b/runtime/vm/debugger_api_impl_test.cc
index 0be2d29..80311f1 100644
--- a/runtime/vm/debugger_api_impl_test.cc
+++ b/runtime/vm/debugger_api_impl_test.cc
@@ -282,8 +282,13 @@
     res = Dart_ActivationFrameGetFramePointer(frame, &frame_pointer);
     EXPECT_TRUE(res);
     if (i > 0) {
+#if !defined(TARGET_ARCH_DBC)
       // We expect the stack to grow from high to low addresses.
       EXPECT_GT(frame_pointer, last_frame_pointer);
+#else
+      // On DBC stack grows upwards from low to high addresses.
+      EXPECT_LT(frame_pointer, last_frame_pointer);
+#endif
     }
     last_frame_pointer = frame_pointer;
     if (i < expected_frames) {
diff --git a/runtime/vm/debugger_dbc.cc b/runtime/vm/debugger_dbc.cc
new file mode 100644
index 0000000..5f82cd5
--- /dev/null
+++ b/runtime/vm/debugger_dbc.cc
@@ -0,0 +1,86 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h"
+#if defined(TARGET_ARCH_DBC)
+
+#include "vm/code_patcher.h"
+#include "vm/cpu.h"
+#include "vm/debugger.h"
+#include "vm/instructions.h"
+#include "vm/stub_code.h"
+
+namespace dart {
+
+#ifndef PRODUCT
+
+RawCode* CodeBreakpoint::OrigStubAddress() const {
+  return reinterpret_cast<RawCode*>(static_cast<uintptr_t>(saved_value_));
+}
+
+
+static Instr* CallInstructionFromReturnAddress(uword pc) {
+  return reinterpret_cast<Instr*>(pc) - 1;
+}
+
+
+void CodeBreakpoint::PatchCode() {
+  ASSERT(!is_enabled_);
+  const Code& code = Code::Handle(code_);
+  const Instructions& instrs = Instructions::Handle(code.instructions());
+  {
+    WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size());
+    saved_value_ = *CallInstructionFromReturnAddress(pc_);
+    switch (breakpoint_kind_) {
+      case RawPcDescriptors::kIcCall:
+      case RawPcDescriptors::kUnoptStaticCall: {
+        // DebugBreak has an A operand matching the call it replaces.
+        // This ensures that Return instructions continue to work - as they
+        // look at calls to figure out how many arguments to drop.
+        *CallInstructionFromReturnAddress(pc_) =
+            Bytecode::Encode(Bytecode::kDebugBreak,
+                             Bytecode::DecodeArgc(saved_value_),
+                             0,
+                             0);
+        break;
+      }
+
+      case RawPcDescriptors::kRuntimeCall: {
+        *CallInstructionFromReturnAddress(pc_) = Bytecode::kDebugBreak;
+        break;
+      }
+
+      default:
+        UNREACHABLE();
+    }
+  }
+  is_enabled_ = true;
+}
+
+
+void CodeBreakpoint::RestoreCode() {
+  ASSERT(is_enabled_);
+  const Code& code = Code::Handle(code_);
+  const Instructions& instrs = Instructions::Handle(code.instructions());
+  {
+    WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size());
+    switch (breakpoint_kind_) {
+      case RawPcDescriptors::kIcCall:
+      case RawPcDescriptors::kUnoptStaticCall:
+      case RawPcDescriptors::kRuntimeCall: {
+        *CallInstructionFromReturnAddress(pc_) = saved_value_;
+        break;
+      }
+      default:
+        UNREACHABLE();
+    }
+  }
+  is_enabled_ = false;
+}
+
+#endif  // !PRODUCT
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index ecef279..614b976 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -660,12 +660,16 @@
     Function& function = Function::Handle(deopt_context->zone());
     function ^= deopt_context->ObjectAt(object_table_index_);
     if (function.IsNull()) {
+      // There are no deoptimization stubs on DBC.
+#if !defined(TARGET_ARCH_DBC)
       *reinterpret_cast<RawObject**>(dest_addr) = deopt_context->is_lazy_deopt()
           ? StubCode::DeoptimizeLazy_entry()->code()
           : StubCode::Deoptimize_entry()->code();
+#endif
       return;
     }
 
+#if !defined(TARGET_ARCH_DBC)
     // We don't always have the Code object for the frame's corresponding
     // unoptimized code as it may have been collected. Use a stub as the pc
     // marker until we can recreate that Code object during deferred
@@ -673,6 +677,7 @@
     // a pc marker.
     *reinterpret_cast<RawObject**>(dest_addr) =
         StubCode::FrameAwaitingMaterialization_entry()->code();
+#endif
     deopt_context->DeferPcMarkerMaterialization(object_table_index_, dest_addr);
   }
 
diff --git a/runtime/vm/disassembler_dbc.cc b/runtime/vm/disassembler_dbc.cc
new file mode 100644
index 0000000..85d734d
--- /dev/null
+++ b/runtime/vm/disassembler_dbc.cc
@@ -0,0 +1,233 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/disassembler.h"
+
+#include "vm/globals.h"  // Needed here to get TARGET_ARCH_DBC.
+#if defined(TARGET_ARCH_DBC)
+
+#include "platform/assert.h"
+#include "vm/constants_dbc.h"
+#include "vm/cpu.h"
+
+namespace dart {
+
+static const char* kOpcodeNames[] = {
+#define BYTECODE_NAME(name, encoding, op1, op2, op3) #name,
+    BYTECODES_LIST(BYTECODE_NAME)
+#undef BYTECODE_NAME
+};
+
+static const size_t kOpcodeCount =
+    sizeof(kOpcodeNames) / sizeof(kOpcodeNames[0]);
+
+typedef void (*BytecodeFormatter)(char* buffer,
+                                  intptr_t size,
+                                  uword pc,
+                                  uint32_t bc);
+typedef void (*Fmt)(char** buf, intptr_t* size, uword pc, int32_t value);
+
+
+template <typename ValueType>
+void FormatOperand(char** buf,
+                   intptr_t* size,
+                   const char* fmt,
+                   ValueType value) {
+  intptr_t written = OS::SNPrint(*buf, *size, fmt, value);
+  if (written < *size) {
+    *buf += written;
+    *size += written;
+  } else {
+    *size = -1;
+  }
+}
+
+
+static void Fmt___(char** buf, intptr_t* size, uword pc, int32_t value) {}
+
+
+static void Fmttgt(char** buf, intptr_t* size, uword pc, int32_t value) {
+  FormatOperand(buf, size, "-> %" Px, pc + (value << 2));
+}
+
+
+static void Fmtlit(char** buf, intptr_t* size, uword pc, int32_t value) {
+  FormatOperand(buf, size, "k%d", value);
+}
+
+
+static void Fmtreg(char** buf, intptr_t* size, uword pc, int32_t value) {
+  FormatOperand(buf, size, "r%d", value);
+}
+
+
+static void Fmtxeg(char** buf, intptr_t* size, uword pc, int32_t value) {
+  FormatOperand(buf, size, "R(%d)", value);
+}
+
+
+static void Fmtnum(char** buf, intptr_t* size, uword pc, int32_t value) {
+  FormatOperand(buf, size, "#%d", value);
+}
+
+
+static void Apply(char** buf,
+                  intptr_t* size,
+                  uword pc,
+                  Fmt fmt,
+                  int32_t value,
+                  const char* suffix) {
+  if (*size <= 0) {
+    return;
+  }
+
+  fmt(buf, size, pc, value);
+  if (*size > 0) {
+    FormatOperand(buf, size, "%s", suffix);
+  }
+}
+
+
+static void Format0(char* buf,
+                    intptr_t size,
+                    uword pc,
+                    uint32_t op,
+                    Fmt op1,
+                    Fmt op2,
+                    Fmt op3) {}
+
+
+static void FormatT(char* buf,
+                    intptr_t size,
+                    uword pc,
+                    uint32_t op,
+                    Fmt op1,
+                    Fmt op2,
+                    Fmt op3) {
+  const int32_t x = static_cast<int32_t>(op) >> 8;
+  Apply(&buf, &size, pc, op1, x, "");
+}
+
+
+static void FormatA(char* buf,
+                    intptr_t size,
+                    uword pc,
+                    uint32_t op,
+                    Fmt op1,
+                    Fmt op2,
+                    Fmt op3) {
+  const int32_t a = (op & 0xFF00) >> 8;
+  Apply(&buf, &size, pc, op1, a, "");
+}
+
+
+static void FormatA_D(char* buf,
+                      intptr_t size,
+                      uword pc,
+                      uint32_t op,
+                      Fmt op1,
+                      Fmt op2,
+                      Fmt op3) {
+  const int32_t a = (op & 0xFF00) >> 8;
+  const int32_t bc = op >> 16;
+  Apply(&buf, &size, pc, op1, a, ", ");
+  Apply(&buf, &size, pc, op2, bc, "");
+}
+
+
+static void FormatA_X(char* buf,
+                      intptr_t size,
+                      uword pc,
+                      uint32_t op,
+                      Fmt op1,
+                      Fmt op2,
+                      Fmt op3) {
+  const int32_t a = (op & 0xFF00) >> 8;
+  const int32_t bc = static_cast<int32_t>(op) >> 16;
+  Apply(&buf, &size, pc, op1, a, ", ");
+  Apply(&buf, &size, pc, op2, bc, "");
+}
+
+
+static void FormatX(char* buf,
+                    intptr_t size,
+                    uword pc,
+                    uint32_t op,
+                    Fmt op1,
+                    Fmt op2,
+                    Fmt op3) {
+  const int32_t bc = static_cast<int32_t>(op) >> 16;
+  Apply(&buf, &size, pc, op1, bc, "");
+}
+
+
+static void FormatD(char* buf,
+                    intptr_t size,
+                    uword pc,
+                    uint32_t op,
+                    Fmt op1,
+                    Fmt op2,
+                    Fmt op3) {
+  const int32_t bc = op >> 16;
+  Apply(&buf, &size, pc, op1, bc, "");
+}
+
+
+static void FormatA_B_C(char* buf,
+                        intptr_t size,
+                        uword pc,
+                        uint32_t op,
+                        Fmt op1,
+                        Fmt op2,
+                        Fmt op3) {
+  const int32_t a = (op >> 8) & 0xFF;
+  const int32_t b = (op >> 16) & 0xFF;
+  const int32_t c = (op >> 24) & 0xFF;
+  Apply(&buf, &size, pc, op1, a, ", ");
+  Apply(&buf, &size, pc, op2, b, ", ");
+  Apply(&buf, &size, pc, op3, c, "");
+}
+
+
+#define BYTECODE_FORMATTER(name, encoding, op1, op2, op3)                     \
+  static void Format##name(char* buf, intptr_t size, uword pc, uint32_t op) { \
+    Format##encoding(buf, size, pc, op, Fmt##op1, Fmt##op2, Fmt##op3);        \
+  }
+BYTECODES_LIST(BYTECODE_FORMATTER)
+#undef BYTECODE_FORMATTER
+
+
+static const BytecodeFormatter kFormatters[] = {
+#define BYTECODE_FORMATTER(name, encoding, op1, op2, op3) &Format##name,
+    BYTECODES_LIST(BYTECODE_FORMATTER)
+#undef BYTECODE_FORMATTER
+};
+
+
+void Disassembler::DecodeInstruction(char* hex_buffer,
+                                     intptr_t hex_size,
+                                     char* human_buffer,
+                                     intptr_t human_size,
+                                     int* out_instr_size,
+                                     uword pc) {
+  const uint32_t instr = *reinterpret_cast<uint32_t*>(pc);
+  const uint8_t opcode = instr & 0xFF;
+  ASSERT(opcode < kOpcodeCount);
+  size_t name_size =
+      OS::SNPrint(human_buffer, human_size, "%-10s\t", kOpcodeNames[opcode]);
+
+  human_buffer += name_size;
+  human_size -= name_size;
+  kFormatters[opcode](human_buffer, human_size, pc, instr);
+
+  OS::SNPrint(hex_buffer, hex_size, "%08x", instr);
+  if (out_instr_size) {
+    *out_instr_size = sizeof(uint32_t);
+  }
+}
+
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/disassembler_test.cc b/runtime/vm/disassembler_test.cc
index d07e174..8df643e 100644
--- a/runtime/vm/disassembler_test.cc
+++ b/runtime/vm/disassembler_test.cc
@@ -9,7 +9,9 @@
 
 namespace dart {
 
-#ifndef PRODUCT
+// TODO(vegorov) this test is disabled on DBC because there is no PopRegister
+// method on DBC assembler.
+#if !defined(PRODUCT) && !defined(TARGET_ARCH_DBC)
 
 TEST_CASE(Disassembler) {
   Assembler assembler;
diff --git a/runtime/vm/disassembler_x64.cc b/runtime/vm/disassembler_x64.cc
index 37d8184..60118f1 100644
--- a/runtime/vm/disassembler_x64.cc
+++ b/runtime/vm/disassembler_x64.cc
@@ -374,8 +374,8 @@
     return xmm_regs[reg];
   }
 
-  void AppendToBuffer(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
-  void AppendAddressToBuffer(uint8_t* addr);
+  void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
+  void PrintAddress(uint8_t* addr);
 
   int PrintOperands(const char* mnem,
                     OperandType op_order,
@@ -388,7 +388,9 @@
   int PrintRightOperand(uint8_t* modrmp);
   int PrintRightByteOperand(uint8_t* modrmp);
   int PrintRightXMMOperand(uint8_t* modrmp);
+  void PrintDisp(int disp, const char* after);
   int PrintImmediate(uint8_t* data, OperandSize size);
+  void PrintImmediateValue(int64_t value);
   int PrintImmediateOp(uint8_t* data);
   const char* TwoByteMnemonic(uint8_t opcode);
   int TwoByteOpcodeInstruction(uint8_t* data);
@@ -406,7 +408,7 @@
   bool DecodeInstructionType(uint8_t** data);
 
   void UnimplementedInstruction() {
-    AppendToBuffer("'Unimplemented Instruction'");
+    Print("'Unimplemented Instruction'");
   }
 
   char* buffer_;  // Decode instructions into this buffer.
@@ -426,7 +428,7 @@
 
 
 // Append the str to the output buffer.
-void DisassemblerX64::AppendToBuffer(const char* format, ...) {
+void DisassemblerX64::Print(const char* format, ...) {
   intptr_t available = buffer_size_ - buffer_pos_;
   if (available <= 1) {
     ASSERT(buffer_[buffer_pos_] == '\0');
@@ -454,7 +456,8 @@
     case 0:
       if ((rm & 7) == 5) {
         int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1);
-        AppendToBuffer("[rip%s%#x]", disp < 0 ? "-" : "+", Utils::Abs(disp));
+        Print("[rip");
+        PrintDisp(disp, "]");
         return 5;
       } else if ((rm & 7) == 4) {
         // Codes for SIB byte.
@@ -464,28 +467,27 @@
         if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
           // index == rsp means no index. Only use sib byte with no index for
           // rsp and r12 base.
-          AppendToBuffer("[%s]", NameOfCPURegister(base));
+          Print("[%s]", NameOfCPURegister(base));
           return 2;
         } else if (base == 5) {
           // base == rbp means no base register (when mod == 0).
           int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
-          AppendToBuffer("[%s*%d+%#x]",
-                         NameOfCPURegister(index),
-                         1 << scale, disp);
+          Print("[%s*%d", NameOfCPURegister(index), 1 << scale);
+          PrintDisp(disp, "]");
           return 6;
         } else if (index != 4 && base != 5) {
           // [base+index*scale]
-          AppendToBuffer("[%s+%s*%d]",
-                         NameOfCPURegister(base),
-                         NameOfCPURegister(index),
-                         1 << scale);
+          Print("[%s+%s*%d]",
+                NameOfCPURegister(base),
+                NameOfCPURegister(index),
+                1 << scale);
           return 2;
         } else {
           UnimplementedInstruction();
           return 1;
         }
       } else {
-        AppendToBuffer("[%s]", NameOfCPURegister(rm));
+        Print("[%s]", NameOfCPURegister(rm));
         return 1;
       }
       break;
@@ -498,41 +500,27 @@
         int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2)
                               : *reinterpret_cast<char*>(modrmp + 2);
         if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
-          if (-disp > 0) {
-            AppendToBuffer("[%s-%#x]", NameOfCPURegister(base), -disp);
-          } else {
-            AppendToBuffer("[%s+%#x]", NameOfCPURegister(base), disp);
-          }
+          Print("[%s", NameOfCPURegister(base));
+          PrintDisp(disp, "]");
         } else {
-          if (-disp > 0) {
-            AppendToBuffer("[%s+%s*%d-%#x]",
-                           NameOfCPURegister(base),
-                           NameOfCPURegister(index),
-                           1 << scale,
-                           -disp);
-          } else {
-            AppendToBuffer("[%s+%s*%d+%#x]",
-                           NameOfCPURegister(base),
-                           NameOfCPURegister(index),
-                           1 << scale,
-                           disp);
-          }
+          Print("[%s+%s*%d",
+                NameOfCPURegister(base),
+                NameOfCPURegister(index),
+                1 << scale);
+          PrintDisp(disp, "]");
         }
         return mod == 2 ? 6 : 3;
       } else {
         // No sib.
         int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1)
                               : *reinterpret_cast<char*>(modrmp + 1);
-        if (-disp > 0) {
-        AppendToBuffer("[%s-%#x]", NameOfCPURegister(rm), -disp);
-        } else {
-        AppendToBuffer("[%s+%#x]", NameOfCPURegister(rm), disp);
-        }
+        Print("[%s", NameOfCPURegister(rm));
+        PrintDisp(disp, "]");
         return (mod == 2) ? 5 : 2;
       }
       break;
     case 3:
-      AppendToBuffer("%s", (this->*register_name)(rm));
+      Print("%s", (this->*register_name)(rm));
       return 1;
     default:
       UnimplementedInstruction();
@@ -567,10 +555,29 @@
       value = 0;  // Initialize variables on all paths to satisfy the compiler.
       count = 0;
   }
-  AppendToBuffer("%#" Px64 "", value);
+  PrintImmediateValue(value);
   return count;
 }
 
+void DisassemblerX64::PrintImmediateValue(int64_t value) {
+  if ((value >= 0) && (value <= 9)) {
+    Print("%" Pd64 "", value);
+  } else {
+    Print("%#" Px64 "", value);
+  }
+}
+
+void DisassemblerX64::PrintDisp(int disp, const char* after) {
+  if (-disp > 0) {
+    Print("-%#x", -disp);
+  } else {
+    Print("+%#x", disp);
+  }
+  if (after != NULL) Print("%s", after);
+}
+
+
+
 
 // Returns number of bytes used by machine instruction, including *data byte.
 // Writes immediate instructions to 'tmp_buffer_'.
@@ -608,9 +615,9 @@
     default:
       UnimplementedInstruction();
   }
-  AppendToBuffer("%s%c ", mnem, operand_size_code());
+  Print("%s%c ", mnem, operand_size_code());
   int count = PrintRightOperand(data + 1);
-  AppendToBuffer(",");
+  Print(",");
   OperandSize immediate_size = byte_size_immediate ? BYTE_SIZE : operand_size();
   count += PrintImmediate(data + 1 + count, immediate_size);
   return 1 + count;
@@ -644,15 +651,15 @@
       default:
         UnimplementedInstruction();
     }
-    AppendToBuffer("%s%c %s",
-                   mnem,
-                   operand_size_code(),
-                   NameOfCPURegister(rm));
+    Print("%s%c %s",
+          mnem,
+          operand_size_code(),
+          NameOfCPURegister(rm));
     return 2;
   } else if (regop == 0) {
-    AppendToBuffer("test%c ", operand_size_code());
+    Print("test%c ", operand_size_code());
     int count = PrintRightOperand(data + 1);  // Use name of 64-bit register.
-    AppendToBuffer(",0x");
+    Print(",");
     count += PrintImmediate(data + 1 + count, operand_size());
     return 1 + count;
   } else {
@@ -712,15 +719,15 @@
     imm8 = *(data + 2);
     num_bytes = 3;
   }
-  AppendToBuffer("%s%c %s,",
-                 mnem,
-                 operand_size_code(),
-                 byte_size_operand_ ? NameOfByteCPURegister(rm)
-                                    : NameOfCPURegister(rm));
+  Print("%s%c %s,",
+        mnem,
+        operand_size_code(),
+        byte_size_operand_ ? NameOfByteCPURegister(rm)
+                           : NameOfCPURegister(rm));
   if (op == 0xD2) {
-    AppendToBuffer("cl");
+    Print("cl");
   } else {
-    AppendToBuffer("%d", imm8);
+    Print("%d", imm8);
   }
   return num_bytes;
 }
@@ -758,19 +765,16 @@
                          : NameOfCPURegister(regop);
   switch (op_order) {
     case REG_OPER_OP_ORDER: {
-      AppendToBuffer("%s%c %s,",
-                     mnem,
-                     operand_size_code(),
-                     register_name);
+      Print("%s%c %s,", mnem, operand_size_code(), register_name);
       advance = byte_size_operand_ ? PrintRightByteOperand(data)
                                    : PrintRightOperand(data);
       break;
     }
     case OPER_REG_OP_ORDER: {
-      AppendToBuffer("%s%c ", mnem, operand_size_code());
+      Print("%s%c ", mnem, operand_size_code());
       advance = byte_size_operand_ ? PrintRightByteOperand(data)
                                    : PrintRightOperand(data);
-      AppendToBuffer(",%s", register_name);
+      Print(",%s", register_name);
       break;
     }
     default:
@@ -803,9 +807,9 @@
 }
 
 
-void DisassemblerX64::AppendAddressToBuffer(uint8_t* addr_byte_ptr) {
+void DisassemblerX64::PrintAddress(uint8_t* addr_byte_ptr) {
   uword addr = reinterpret_cast<uword>(addr_byte_ptr);
-  AppendToBuffer("%#" Px "", addr);
+  Print("%#" Px "", addr);
   // Try to print as heap object or stub name
   if (((addr & kSmiTagMask) == kHeapObjectTag) &&
       reinterpret_cast<RawObject*>(addr)->IsWellFormed() &&
@@ -819,25 +823,25 @@
       const Array& arr = Array::Cast(obj);
       intptr_t len = arr.Length();
       if (len > 5) len = 5;  // Print a max of 5 elements.
-      AppendToBuffer("  Array[");
+      Print("  Array[");
       int i = 0;
       Object& element = Object::Handle();
       while (i < len) {
         element = arr.At(i);
-        if (i > 0) AppendToBuffer(", ");
-        AppendToBuffer("%s", ObjectToCStringNoGC(element));
+        if (i > 0) Print(", ");
+        Print("%s", ObjectToCStringNoGC(element));
         i++;
       }
-      if (i < arr.Length()) AppendToBuffer(", ...");
-      AppendToBuffer("]");
+      if (i < arr.Length()) Print(", ...");
+      Print("]");
       return;
     }
-    AppendToBuffer("  '%s'", ObjectToCStringNoGC(obj));
+    Print("  '%s'", ObjectToCStringNoGC(obj));
   } else {
     // 'addr' is not an object, but probably a code address.
     const char* name_of_stub = StubCode::NameOfStub(addr);
     if (name_of_stub != NULL) {
-      AppendToBuffer("  [stub: %s]", name_of_stub);
+      Print("  [stub: %s]", name_of_stub);
     }
   }
 }
@@ -848,8 +852,8 @@
   ASSERT(0xEB == *data);
   uint8_t b = *(data + 1);
   uint8_t* dest = data + static_cast<int8_t>(b) + 2;
-  AppendToBuffer("jmp ");
-  AppendAddressToBuffer(dest);
+  Print("jmp ");
+  PrintAddress(dest);
   return 2;
 }
 
@@ -860,8 +864,8 @@
   uint8_t cond = *(data + 1) & 0x0F;
   uint8_t* dest = data + *reinterpret_cast<int32_t*>(data + 2) + 6;
   const char* mnem = conditional_code_suffix[cond];
-  AppendToBuffer("j%s ", mnem);
-  AppendAddressToBuffer(dest);
+  Print("j%s ", mnem);
+  PrintAddress(dest);
   return 6;  // includes 0x0F
 }
 
@@ -872,8 +876,8 @@
   uint8_t b = *(data + 1);
   uint8_t* dest = data + static_cast<int8_t>(b) + 2;
   const char* mnem = conditional_code_suffix[cond];
-  AppendToBuffer("j%s ", mnem);
-  AppendAddressToBuffer(dest);
+  Print("j%s ", mnem);
+  PrintAddress(dest);
   return 2;
 }
 
@@ -883,7 +887,7 @@
   ASSERT(0x0F == *data);
   uint8_t cond = *(data + 1) & 0x0F;
   const char* mnem = conditional_code_suffix[cond];
-  AppendToBuffer("set%s%c ", mnem, operand_size_code());
+  Print("set%s%c ", mnem, operand_size_code());
   PrintRightByteOperand(data + 2);
   return 3;  // includes 0x0F
 }
@@ -942,7 +946,7 @@
 
     default: UnimplementedInstruction();
   }
-  AppendToBuffer("%s ", mnem);
+  Print("%s ", mnem);
   int count = PrintRightOperand(modrm_start);
   return count + 1;
 }
@@ -1058,9 +1062,9 @@
   }
 
   if (has_register) {
-    AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7);
+    Print("%s st%d", mnem, modrm_byte & 0x7);
   } else {
-    AppendToBuffer("%s", mnem);
+    Print("%s", mnem);
   }
   return 2;
 }
@@ -1078,11 +1082,11 @@
     } else if ((current & 0xF0) == 0x40) {  // REX prefix.
       setRex(current);
       // TODO(srdjan): Should we enable printing of REX.W?
-      // if (rex_w()) AppendToBuffer("REX.W ");
+      // if (rex_w()) Print("REX.W ");
     } else if ((current & 0xFE) == 0xF2) {  // Group 1 prefix (0xF2 or 0xF3).
       group_1_prefix_ = current;
     } else if (current == 0xF0) {
-      AppendToBuffer("lock ");
+      Print("lock ");
     } else {  // Not a prefix - an opcode.
       break;
     }
@@ -1098,13 +1102,13 @@
         // String move or compare operations.
         if (group_1_prefix_ == REP_PREFIX) {
           // REP.
-          AppendToBuffer("rep ");
+          Print("rep ");
         }
         // TODO(srdjan): Should we enable printing of REX.W?
-        // if (rex_w()) AppendToBuffer("REX.W ");
-        AppendToBuffer("%s%c", idesc.mnem, operand_size_code());
+        // if (rex_w()) Print("REX.W ");
+        Print("%s%c", idesc.mnem, operand_size_code());
       } else {
-        AppendToBuffer("%s%c", idesc.mnem, operand_size_code());
+        Print("%s%c", idesc.mnem, operand_size_code());
       }
       (*data)++;
       break;
@@ -1119,16 +1123,16 @@
       break;
 
     case REGISTER_INSTR:
-      AppendToBuffer("%s%c %s",
-                     idesc.mnem,
-                     operand_size_code(),
-                     NameOfCPURegister(base_reg(current & 0x07)));
+      Print("%s%c %s",
+            idesc.mnem,
+            operand_size_code(),
+            NameOfCPURegister(base_reg(current & 0x07)));
       (*data)++;
       break;
     case PUSHPOP_INSTR:
-      AppendToBuffer("%s %s",
-                     idesc.mnem,
-                     NameOfCPURegister(base_reg(current & 0x07)));
+      Print("%s %s",
+            idesc.mnem,
+            NameOfCPURegister(base_reg(current & 0x07)));
       (*data)++;
       break;
     case MOVE_REG_INSTR: {
@@ -1152,17 +1156,17 @@
         default:
           UNREACHABLE();
       }
-      AppendToBuffer("mov%c %s,",
-                     operand_size_code(),
-                     NameOfCPURegister(base_reg(current & 0x07)));
-      AppendAddressToBuffer(addr);
+      Print("mov%c %s,",
+            operand_size_code(),
+            NameOfCPURegister(base_reg(current & 0x07)));
+      PrintAddress(addr);
       break;
     }
 
     case CALL_JUMP_INSTR: {
       uint8_t* addr = *data + *reinterpret_cast<int32_t*>(*data + 1) + 5;
-      AppendToBuffer("%s ", idesc.mnem);
-      AppendAddressToBuffer(addr);
+      Print("%s ", idesc.mnem);
+      PrintAddress(addr);
       (*data) += 5;
       break;
     }
@@ -1170,8 +1174,8 @@
     case SHORT_IMMEDIATE_INSTR: {
       uint8_t* addr =
           reinterpret_cast<uint8_t*>(*reinterpret_cast<int32_t*>(*data + 1));
-      AppendToBuffer("%s rax, ", idesc.mnem);
-      AppendAddressToBuffer(addr);
+      Print("%s rax, ", idesc.mnem);
+      PrintAddress(addr);
       (*data) += 5;
       break;
     }
@@ -1200,25 +1204,25 @@
     if (opcode == 0xC6) {
       int mod, regop, rm;
       get_modrm(*current, &mod, &regop, &rm);
-      AppendToBuffer("shufpd %s, ", NameOfXMMRegister(regop));
+      Print("shufpd %s, ", NameOfXMMRegister(regop));
       current += PrintRightXMMOperand(current);
-      AppendToBuffer(" [%x]", *current);
+      Print(" [%x]", *current);
       current++;
     } else if (opcode == 0x3A) {
       uint8_t third_byte = *current;
       current = data + 3;
       if (third_byte == 0x17) {
         get_modrm(*current, &mod, &regop, &rm);
-        AppendToBuffer("extractps ");  // reg/m32, xmm, imm8
+        Print("extractps ");  // reg/m32, xmm, imm8
         current += PrintRightOperand(current);
-        AppendToBuffer(", %s, %d", NameOfCPURegister(regop), (*current) & 3);
+        Print(", %s, %d", NameOfCPURegister(regop), (*current) & 3);
         current += 1;
       } else if (third_byte == 0x0b) {
         get_modrm(*current, &mod, &regop, &rm);
          // roundsd xmm, xmm/m64, imm8
-        AppendToBuffer("roundsd %s, ", NameOfCPURegister(regop));
+        Print("roundsd %s, ", NameOfCPURegister(regop));
         current += PrintRightOperand(current);
-        AppendToBuffer(", %d", (*current) & 3);
+        Print(", %d", (*current) & 3);
         current += 1;
       } else {
         UnimplementedInstruction();
@@ -1235,38 +1239,38 @@
         } else if (mod == 2) {  // 32-bit displacement.
           current += 4;
         }  // else no immediate displacement.
-        AppendToBuffer("nop");
+        Print("nop");
       } else if (opcode == 0x28) {
-        AppendToBuffer("movapd %s, ", NameOfXMMRegister(regop));
+        Print("movapd %s, ", NameOfXMMRegister(regop));
         current += PrintRightXMMOperand(current);
       } else if (opcode == 0x29) {
-        AppendToBuffer("movapd ");
+        Print("movapd ");
         current += PrintRightXMMOperand(current);
-        AppendToBuffer(", %s", NameOfXMMRegister(regop));
+        Print(", %s", NameOfXMMRegister(regop));
       } else if (opcode == 0x6E) {
-        AppendToBuffer("mov%c %s,",
-                       rex_w() ? 'q' : 'd',
-                       NameOfXMMRegister(regop));
+        Print("mov%c %s,",
+              rex_w() ? 'q' : 'd',
+              NameOfXMMRegister(regop));
         current += PrintRightOperand(current);
       } else if (opcode == 0x6F) {
-        AppendToBuffer("movdqa %s,",
-                       NameOfXMMRegister(regop));
+        Print("movdqa %s,",
+              NameOfXMMRegister(regop));
         current += PrintRightXMMOperand(current);
       } else if (opcode == 0x7E) {
-        AppendToBuffer("mov%c ",
-                       rex_w() ? 'q' : 'd');
+        Print("mov%c ",
+              rex_w() ? 'q' : 'd');
         current += PrintRightOperand(current);
-        AppendToBuffer(", %s", NameOfXMMRegister(regop));
+        Print(", %s", NameOfXMMRegister(regop));
       } else if (opcode == 0x7F) {
-        AppendToBuffer("movdqa ");
+        Print("movdqa ");
         current += PrintRightXMMOperand(current);
-        AppendToBuffer(", %s", NameOfXMMRegister(regop));
+        Print(", %s", NameOfXMMRegister(regop));
       } else if (opcode == 0xD6) {
-        AppendToBuffer("movq ");
+        Print("movq ");
         current += PrintRightXMMOperand(current);
-        AppendToBuffer(", %s", NameOfXMMRegister(regop));
+        Print(", %s", NameOfXMMRegister(regop));
       } else if (opcode == 0x50) {
-        AppendToBuffer("movmskpd %s,", NameOfCPURegister(regop));
+        Print("movmskpd %s,", NameOfCPURegister(regop));
         current += PrintRightXMMOperand(current);
       } else {
         const char* mnemonic = "?";
@@ -1307,7 +1311,7 @@
         } else {
           UnimplementedInstruction();
         }
-        AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
+        Print("%s %s,", mnemonic, NameOfXMMRegister(regop));
         current += PrintRightXMMOperand(current);
       }
     }
@@ -1316,42 +1320,42 @@
 
     if (opcode == 0x11 || opcode == 0x10) {
       // MOVSD: Move scalar double-precision fp to/from/between XMM registers.
-      AppendToBuffer("movsd ");
+      Print("movsd ");
       int mod, regop, rm;
       get_modrm(*current, &mod, &regop, &rm);
       if (opcode == 0x11) {
         current += PrintRightXMMOperand(current);
-        AppendToBuffer(",%s", NameOfXMMRegister(regop));
+        Print(",%s", NameOfXMMRegister(regop));
       } else {
-        AppendToBuffer("%s,", NameOfXMMRegister(regop));
+        Print("%s,", NameOfXMMRegister(regop));
         current += PrintRightXMMOperand(current);
       }
     } else if (opcode == 0x2A) {
       // CVTSI2SD: integer to XMM double conversion.
       int mod, regop, rm;
       get_modrm(*current, &mod, &regop, &rm);
-      AppendToBuffer("%sd %s,", mnemonic, NameOfXMMRegister(regop));
+      Print("%sd %s,", mnemonic, NameOfXMMRegister(regop));
       current += PrintRightOperand(current);
     } else if (opcode == 0x2C) {
       // CVTTSD2SI:
       // Convert with truncation scalar double-precision FP to integer.
       int mod, regop, rm;
       get_modrm(*current, &mod, &regop, &rm);
-      AppendToBuffer("cvttsd2si%c %s,",
+      Print("cvttsd2si%c %s,",
           operand_size_code(), NameOfCPURegister(regop));
       current += PrintRightXMMOperand(current);
     } else if (opcode == 0x2D) {
       // CVTSD2SI: Convert scalar double-precision FP to integer.
       int mod, regop, rm;
       get_modrm(*current, &mod, &regop, &rm);
-      AppendToBuffer("cvtsd2si%c %s,",
+      Print("cvtsd2si%c %s,",
           operand_size_code(), NameOfCPURegister(regop));
       current += PrintRightXMMOperand(current);
     } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
       // XMM arithmetic. Mnemonic was retrieved at the start of this function.
       int mod, regop, rm;
       get_modrm(*current, &mod, &regop, &rm);
-      AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
+      Print("%s %s,", mnemonic, NameOfXMMRegister(regop));
       current += PrintRightXMMOperand(current);
     } else {
       UnimplementedInstruction();
@@ -1360,46 +1364,46 @@
     // Instructions with prefix 0xF3.
     if (opcode == 0x11 || opcode == 0x10) {
       // MOVSS: Move scalar double-precision fp to/from/between XMM registers.
-      AppendToBuffer("movss ");
+      Print("movss ");
       int mod, regop, rm;
       get_modrm(*current, &mod, &regop, &rm);
       if (opcode == 0x11) {
         current += PrintRightOperand(current);
-        AppendToBuffer(",%s", NameOfXMMRegister(regop));
+        Print(",%s", NameOfXMMRegister(regop));
       } else {
-        AppendToBuffer("%s,", NameOfXMMRegister(regop));
+        Print("%s,", NameOfXMMRegister(regop));
         current += PrintRightOperand(current);
       }
     } else if (opcode == 0x2A) {
       // CVTSI2SS: integer to XMM single conversion.
       int mod, regop, rm;
       get_modrm(*current, &mod, &regop, &rm);
-      AppendToBuffer("%ss %s,", mnemonic, NameOfXMMRegister(regop));
+      Print("%ss %s,", mnemonic, NameOfXMMRegister(regop));
       current += PrintRightOperand(current);
     } else if (opcode == 0x2C) {
       // CVTTSS2SI:
       // Convert with truncation scalar single-precision FP to dword integer.
       int mod, regop, rm;
       get_modrm(*current, &mod, &regop, &rm);
-      AppendToBuffer("cvttss2si%c %s,",
-          operand_size_code(), NameOfCPURegister(regop));
+      Print("cvttss2si%c %s,",
+            operand_size_code(), NameOfCPURegister(regop));
       current += PrintRightXMMOperand(current);
     } else if (opcode == 0x5A) {
       // CVTSS2SD:
       // Convert scalar single-precision FP to scalar double-precision FP.
       int mod, regop, rm;
       get_modrm(*current, &mod, &regop, &rm);
-      AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
+      Print("cvtss2sd %s,", NameOfXMMRegister(regop));
       current += PrintRightXMMOperand(current);
     } else if (opcode == 0x7E) {
       int mod, regop, rm;
       get_modrm(*current, &mod, &regop, &rm);
-      AppendToBuffer("movq %s, ", NameOfXMMRegister(regop));
+      Print("movq %s, ", NameOfXMMRegister(regop));
       current += PrintRightXMMOperand(current);
     } else if (opcode == 0x58) {
       int mod, regop, rm;
       get_modrm(*current, &mod, &regop, &rm);
-      AppendToBuffer("addss %s,", NameOfXMMRegister(regop));
+      Print("addss %s,", NameOfXMMRegister(regop));
       current += PrintRightXMMOperand(current);
     } else {
       UnimplementedInstruction();
@@ -1417,42 +1421,42 @@
     } else if (mod == 2) {  // 32-bit displacement.
       current += 4;
     }  // else no immediate displacement.
-    AppendToBuffer("nop");
+    Print("nop");
 
   } else if (opcode == 0x28) {
     // movaps xmm, xmm/m128
     int mod, regop, rm;
     get_modrm(*current, &mod, &regop, &rm);
-    AppendToBuffer("movaps %s, ", NameOfXMMRegister(regop));
+    Print("movaps %s, ", NameOfXMMRegister(regop));
     current += PrintRightXMMOperand(current);
   } else if (opcode == 0x29) {
     // movaps xmm/m128, xmm
     int mod, regop, rm;
     get_modrm(*current, &mod, &regop, &rm);
-    AppendToBuffer("movaps ");
+    Print("movaps ");
     current += PrintRightXMMOperand(current);
-    AppendToBuffer(", %s", NameOfXMMRegister(regop));
+    Print(", %s", NameOfXMMRegister(regop));
   } else if (opcode == 0x11) {
     // movups xmm/m128, xmm
     int mod, regop, rm;
     get_modrm(*current, &mod, &regop, &rm);
-    AppendToBuffer("movups ");
+    Print("movups ");
     current += PrintRightXMMOperand(current);
-    AppendToBuffer(", %s", NameOfXMMRegister(regop));
+    Print(", %s", NameOfXMMRegister(regop));
   } else if (opcode == 0x10) {
     // movups xmm, xmm/m128
     int mod, regop, rm;
     get_modrm(*current, &mod, &regop, &rm);
-    AppendToBuffer("movups %s, ", NameOfXMMRegister(regop));
+    Print("movups %s, ", NameOfXMMRegister(regop));
     current += PrintRightXMMOperand(current);
   } else if (opcode == 0x50) {
     int mod, regop, rm;
     get_modrm(*current, &mod, &regop, &rm);
-    AppendToBuffer("movmskps %s,", NameOfCPURegister(regop));
+    Print("movmskps %s,", NameOfCPURegister(regop));
     current += PrintRightXMMOperand(current);
   } else if (opcode == 0xA2 || opcode == 0x31) {
     // RDTSC or CPUID
-    AppendToBuffer("%s", mnemonic);
+    Print("%s", mnemonic);
 
   } else if ((opcode & 0xF0) == 0x40) {
     // CMOVcc: conditional move.
@@ -1490,19 +1494,19 @@
     }
     int mod, regop, rm;
     get_modrm(*current, &mod, &regop, &rm);
-    AppendToBuffer("%s %s, ", mnemonic, NameOfXMMRegister(regop));
+    Print("%s %s, ", mnemonic, NameOfXMMRegister(regop));
     current += PrintRightXMMOperand(current);
   } else if (opcode == 0xC2 || opcode == 0xC6) {
     int mod, regop, rm;
     get_modrm(*current, &mod, &regop, &rm);
     if (opcode == 0xC2) {
-      AppendToBuffer("cmpps %s, ", NameOfXMMRegister(regop));
+      Print("cmpps %s, ", NameOfXMMRegister(regop));
     } else {
       ASSERT(opcode == 0xC6);
-      AppendToBuffer("shufps %s, ", NameOfXMMRegister(regop));
+      Print("shufps %s, ", NameOfXMMRegister(regop));
     }
     current += PrintRightXMMOperand(current);
-    AppendToBuffer(" [%x]", *current);
+    Print(" [%x]", *current);
     current++;
   } else if ((opcode & 0xF0) == 0x80) {
     // Jcc: Conditional jump (branch).
@@ -1521,17 +1525,17 @@
   } else if (((opcode & 0xFE) == 0xA4) || ((opcode & 0xFE) == 0xAC) ||
              (opcode == 0xAB) || (opcode == 0xA3) || (opcode == 0xBD)) {
     // SHLD, SHRD (double-prec. shift), BTS (bit test and set), BT (bit test).
-    AppendToBuffer("%s%c ", mnemonic, operand_size_code());
+    Print("%s%c ", mnemonic, operand_size_code());
     int mod, regop, rm;
     get_modrm(*current, &mod, &regop, &rm);
     current += PrintRightOperand(current);
-    AppendToBuffer(",%s", NameOfCPURegister(regop));
+    Print(",%s", NameOfCPURegister(regop));
     if ((opcode == 0xAB) || (opcode == 0xA3) || (opcode == 0xBD)) {
       // Done.
     } else if ((opcode == 0xA5) || (opcode == 0xAD)) {
-      AppendToBuffer(",cl");
+      Print(",cl");
     } else {
-      AppendToBuffer(",");
+      Print(",");
       current += PrintImmediate(current, BYTE_SIZE);
     }
   } else {
@@ -1607,14 +1611,15 @@
   if (!processed) {
     switch (*data) {
       case 0xC2:
-        AppendToBuffer("ret %#x", *reinterpret_cast<uint16_t*>(data + 1));
+        Print("ret ");
+        PrintImmediateValue(*reinterpret_cast<uint16_t*>(data + 1));
         data += 3;
         break;
 
       case 0xC8:
-        AppendToBuffer("enter %d, %d",
-                       *reinterpret_cast<uint16_t*>(data + 1),
-                       data[3]);
+        Print("enter %d, %d",
+              *reinterpret_cast<uint16_t*>(data + 1),
+              data[3]);
         data += 4;
         break;
 
@@ -1624,10 +1629,11 @@
         get_modrm(*(data + 1), &mod, &regop, &rm);
         int32_t imm = *data == 0x6B ? *(data + 2)
             : *reinterpret_cast<int32_t*>(data + 2);
-        AppendToBuffer("imul%c %s,%s,%#x",
-                       operand_size_code(),
-                       NameOfCPURegister(regop),
-                       NameOfCPURegister(rm), imm);
+        Print("imul%c %s,%s,",
+              operand_size_code(),
+              NameOfCPURegister(regop),
+              NameOfCPURegister(rm));
+        PrintImmediateValue(imm);
         data += 2 + (*data == 0x6B ? 1 : 4);
         break;
       }
@@ -1646,7 +1652,7 @@
         int mod, regop, rm;
         get_modrm(*data, &mod, &regop, &rm);
         if (regop == 0) {
-          AppendToBuffer("pop ");
+          Print("pop ");
           data += PrintRightOperand(data);
         }
       }
@@ -1677,9 +1683,9 @@
             mnem = "???";
         }
         if (regop <= 1) {
-          AppendToBuffer("%s%c ", mnem, operand_size_code());
+          Print("%s%c ", mnem, operand_size_code());
         } else {
-          AppendToBuffer("%s ", mnem);
+          Print("%s ", mnem);
         }
         data += PrintRightOperand(data);
       }
@@ -1691,16 +1697,18 @@
         bool is_byte = *data == 0xC6;
         data++;
         if (is_byte) {
-          AppendToBuffer("movb ");
+          Print("movb ");
           data += PrintRightByteOperand(data);
           int32_t imm = *data;
-          AppendToBuffer(",%#x", imm);
+          Print(",");
+          PrintImmediateValue(imm);
           data++;
         } else {
-          AppendToBuffer("mov%c ", operand_size_code());
+          Print("mov%c ", operand_size_code());
           data += PrintRightOperand(data);
           int32_t imm = *reinterpret_cast<int32_t*>(data);
-          AppendToBuffer(",%#x", imm);
+          Print(",");
+          PrintImmediateValue(imm);
           data += 4;
         }
       }
@@ -1708,10 +1716,11 @@
 
       case 0x80: {
         data++;
-        AppendToBuffer("cmpb ");
+        Print("cmpb ");
         data += PrintRightByteOperand(data);
         int32_t imm = *data;
-        AppendToBuffer(",%#x", imm);
+        Print(",");
+        PrintImmediateValue(imm);
         data++;
       }
         break;
@@ -1724,13 +1733,13 @@
         data++;
         get_modrm(*data, &mod, &regop, &rm);
         if (is_byte) {
-          AppendToBuffer("movb ");
+          Print("movb ");
           data += PrintRightByteOperand(data);
-          AppendToBuffer(",%s", NameOfByteCPURegister(regop));
+          Print(",%s", NameOfByteCPURegister(regop));
         } else {
-          AppendToBuffer("mov%c ", operand_size_code());
+          Print("mov%c ", operand_size_code());
           data += PrintRightOperand(data);
-          AppendToBuffer(",%s", NameOfCPURegister(regop));
+          Print(",%s", NameOfCPURegister(regop));
         }
       }
         break;
@@ -1745,11 +1754,9 @@
       case 0x97: {
         int reg = (*data & 0x7) | (rex_b() ? 8 : 0);
         if (reg == 0) {
-          AppendToBuffer("nop");  // Common name for xchg rax,rax.
+          Print("nop");  // Common name for xchg rax,rax.
         } else {
-          AppendToBuffer("xchg%c rax, %s",
-                         operand_size_code(),
-                         NameOfCPURegister(reg));
+          Print("xchg%c rax, %s", operand_size_code(), NameOfCPURegister(reg));
         }
         data++;
       }
@@ -1776,13 +1783,10 @@
         uint8_t is_32bit = (opcode >= 0xB8);
         int reg = (opcode & 0x7) | (rex_b() ? 8 : 0);
         if (is_32bit) {
-          AppendToBuffer("mov%c %s, ",
-                         operand_size_code(),
-                         NameOfCPURegister(reg));
+          Print("mov%c %s,", operand_size_code(), NameOfCPURegister(reg));
           data += PrintImmediate(data, DOUBLEWORD_SIZE);
         } else {
-          AppendToBuffer("movb %s, ",
-                         NameOfByteCPURegister(reg));
+          Print("movb %s,", NameOfByteCPURegister(reg));
           data += PrintImmediate(data, BYTE_SIZE);
         }
         break;
@@ -1792,7 +1796,7 @@
         int mod, regop, rm;
         get_modrm(*data, &mod, &regop, &rm);
         if (regop == 1) {
-          AppendToBuffer("decb ");
+          Print("decb ");
           data += PrintRightByteOperand(data);
         } else {
           UnimplementedInstruction();
@@ -1800,12 +1804,14 @@
         break;
       }
       case 0x68:
-        AppendToBuffer("push %#x", *reinterpret_cast<int32_t*>(data + 1));
+        Print("push ");
+        PrintImmediateValue(*reinterpret_cast<int32_t*>(data + 1));
         data += 5;
         break;
 
       case 0x6A:
-        AppendToBuffer("push %#x", *reinterpret_cast<int8_t*>(data + 1));
+        Print("push ");
+        PrintImmediateValue(*reinterpret_cast<int8_t*>(data + 1));
         data += 2;
         break;
 
@@ -1813,21 +1819,21 @@
       case 0xA3:
         switch (operand_size()) {
           case DOUBLEWORD_SIZE: {
-            AppendAddressToBuffer(
+            PrintAddress(
                 reinterpret_cast<uint8_t*>(
                     *reinterpret_cast<int32_t*>(data + 1)));
             if (*data == 0xA1) {  // Opcode 0xA1
-              AppendToBuffer("movzxlq rax,(");
-              AppendAddressToBuffer(
+              Print("movzxlq rax,(");
+              PrintAddress(
                   reinterpret_cast<uint8_t*>(
                       *reinterpret_cast<int32_t*>(data + 1)));
-              AppendToBuffer(")");
+              Print(")");
             } else {  // Opcode 0xA3
-              AppendToBuffer("movzxlq (");
-              AppendAddressToBuffer(
+              Print("movzxlq (");
+              PrintAddress(
                   reinterpret_cast<uint8_t*>(
                       *reinterpret_cast<int32_t*>(data + 1)));
-              AppendToBuffer("),rax");
+              Print("),rax");
            }
             data += 5;
             break;
@@ -1835,13 +1841,13 @@
           case QUADWORD_SIZE: {
             // New x64 instruction mov rax,(imm_64).
             if (*data == 0xA1) {  // Opcode 0xA1
-              AppendToBuffer("movq rax,(");
-              AppendAddressToBuffer(*reinterpret_cast<uint8_t**>(data + 1));
-              AppendToBuffer(")");
+              Print("movq rax,(");
+              PrintAddress(*reinterpret_cast<uint8_t**>(data + 1));
+              Print(")");
             } else {  // Opcode 0xA3
-              AppendToBuffer("movq (");
-              AppendAddressToBuffer(*reinterpret_cast<uint8_t**>(data + 1));
-              AppendToBuffer("),rax");
+              Print("movq (");
+              PrintAddress(*reinterpret_cast<uint8_t**>(data + 1));
+              Print("),rax");
             }
             data += 9;
             break;
@@ -1853,7 +1859,8 @@
         break;
 
       case 0xA8:
-        AppendToBuffer("test al,%#x", *reinterpret_cast<uint8_t*>(data + 1));
+        Print("test al,");
+        PrintImmediateValue(*reinterpret_cast<uint8_t*>(data + 1));
         data += 2;
         break;
 
@@ -1875,9 +1882,8 @@
           default:
             UNREACHABLE();
         }
-        AppendToBuffer("test%c rax,%#" Px64 "",
-                       operand_size_code(),
-                       value);
+        Print("test%c rax,", operand_size_code());
+        PrintImmediateValue(value);
         break;
       }
       case 0xD1:  // fall through
diff --git a/runtime/vm/find_code_object_test.cc b/runtime/vm/find_code_object_test.cc
index bac5c1e..b7e437b 100644
--- a/runtime/vm/find_code_object_test.cc
+++ b/runtime/vm/find_code_object_test.cc
@@ -16,10 +16,14 @@
 VM_TEST_CASE(FindCodeObject) {
 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
   const int kLoopCount = 50000;
+  const int kScriptSize = 512 * KB;
+#elif defined(TARGET_ARCH_DBC)
+  const int kLoopCount = 60000;
+  const int kScriptSize = 1 * MB;
 #else
   const int kLoopCount = 25000;
-#endif
   const int kScriptSize = 512 * KB;
+#endif
   const int kNumFunctions = 1024;
   char scriptChars[kScriptSize];
 
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index bbc7f05..58a5c6a 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -5,6 +5,12 @@
 #ifndef VM_FLAG_LIST_H_
 #define VM_FLAG_LIST_H_
 
+#if defined(TARGET_ARCH_DBC)
+#define USING_DBC 1
+#else
+#define USING_DBC 0
+#endif
+
 // List of all flags in the VM.
 // Flags can be one of three categories:
 // * P roduct flags: Can be set in any of the deployment modes, including in
@@ -21,12 +27,12 @@
 //   R(name, product_value, type, default_value, comment)
 //   C(name, precompiled_value, product_value, type, default_value, comment)
 #define FLAG_LIST(P, R, D, C)                                                  \
-P(allow_absolute_addresses, bool, true,                                        \
-  "Allow embedding absolute addresses in generated code.")                     \
 P(always_megamorphic_calls, bool, false,                                       \
   "Instance call always as megamorphic.")                                      \
-C(background_compilation, false, false, bool, false,                           \
+C(background_compilation, false, true, bool, true,                             \
   "Run optimizing compilation in background")                                  \
+R(background_compilation_stop_alot, false, bool, false,                        \
+  "Stress test system: stop background compiler often.")                       \
 R(break_at_isolate_spawn, false, bool, false,                                  \
   "Insert a one-time breakpoint at the entrypoint for all spawned isolates")   \
 C(collect_code, false, true, bool, true,                                       \
@@ -70,9 +76,9 @@
   "Ratio of getter/setter usage used for double field unboxing heuristics")    \
 P(guess_icdata_cid, bool, true,                                                \
   "Artificially create type feedback for arithmetic etc. operations")          \
-P(ic_range_profiling, bool, true,                                              \
+P(ic_range_profiling, bool, !USING_DBC,                                        \
   "Generate special IC stubs collecting range information ")                   \
-P(interpret_irregexp, bool, false,                                             \
+P(interpret_irregexp, bool, USING_DBC,                                         \
   "Use irregexp bytecode interpreter")                                         \
 P(lazy_dispatchers, bool, true,                                                \
   "Generate dispatchers lazily")                                               \
@@ -119,7 +125,7 @@
   "Print live ranges after allocation.")                                       \
 C(print_stop_message, false, false, bool, false,                               \
   "Print stop message.")                                                       \
-R(profiler, false, bool, true,                                                 \
+R(profiler, false, bool, !USING_DBC,                                           \
   "Enable the profiler.")                                                      \
 P(reorder_basic_blocks, bool, true,                                            \
   "Reorder basic blocks")                                                      \
@@ -159,7 +165,7 @@
   "Optimize left shift to truncate if possible")                               \
 P(use_cha_deopt, bool, true,                                                   \
   "Use class hierarchy analysis even if it can cause deoptimization.")         \
-P(use_field_guards, bool, true,                                                \
+P(use_field_guards, bool, !USING_DBC,                                          \
   "Use field guards and track field types")                                    \
 C(use_osr, false, true, bool, true,                                            \
   "Use OSR")                                                                   \
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 1f428174..69f7f16 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -1460,54 +1460,6 @@
 }
 
 
-static const String& BinaryOpAndMaskName(BinaryOpNode* node) {
-  if (node->kind() == Token::kSHL) {
-    return Library::PrivateCoreLibName(Symbols::_leftShiftWithMask32());
-  }
-  UNIMPLEMENTED();
-  return String::ZoneHandle(Thread::Current()->zone(), String::null());
-}
-
-
-// <Expression> :: BinaryOp { kind:  Token::Kind
-//                            left:  <Expression>
-//                            right: <Expression>
-//                            mask32: constant }
-void EffectGraphVisitor::VisitBinaryOpWithMask32Node(
-    BinaryOpWithMask32Node* node) {
-  ASSERT((node->kind() != Token::kAND) && (node->kind() != Token::kOR));
-  ValueGraphVisitor for_left_value(owner());
-  node->left()->Visit(&for_left_value);
-  Append(for_left_value);
-  PushArgumentInstr* push_left = PushArgument(for_left_value.value());
-
-  ValueGraphVisitor for_right_value(owner());
-  node->right()->Visit(&for_right_value);
-  Append(for_right_value);
-  PushArgumentInstr* push_right = PushArgument(for_right_value.value());
-
-  Value* mask_value = Bind(new(Z) ConstantInstr(
-      Integer::ZoneHandle(Z, Integer::New(node->mask32(), Heap::kOld))));
-  PushArgumentInstr* push_mask = PushArgument(mask_value);
-
-  ZoneGrowableArray<PushArgumentInstr*>* arguments =
-      new(Z) ZoneGrowableArray<PushArgumentInstr*>(3);
-  arguments->Add(push_left);
-  arguments->Add(push_right);
-  // Call to special method 'BinaryOpAndMaskName(node)'.
-  arguments->Add(push_mask);
-  const intptr_t kNumArgsChecked = 2;
-  InstanceCallInstr* call = new(Z) InstanceCallInstr(node->token_pos(),
-                                                     BinaryOpAndMaskName(node),
-                                                     Token::kILLEGAL,
-                                                     arguments,
-                                                     Object::null_array(),
-                                                     kNumArgsChecked,
-                                                     owner()->ic_data_array());
-  ReturnDefinition(call);
-}
-
-
 void EffectGraphVisitor::BuildTypecheckPushArguments(
     TokenPosition token_pos,
     PushArgumentInstr** push_instantiator_type_arguments_result) {
@@ -3499,6 +3451,8 @@
         load->set_is_immutable(kind != MethodRecognizer::kGrowableArrayLength);
         return ReturnDefinition(load);
       }
+#if !defined(TARGET_ARCH_DBC)
+      // TODO(vegorov) add bytecode to support this method.
       case MethodRecognizer::kClassIDgetID: {
         LocalVariable* value_var =
             node->scope()->LookupVariable(Symbols::Value(), true);
@@ -3506,6 +3460,7 @@
         LoadClassIdInstr* load = new(Z) LoadClassIdInstr(value);
         return ReturnDefinition(load);
       }
+#endif
       case MethodRecognizer::kGrowableArrayCapacity: {
         Value* receiver = Bind(BuildLoadThisVar(node->scope(), token_pos));
         LoadFieldInstr* data_load = new(Z) LoadFieldInstr(
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index cfdf133..6632df8 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -79,7 +79,6 @@
     FLAG_inlining_constant_arguments_max_size_threshold = 100;
     FLAG_inlining_constant_arguments_min_size_threshold = 30;
 
-    FLAG_allow_absolute_addresses = false;
     FLAG_always_megamorphic_calls = true;
     FLAG_collect_dynamic_function_names = true;
     FLAG_fields_may_be_reset = true;
@@ -503,7 +502,7 @@
       continue;
     }
 
-#if defined(DEBUG)
+#if defined(DEBUG) && !defined(TARGET_ARCH_DBC)
     if (!is_optimizing()) {
       FrameStateClear();
     }
@@ -557,14 +556,14 @@
         EndCodeSourceRange(instr->token_pos());
       }
 
-#if defined(DEBUG)
+#if defined(DEBUG) && !defined(TARGET_ARCH_DBC)
       if (!is_optimizing()) {
         FrameStateUpdateWith(instr);
       }
 #endif
     }
 
-#if defined(DEBUG)
+#if defined(DEBUG) && !defined(TARGET_ARCH_DBC)
     ASSERT(is_optimizing() || FrameStateIsSafeToCall());
 #endif
   }
@@ -1147,14 +1146,18 @@
 }
 
 
+// DBC is very different from other architectures in how it performs instance
+// and static calls because it does not use stubs.
+#if !defined(TARGET_ARCH_DBC)
 void FlowGraphCompiler::GenerateInstanceCall(
     intptr_t deopt_id,
     TokenPosition token_pos,
     intptr_t argument_count,
     LocationSummary* locs,
     const ICData& ic_data_in) {
-  const ICData& ic_data = ICData::ZoneHandle(ic_data_in.Original());
+  ICData& ic_data = ICData::ZoneHandle(ic_data_in.Original());
   if (FLAG_precompiled_mode) {
+    ic_data = ic_data.AsUnaryClassChecks();
     EmitSwitchableInstanceCall(ic_data, argument_count,
                                deopt_id, token_pos, locs);
     return;
@@ -1285,7 +1288,7 @@
   CheckClassIds(kClassIdReg, args, is_instance_lbl, &unknown);
   assembler()->Bind(&unknown);
 }
-
+#endif  // !defined(TARGET_ARCH_DBC)
 
 void FlowGraphCompiler::EmitComment(Instruction* instr) {
   if (!FLAG_support_il_printer || !FLAG_support_disassembler) {
@@ -1300,6 +1303,8 @@
 }
 
 
+#if !defined(TARGET_ARCH_DBC)
+// TODO(vegorov) enable edge-counters on DBC if we consider them beneficial.
 bool FlowGraphCompiler::NeedsEdgeCounter(TargetEntryInstr* block) {
   // Only emit an edge counter if there is not goto at the end of the block,
   // except for the entry block.
@@ -1320,18 +1325,17 @@
   UNREACHABLE();
   return kNoRegister;
 }
-
-
-static uword RegMaskBit(Register reg) {
-  return ((reg) != kNoRegister) ? (1 << (reg)) : 0;
-}
+#endif
 
 
 void FlowGraphCompiler::AllocateRegistersLocally(Instruction* instr) {
   ASSERT(!is_optimizing());
-
   instr->InitializeLocationSummary(zone(),
                                    false);  // Not optimizing.
+
+  // No need to allocate registers based on LocationSummary on DBC as in
+  // unoptimized mode it's a stack based bytecode just like IR itself.
+#if !defined(TARGET_ARCH_DBC)
   LocationSummary* locs = instr->locs();
 
   bool blocked_registers[kNumberOfCpuRegisters];
@@ -1421,6 +1425,12 @@
     }
     locs->set_out(0, result_location);
   }
+#endif  // !defined(TARGET_ARCH_DBC)
+}
+
+
+static uword RegMaskBit(Register reg) {
+  return ((reg) != kNoRegister) ? (1 << (reg)) : 0;
 }
 
 
@@ -1837,6 +1847,9 @@
 }
 
 
+#if !defined(TARGET_ARCH_DBC)
+// DBC emits calls very differently from other architectures due to its
+// interpreted nature.
 void FlowGraphCompiler::EmitPolymorphicInstanceCall(
     const ICData& ic_data,
     intptr_t argument_count,
@@ -1880,9 +1893,12 @@
     }
   }
 }
+#endif
 
-
-#if defined(DEBUG)
+#if defined(DEBUG) && !defined(TARGET_ARCH_DBC)
+// TODO(vegorov) re-enable frame state tracking on DBC. It is
+// currently disabled because it relies on LocationSummaries and
+// we don't use them during unoptimized compilation on DBC.
 void FlowGraphCompiler::FrameStateUpdateWith(Instruction* instr) {
   ASSERT(!is_optimizing());
 
@@ -1953,7 +1969,7 @@
   ASSERT(!is_optimizing());
   frame_state_.TruncateTo(0);
 }
-#endif
+#endif  // defined(DEBUG) && !defined(TARGET_ARCH_DBC)
 
 
 }  // namespace dart
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index 7c1fa0e..586dbdb 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -367,6 +367,15 @@
   // Returns 'true' if regular code generation should be skipped.
   bool TryIntrinsify();
 
+  void GenerateAssertAssignable(TokenPosition token_pos,
+                                intptr_t deopt_id,
+                                const AbstractType& dst_type,
+                                const String& dst_name,
+                                LocationSummary* locs);
+
+  // DBC emits calls very differently from all other architectures due to its
+  // interpreted nature.
+#if !defined(TARGET_ARCH_DBC)
   void GenerateRuntimeCall(TokenPosition token_pos,
                            intptr_t deopt_id,
                            const RuntimeEntry& entry,
@@ -390,12 +399,6 @@
                               LocationSummary* locs,
                               const Function& target);
 
-  void GenerateAssertAssignable(TokenPosition token_pos,
-                                intptr_t deopt_id,
-                                const AbstractType& dst_type,
-                                const String& dst_name,
-                                LocationSummary* locs);
-
   void GenerateInstanceOf(TokenPosition token_pos,
                           intptr_t deopt_id,
                           const AbstractType& type,
@@ -426,12 +429,6 @@
   void GenerateListTypeCheck(Register kClassIdReg,
                              Label* is_instance_lbl);
 
-  void EmitComment(Instruction* instr);
-
-  bool NeedsEdgeCounter(TargetEntryInstr* block);
-
-  void EmitEdgeCounter(intptr_t edge_id);
-
   void EmitOptimizedInstanceCall(const StubEntry& stub_entry,
                                  const ICData& ic_data,
                                  intptr_t argument_count,
@@ -489,8 +486,15 @@
                                       bool needs_number_check,
                                       TokenPosition token_pos);
 
+  bool NeedsEdgeCounter(TargetEntryInstr* block);
+
+  void EmitEdgeCounter(intptr_t edge_id);
+#endif  // !defined(TARGET_ARCH_DBC)
+
   void EmitTrySync(Instruction* instr, intptr_t try_index);
 
+  void EmitComment(Instruction* instr);
+
   intptr_t StackSize() const;
 
   // Returns assembler label associated with the given block entry.
@@ -637,6 +641,9 @@
                                  LocationSummary* locs,
                                  const ICData& ic_data);
 
+  // DBC handles type tests differently from all other architectures due
+  // to its interpreted nature.
+#if !defined(TARGET_ARCH_DBC)
   // Type checking helper methods.
   void CheckClassIds(Register class_id_reg,
                      const GrowableArray<intptr_t>& class_ids,
@@ -690,6 +697,7 @@
   void GenerateBoolToJump(Register bool_reg, Label* is_true, Label* is_false);
 
   void CopyParameters();
+#endif  // !defined(TARGET_ARCH_DBC)
 
   void GenerateInlinedGetter(intptr_t offset);
   void GenerateInlinedSetter(intptr_t offset);
@@ -722,7 +730,10 @@
     return stackmap_table_builder_;
   }
 
-#if defined(DEBUG)
+  // TODO(vegorov) re-enable frame state tracking on DBC. It is
+  // currently disabled because it relies on LocationSummaries and
+  // we don't use them during unoptimized compilation on DBC.
+#if defined(DEBUG) && !defined(TARGET_ARCH_DBC)
   void FrameStateUpdateWith(Instruction* instr);
   void FrameStatePush(Definition* defn);
   void FrameStatePop(intptr_t count);
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index ace14d0..9c58044 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -1319,7 +1319,30 @@
       MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
 
   __ Comment("MegamorphicCall");
+  // Load receiver into R0.
   __ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize);
+  Label done;
+  if (name.raw() == Symbols::hashCode().raw()) {
+    Label megamorphic_call;
+    __ Comment("Inlined get:hashCode for Smi and OneByteString");
+    __ tst(R0, Operand(kSmiTagMask));
+    __ b(&done, EQ);  // Is Smi (result is receiver).
+
+    // Use R9 (cache for megamorphic call) as scratch.
+    __ CompareClassId(R0, kOneByteStringCid, R9);
+    __ b(&megamorphic_call, NE);
+
+    __ mov(R9, Operand(R0));  // Preserve receiver in R9.
+    __ ldr(R0, FieldAddress(R0, String::hash_offset()));
+    ASSERT(Smi::New(0) == 0);
+    __ cmp(R0, Operand(0));
+
+    __ b(&done, NE);  // Return if already computed.
+    __ mov(R0, Operand(R9));  // Restore receiver in R0.
+
+    __ Bind(&megamorphic_call);
+    __ Comment("Slow case: megamorphic call");
+  }
   __ LoadObject(R9, cache);
   if (FLAG_use_megamorphic_stub) {
     __ BranchLink(*StubCode::MegamorphicLookup_entry());
@@ -1328,6 +1351,7 @@
   }
   __ blx(R1);
 
+  __ Bind(&done);
   RecordSafepoint(locs, slow_path_argument_count);
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
   if (FLAG_precompiled_mode) {
@@ -1365,21 +1389,9 @@
     LocationSummary* locs) {
   __ Comment("SwitchableCall");
   __ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize);
-  if (ic_data.NumArgsTested() == 1) {
-    __ LoadUniqueObject(R9, ic_data);
-    __ BranchLinkPatchable(*StubCode::ICLookupThroughFunction_entry());
-  } else {
-    const String& name = String::Handle(zone(), ic_data.target_name());
-    const Array& arguments_descriptor =
-        Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
-    ASSERT(!arguments_descriptor.IsNull() &&
-           (arguments_descriptor.Length() > 0));
-    const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(),
-        MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
-
-    __ LoadUniqueObject(R9, cache);
-    __ BranchLinkPatchable(*StubCode::MegamorphicLookup_entry());
-  }
+  ASSERT(ic_data.NumArgsTested() == 1);
+  __ LoadUniqueObject(R9, ic_data);
+  __ BranchLinkPatchable(*StubCode::ICLookupThroughFunction_entry());
   __ blx(R1);
 
   AddCurrentDescriptor(RawPcDescriptors::kOther, Thread::kNoDeoptId, token_pos);
@@ -1516,7 +1528,7 @@
       if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) {
         DRegister d1 = EvenDRegisterOf(fpu_reg);
         DRegister d2 = OddDRegisterOf(fpu_reg);
-        // TOOD(regis): merge stores using vstmd instruction.
+        // TODO(regis): merge stores using vstmd instruction.
         __ vstrd(d1, Address(SP, offset));
         __ vstrd(d2, Address(SP, offset + 2 * kWordSize));
         offset += kFpuRegisterSize;
@@ -1562,7 +1574,7 @@
       if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) {
         DRegister d1 = EvenDRegisterOf(fpu_reg);
         DRegister d2 = OddDRegisterOf(fpu_reg);
-        // TOOD(regis): merge loads using vldmd instruction.
+        // TODO(regis): merge loads using vldmd instruction.
         __ vldrd(d1, Address(SP, offset));
         __ vldrd(d2, Address(SP, offset + 2 * kWordSize));
         offset += kFpuRegisterSize;
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index f872532..d62a23a 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -1300,7 +1300,29 @@
       MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
 
   __ Comment("MegamorphicCall");
+  // Load receiver into R0.
   __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize);
+  Label done;
+  if (name.raw() == Symbols::hashCode().raw()) {
+    Label megamorphic_call;
+    __ Comment("Inlined get:hashCode for Smi and OneByteString");
+    __ tsti(R0, Immediate(kSmiTagMask));
+    __ b(&done, EQ);  // Is Smi (result is receiver).
+
+    __ CompareClassId(R0, kOneByteStringCid);
+    __ b(&megamorphic_call, NE);
+
+    // Use R5 (cache for megamorphic call) as scratch.
+    __ mov(R5, R0);  // Preserve receiver in R5, result in R0.
+    __ ldr(R0, FieldAddress(R0, String::hash_offset()));
+    __ CompareRegisters(R0, ZR);
+    __ b(&done, NE);
+    __ mov(R0, R5);  // Restore receiver in R0,
+
+    __ Bind(&megamorphic_call);
+    __ Comment("Slow case: megamorphic call");
+  }
+
   __ LoadObject(R5, cache);
   if (FLAG_use_megamorphic_stub) {
     __ BranchLink(*StubCode::MegamorphicLookup_entry());
@@ -1309,6 +1331,7 @@
   }
   __ blr(R1);
 
+  __ Bind(&done);
   RecordSafepoint(locs, slow_path_argument_count);
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
   if (FLAG_precompiled_mode) {
@@ -1345,21 +1368,9 @@
     LocationSummary* locs) {
   __ Comment("SwitchableCall");
   __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize);
-  if (ic_data.NumArgsTested() == 1) {
-    __ LoadUniqueObject(R5, ic_data);
-    __ BranchLinkPatchable(*StubCode::ICLookupThroughFunction_entry());
-  } else {
-    const String& name = String::Handle(zone(), ic_data.target_name());
-    const Array& arguments_descriptor =
-        Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
-    ASSERT(!arguments_descriptor.IsNull() &&
-           (arguments_descriptor.Length() > 0));
-    const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(),
-        MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
-
-    __ LoadUniqueObject(R5, cache);
-    __ BranchLinkPatchable(*StubCode::MegamorphicLookup_entry());
-  }
+  ASSERT(ic_data.NumArgsTested() == 1);
+  __ LoadUniqueObject(R5, ic_data);
+  __ BranchLinkPatchable(*StubCode::ICLookupThroughFunction_entry());
   __ blr(R1);
 
   AddCurrentDescriptor(RawPcDescriptors::kOther,
diff --git a/runtime/vm/flow_graph_compiler_dbc.cc b/runtime/vm/flow_graph_compiler_dbc.cc
new file mode 100644
index 0000000..2f3ff8e
--- /dev/null
+++ b/runtime/vm/flow_graph_compiler_dbc.cc
@@ -0,0 +1,331 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h"  // Needed here to get TARGET_ARCH_DBC.
+#if defined(TARGET_ARCH_DBC)
+
+#include "vm/flow_graph_compiler.h"
+
+#include "vm/ast_printer.h"
+#include "vm/compiler.h"
+#include "vm/cpu.h"
+#include "vm/dart_entry.h"
+#include "vm/deopt_instructions.h"
+#include "vm/il_printer.h"
+#include "vm/instructions.h"
+#include "vm/locations.h"
+#include "vm/object_store.h"
+#include "vm/parser.h"
+#include "vm/stack_frame.h"
+#include "vm/stub_code.h"
+#include "vm/symbols.h"
+#include "vm/verified_memory.h"
+
+namespace dart {
+
+DEFINE_FLAG(bool, trap_on_deoptimization, false, "Trap on deoptimization.");
+DEFINE_FLAG(bool, unbox_mints, true, "Optimize 64-bit integer arithmetic.");
+DEFINE_FLAG(bool, unbox_doubles, true, "Optimize double arithmetic.");
+DECLARE_FLAG(bool, enable_simd_inline);
+DECLARE_FLAG(bool, use_megamorphic_stub);
+DECLARE_FLAG(charp, optimization_filter);
+
+void MegamorphicSlowPath::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
+FlowGraphCompiler::~FlowGraphCompiler() {
+  // BlockInfos are zone-allocated, so their destructors are not called.
+  // Verify the labels explicitly here.
+  for (int i = 0; i < block_info_.length(); ++i) {
+    ASSERT(!block_info_[i]->jump_label()->IsLinked());
+  }
+}
+
+
+bool FlowGraphCompiler::SupportsUnboxedDoubles() {
+  return false;
+}
+
+
+bool FlowGraphCompiler::SupportsUnboxedMints() {
+  return false;
+}
+
+
+bool FlowGraphCompiler::SupportsUnboxedSimd128() {
+  return false;
+}
+
+
+bool FlowGraphCompiler::SupportsSinCos() {
+  return false;
+}
+
+
+bool FlowGraphCompiler::SupportsHardwareDivision() {
+  return true;
+}
+
+
+bool FlowGraphCompiler::CanConvertUnboxedMintToDouble() {
+  return false;
+}
+
+
+void FlowGraphCompiler::EnterIntrinsicMode() {
+  ASSERT(!intrinsic_mode());
+  intrinsic_mode_ = true;
+}
+
+
+void FlowGraphCompiler::ExitIntrinsicMode() {
+  ASSERT(intrinsic_mode());
+  intrinsic_mode_ = false;
+}
+
+
+RawTypedData* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
+                                                 DeoptInfoBuilder* builder,
+                                                 const Array& deopt_table) {
+  UNIMPLEMENTED();
+  return TypedData::null();
+}
+
+
+void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
+                                             intptr_t stub_ix) {
+  UNIMPLEMENTED();
+}
+
+
+#define __ assembler()->
+
+
+void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
+                                                 intptr_t deopt_id,
+                                                 const AbstractType& dst_type,
+                                                 const String& dst_name,
+                                                 LocationSummary* locs) {
+  ASSERT(!is_optimizing());
+  SubtypeTestCache& test_cache = SubtypeTestCache::Handle();
+  if (!dst_type.IsVoidType() && dst_type.IsInstantiated()) {
+    test_cache = SubtypeTestCache::New();
+  }
+
+  __ PushConstant(dst_type);
+  __ PushConstant(dst_name);
+  __ AssertAssignable(__ AddConstant(test_cache));
+  AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id, token_pos);
+}
+
+
+void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
+  if (!is_optimizing()) {
+    Definition* defn = instr->AsDefinition();
+    if ((defn != NULL) &&
+        (defn->tag() != Instruction::kPushArgument) &&
+        (defn->tag() != Instruction::kStoreIndexed) &&
+        (defn->tag() != Instruction::kStoreStaticField) &&
+        (defn->tag() != Instruction::kStoreLocal) &&
+        (defn->tag() != Instruction::kStoreInstanceField) &&
+        (defn->tag() != Instruction::kDropTemps) &&
+        (defn->tag() != Instruction::kPushTemp) &&
+        !defn->HasTemp()) {
+      __ Drop1();
+    }
+  }
+}
+
+
+void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) {
+  __ Move(0, -(1 + kParamEndSlotFromFp));
+  __ LoadField(0, 0, offset / kWordSize);
+  __ Return(0);
+}
+
+
+void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) {
+  __ Move(0, -(2 + kParamEndSlotFromFp));
+  __ Move(1, -(1 + kParamEndSlotFromFp));
+  __ StoreField(0, offset / kWordSize, 1);
+  __ LoadConstant(0, Object::Handle());
+  __ Return(0);
+}
+
+
+void FlowGraphCompiler::EmitFrameEntry() {
+  const Function& function = parsed_function().function();
+  const intptr_t num_fixed_params = function.num_fixed_parameters();
+  const int num_opt_pos_params = function.NumOptionalPositionalParameters();
+  const int num_opt_named_params = function.NumOptionalNamedParameters();
+  const int num_params =
+      num_fixed_params + num_opt_pos_params + num_opt_named_params;
+  const bool has_optional_params = (num_opt_pos_params != 0) ||
+      (num_opt_named_params != 0);
+  const int num_locals = parsed_function().num_stack_locals();
+  const intptr_t context_index =
+      -parsed_function().current_context_var()->index() - 1;
+
+  if (has_optional_params) {
+    __ EntryOpt(num_fixed_params, num_opt_pos_params, num_opt_named_params);
+  } else {
+    __ Entry(num_fixed_params, num_locals, context_index);
+  }
+
+  if (num_opt_named_params != 0) {
+    LocalScope* scope = parsed_function().node_sequence()->scope();
+
+    // Start by alphabetically sorting the names of the optional parameters.
+    LocalVariable** opt_param =
+        zone()->Alloc<LocalVariable*>(num_opt_named_params);
+    int* opt_param_position = zone()->Alloc<int>(num_opt_named_params);
+    for (int pos = num_fixed_params; pos < num_params; pos++) {
+      LocalVariable* parameter = scope->VariableAt(pos);
+      const String& opt_param_name = parameter->name();
+      int i = pos - num_fixed_params;
+      while (--i >= 0) {
+        LocalVariable* param_i = opt_param[i];
+        const intptr_t result = opt_param_name.CompareTo(param_i->name());
+        ASSERT(result != 0);
+        if (result > 0) break;
+        opt_param[i + 1] = opt_param[i];
+        opt_param_position[i + 1] = opt_param_position[i];
+      }
+      opt_param[i + 1] = parameter;
+      opt_param_position[i + 1] = pos;
+    }
+
+    for (intptr_t i = 0; i < num_opt_named_params; i++) {
+      const int param_pos = opt_param_position[i];
+      const Instance& value = parsed_function().DefaultParameterValueAt(
+          param_pos - num_fixed_params);
+      __ LoadConstant(param_pos, opt_param[i]->name());
+      __ LoadConstant(param_pos, value);
+    }
+  } else if (num_opt_pos_params != 0) {
+    for (intptr_t i = 0; i < num_opt_pos_params; i++) {
+      const Object& value = parsed_function().DefaultParameterValueAt(i);
+      __ LoadConstant(num_fixed_params + i, value);
+    }
+  }
+
+
+  ASSERT(num_locals > 0);  // There is always at least context_var.
+  if (has_optional_params) {
+    ASSERT(!is_optimizing());
+    __ Frame(num_locals);  // Reserve space for locals.
+  }
+
+  if (function.IsClosureFunction()) {
+    Register reg = context_index;
+    Register closure_reg = reg;
+    LocalScope* scope = parsed_function().node_sequence()->scope();
+    LocalVariable* local = scope->VariableAt(0);
+    if (local->index() > 0) {
+      __ Move(reg, -local->index());
+    } else {
+      closure_reg = -local->index() - 1;
+    }
+    __ LoadField(reg, closure_reg, Closure::context_offset() / kWordSize);
+  } else if (has_optional_params) {
+    __ LoadConstant(context_index,
+        Object::Handle(isolate()->object_store()->empty_context()));
+  }
+}
+
+
+void FlowGraphCompiler::CompileGraph() {
+  InitCompiler();
+
+  if (TryIntrinsify()) {
+    // Skip regular code generation.
+    return;
+  }
+
+  EmitFrameEntry();
+  VisitBlocks();
+}
+
+
+#undef __
+#define __ compiler_->assembler()->
+
+
+void ParallelMoveResolver::EmitMove(int index) {
+  UNIMPLEMENTED();
+}
+
+
+void ParallelMoveResolver::EmitSwap(int index) {
+  UNIMPLEMENTED();
+}
+
+
+void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst,
+                                              const Address& src) {
+  UNREACHABLE();
+}
+
+
+void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) {
+  UNREACHABLE();
+}
+
+
+// Do not call or implement this function. Instead, use the form below that
+// uses an offset from the frame pointer instead of an Address.
+void ParallelMoveResolver::Exchange(Register reg, const Address& mem) {
+  UNREACHABLE();
+}
+
+
+// Do not call or implement this function. Instead, use the form below that
+// uses offsets from the frame pointer instead of Addresses.
+void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) {
+  UNREACHABLE();
+}
+
+
+void ParallelMoveResolver::Exchange(Register reg,
+                                    Register base_reg,
+                                    intptr_t stack_offset) {
+  UNIMPLEMENTED();
+}
+
+
+void ParallelMoveResolver::Exchange(Register base_reg1,
+                                    intptr_t stack_offset1,
+                                    Register base_reg2,
+                                    intptr_t stack_offset2) {
+  UNIMPLEMENTED();
+}
+
+
+void ParallelMoveResolver::SpillScratch(Register reg) {
+  UNIMPLEMENTED();
+}
+
+
+void ParallelMoveResolver::RestoreScratch(Register reg) {
+  UNIMPLEMENTED();
+}
+
+
+void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) {
+  UNIMPLEMENTED();
+}
+
+
+void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
+  UNIMPLEMENTED();
+}
+
+
+#undef __
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index eac4f3c..8a7c349 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -1300,7 +1300,27 @@
       MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
 
   __ Comment("MegamorphicCall");
+  // Load receiver into EBX.
   __ movl(EBX, Address(ESP, (argument_count - 1) * kWordSize));
+  Label done;
+  if (name.raw() == Symbols::hashCode().raw()) {
+    Label try_onebytestring, megamorphic_call;
+    __ Comment("Inlined get:hashCode for Smi and OneByteString");
+    __ testl(EBX, Immediate(kSmiTagMask));
+    __ j(NOT_ZERO, &try_onebytestring, Assembler::kNearJump);  // Non-smi value.
+    __ movl(EAX, EBX);
+    __ jmp(&done, Assembler::kNearJump);
+
+    __ Bind(&try_onebytestring);
+    __ CompareClassId(EBX, kOneByteStringCid, EAX);
+    __ j(NOT_EQUAL, &megamorphic_call, Assembler::kNearJump);
+    __ movl(EAX, FieldAddress(EBX, String::hash_offset()));
+    __ cmpl(EAX, Immediate(0));
+    __ j(NOT_EQUAL, &done, Assembler::kNearJump);
+
+    __ Bind(&megamorphic_call);
+    __ Comment("Slow case: megamorphic call");
+  }
   __ LoadObject(ECX, cache);
   if (FLAG_use_megamorphic_stub) {
     __ Call(*StubCode::MegamorphicLookup_entry());
@@ -1309,6 +1329,7 @@
   }
   __ call(EBX);
 
+  __ Bind(&done);
   AddCurrentDescriptor(RawPcDescriptors::kOther,
       Thread::kNoDeoptId, token_pos);
   RecordSafepoint(locs, slow_path_argument_count);
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 3ec2756..9fa5d9f 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -1327,7 +1327,28 @@
       MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
 
   __ Comment("MegamorphicCall");
+  // Load receiver into T0,
   __ lw(T0, Address(SP, (argument_count - 1) * kWordSize));
+  Label done;
+  if (name.raw() == Symbols::hashCode().raw()) {
+    Label try_onebytestring, megamorphic_call;
+    __ Comment("Inlined get:hashCode for Smi and OneByteString");
+    __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
+    __ bne(CMPRES1, ZR, &try_onebytestring);  // Not Smi.
+    __ mov(V0, T0);
+    __ b(&done);
+
+    __ Bind(&try_onebytestring);
+    __ LoadClassId(CMPRES1, T0);  // Class ID check.
+    __ BranchNotEqual(
+        CMPRES1, Immediate(kOneByteStringCid), &megamorphic_call);
+
+    __ lw(V0, FieldAddress(T0, String::hash_offset()));
+    __ bne(V0, ZR, &done);
+
+    __ Bind(&megamorphic_call);
+    __ Comment("Slow case: megamorphic call");
+  }
   __ LoadObject(S5, cache);
   if (FLAG_use_megamorphic_stub) {
     __ BranchLink(*StubCode::MegamorphicLookup_entry());
@@ -1336,6 +1357,7 @@
   }
   __ jalr(T1);
 
+  __ Bind(&done);
   RecordSafepoint(locs, slow_path_argument_count);
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
   if (FLAG_precompiled_mode) {
@@ -1372,21 +1394,9 @@
     LocationSummary* locs) {
   __ Comment("SwitchableCall");
   __ lw(T0, Address(SP, (argument_count - 1) * kWordSize));
-  if (ic_data.NumArgsTested() == 1) {
-    __ LoadUniqueObject(S5, ic_data);
-    __ BranchLinkPatchable(*StubCode::ICLookupThroughFunction_entry());
-  } else {
-    const String& name = String::Handle(zone(), ic_data.target_name());
-    const Array& arguments_descriptor =
-        Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
-    ASSERT(!arguments_descriptor.IsNull() &&
-           (arguments_descriptor.Length() > 0));
-    const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(),
-        MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
-
-    __ LoadUniqueObject(S5, cache);
-    __ BranchLinkPatchable(*StubCode::MegamorphicLookup_entry());
-  }
+  ASSERT(ic_data.NumArgsTested() == 1);
+  __ LoadUniqueObject(S5, ic_data);
+  __ BranchLinkPatchable(*StubCode::ICLookupThroughFunction_entry());
   __ jalr(T1);
 
   AddCurrentDescriptor(RawPcDescriptors::kOther,
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index e044923..def75aa 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -1328,9 +1328,28 @@
   ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
   const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(),
       MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
-
   __ Comment("MegamorphicCall");
+  // Load receiver into RDI.
   __ movq(RDI, Address(RSP, (argument_count - 1) * kWordSize));
+  Label done;
+  if (name.raw() == Symbols::hashCode().raw()) {
+    Label try_onebytestring, megamorphic_call;
+    __ Comment("Inlined get:hashCode for Smi and OneByteString");
+    __ testq(RDI, Immediate(kSmiTagMask));
+    __ j(NOT_ZERO, &try_onebytestring, Assembler::kNearJump);  // Non-smi value.
+    __ movq(RAX, RDI);
+    __ jmp(&done, Assembler::kNearJump);
+
+    __ Bind(&try_onebytestring);
+    __ CompareClassId(RDI, kOneByteStringCid);
+    __ j(NOT_EQUAL, &megamorphic_call, Assembler::kNearJump);
+    __ movq(RAX, FieldAddress(RDI, String::hash_offset()));
+    __ cmpq(RAX, Immediate(0));
+    __ j(NOT_EQUAL, &done, Assembler::kNearJump);
+
+    __ Bind(&megamorphic_call);
+    __ Comment("Slow case: megamorphic call");
+  }
   __ LoadObject(RBX, cache);
   if (FLAG_use_megamorphic_stub) {
     __ Call(*StubCode::MegamorphicLookup_entry());
@@ -1339,6 +1358,7 @@
   }
   __ call(RCX);
 
+  __ Bind(&done);
   RecordSafepoint(locs, slow_path_argument_count);
   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
   if (FLAG_precompiled_mode) {
@@ -1375,21 +1395,9 @@
     LocationSummary* locs) {
   __ Comment("SwitchableCall");
   __ movq(RDI, Address(RSP, (argument_count - 1) * kWordSize));
-  if (ic_data.NumArgsTested() == 1) {
-    __ LoadUniqueObject(RBX, ic_data);
-    __ CallPatchable(*StubCode::ICLookupThroughFunction_entry());
-  } else {
-    const String& name = String::Handle(zone(), ic_data.target_name());
-    const Array& arguments_descriptor =
-        Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
-    ASSERT(!arguments_descriptor.IsNull() &&
-           (arguments_descriptor.Length() > 0));
-    const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(),
-        MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
-
-    __ LoadUniqueObject(RBX, cache);
-    __ CallPatchable(*StubCode::MegamorphicLookup_entry());
-  }
+  ASSERT(ic_data.NumArgsTested() == 1);
+  __ LoadUniqueObject(RBX, ic_data);
+  __ CallPatchable(*StubCode::ICLookupThroughFunction_entry());
   __ call(RCX);
 
   AddCurrentDescriptor(RawPcDescriptors::kOther,
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index b1d188a..8accbf4 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -466,6 +466,11 @@
 }
 
 
+CompileType CompileType::Smi() {
+  return Create(kSmiCid, Type::ZoneHandle(Type::SmiType()));
+}
+
+
 CompileType CompileType::String() {
   return FromAbstractType(Type::ZoneHandle(Type::StringType()), kNonNullable);
 }
diff --git a/runtime/vm/hash_table.h b/runtime/vm/hash_table.h
index f4eb375..15317a1 100644
--- a/runtime/vm/hash_table.h
+++ b/runtime/vm/hash_table.h
@@ -137,6 +137,14 @@
     smi_handle_ = Smi::New(0);
     data_->SetAt(kOccupiedEntriesIndex, smi_handle_);
     data_->SetAt(kDeletedEntriesIndex, smi_handle_);
+
+NOT_IN_PRODUCT(
+    data_->SetAt(kNumGrowsIndex, smi_handle_);
+    data_->SetAt(kNumLT5LookupsIndex, smi_handle_);
+    data_->SetAt(kNumLT25LookupsIndex, smi_handle_);
+    data_->SetAt(kNumGT25LookupsIndex, smi_handle_);
+)  // !PRODUCT
+
     for (intptr_t i = kHeaderSize; i < data_->Length(); ++i) {
       data_->SetAt(i, Object::sentinel());
     }
@@ -154,17 +162,21 @@
     const intptr_t num_entries = NumEntries();
     ASSERT(NumOccupied() < num_entries);
     // TODO(koda): Add salt.
+    NOT_IN_PRODUCT(intptr_t collisions = 0;)
     uword hash = KeyTraits::Hash(key);
     intptr_t probe = hash % num_entries;
     // TODO(koda): Consider quadratic probing.
     while (true) {
       if (IsUnused(probe)) {
+        NOT_IN_PRODUCT(UpdateCollisions(collisions);)
         return -1;
       } else if (!IsDeleted(probe)) {
         key_handle_ = GetKey(probe);
         if (KeyTraits::IsMatch(key, key_handle_)) {
+          NOT_IN_PRODUCT(UpdateCollisions(collisions);)
           return probe;
         }
+        NOT_IN_PRODUCT(collisions += 1;)
       }
       // Advance probe.
       probe++;
@@ -183,6 +195,7 @@
     const intptr_t num_entries = NumEntries();
     ASSERT(entry != NULL);
     ASSERT(NumOccupied() < num_entries);
+    NOT_IN_PRODUCT(intptr_t collisions = 0;)
     uword hash = KeyTraits::Hash(key);
     intptr_t probe = hash % num_entries;
     intptr_t deleted = -1;
@@ -190,6 +203,7 @@
     while (true) {
       if (IsUnused(probe)) {
         *entry = (deleted != -1) ? deleted : probe;
+        NOT_IN_PRODUCT(UpdateCollisions(collisions);)
         return false;
       } else if (IsDeleted(probe)) {
         if (deleted == -1) {
@@ -199,8 +213,10 @@
         key_handle_ = GetKey(probe);
         if (KeyTraits::IsMatch(key, key_handle_)) {
           *entry = probe;
+          NOT_IN_PRODUCT(UpdateCollisions(collisions);)
           return true;
         }
+        NOT_IN_PRODUCT(collisions += 1;)
       }
       // Advance probe.
       probe++;
@@ -279,10 +295,63 @@
     return smi_handle_;
   }
 
+NOT_IN_PRODUCT(
+  intptr_t NumGrows() const {
+    return GetSmiValueAt(kNumGrowsIndex);
+  }
+  intptr_t NumLT5Collisions() const {
+    return GetSmiValueAt(kNumLT5LookupsIndex);
+  }
+  intptr_t NumLT25Collisions() const {
+    return GetSmiValueAt(kNumLT25LookupsIndex);
+  }
+  intptr_t NumGT25Collisions() const {
+    return GetSmiValueAt(kNumGT25LookupsIndex);
+  }
+  void UpdateGrowth() const {
+    AdjustSmiValueAt(kNumGrowsIndex, 1);
+  }
+  void UpdateCollisions(intptr_t collisions) const {
+    if (data_->raw()->IsVMHeapObject()) {
+      return;
+    }
+    if (collisions < 5) {
+      AdjustSmiValueAt(kNumLT5LookupsIndex, 1);
+    } else if (collisions < 25) {
+      AdjustSmiValueAt(kNumLT25LookupsIndex, 1);
+    } else {
+      AdjustSmiValueAt(kNumGT25LookupsIndex, 1);
+    }
+  }
+  void PrintStats() const {
+    if (!KeyTraits::ReportStats()) {
+      return;
+    }
+    OS::Print("Stats for %s table :\n"
+              " Size of table = %" Pd ",Number of Occupied entries = %" Pd "\n"
+              " Number of Grows = %" Pd "\n"
+              " Number of look ups with < 5 collisions = %" Pd "\n"
+              " Number of look ups with < 25 collisions = %" Pd "\n"
+              " Number of look ups with > 25 collisions = %" Pd "\n",
+              KeyTraits::Name(),
+              NumEntries(), NumOccupied(),
+              NumGrows(),
+              NumLT5Collisions(), NumLT25Collisions(), NumGT25Collisions());
+  }
+)  // !PRODUCT
+
  protected:
   static const intptr_t kOccupiedEntriesIndex = 0;
   static const intptr_t kDeletedEntriesIndex = 1;
+#if defined(PRODUCT)
   static const intptr_t kHeaderSize = kDeletedEntriesIndex + 1;
+#else
+  static const intptr_t kNumGrowsIndex = 2;
+  static const intptr_t kNumLT5LookupsIndex = 3;
+  static const intptr_t kNumLT25LookupsIndex = 4;
+  static const intptr_t kNumGT25LookupsIndex = 5;
+  static const intptr_t kHeaderSize = kNumGT25LookupsIndex + 1;
+#endif
   static const intptr_t kMetaDataIndex = kHeaderSize;
   static const intptr_t kFirstKeyIndex = kHeaderSize + kMetaDataSize;
   static const intptr_t kEntrySize = 1 + kPayloadSize;
@@ -491,6 +560,7 @@
         table.data_->IsOld() ? Heap::kOld : Heap::kNew));
     Copy(table, new_table);
     *table.data_ = new_table.Release().raw();
+    NOT_IN_PRODUCT(table.UpdateGrowth(); table.PrintStats();)
   }
 
   // Serializes a table by concatenating its entries as an array.
diff --git a/runtime/vm/hash_table_test.cc b/runtime/vm/hash_table_test.cc
index f413932..8e0ac23 100644
--- a/runtime/vm/hash_table_test.cc
+++ b/runtime/vm/hash_table_test.cc
@@ -21,6 +21,7 @@
 class TestTraits {
  public:
   static const char* Name() { return "TestTraits"; }
+  static bool ReportStats() { return false; }
 
   static bool IsMatch(const char* key, const Object& obj) {
     return String::Cast(obj).Equals(key);
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index 0cd9f41..6fd3c3a 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -31,10 +31,10 @@
            intptr_t max_old_gen_words,
            intptr_t max_external_words)
     : isolate_(isolate),
-      barrier_(new Monitor()),
-      barrier_done_(new Monitor()),
       new_space_(this, max_new_gen_semi_words, kNewObjectAlignmentOffset),
       old_space_(this, max_old_gen_words, max_external_words),
+      barrier_(new Monitor()),
+      barrier_done_(new Monitor()),
       read_only_(false),
       gc_new_space_in_progress_(false),
       gc_old_space_in_progress_(false),
diff --git a/runtime/vm/heap.h b/runtime/vm/heap.h
index 287cbdc..1526424 100644
--- a/runtime/vm/heap.h
+++ b/runtime/vm/heap.h
@@ -340,16 +340,17 @@
   void GetMergedAddressRange(uword* start, uword* end) const;
 
   Isolate* isolate_;
-  Monitor* barrier_;
-  Monitor* barrier_done_;
 
   // The different spaces used for allocation.
-  Scavenger new_space_;
+  ALIGN8 Scavenger new_space_;
   PageSpace old_space_;
 
   WeakTable* new_weak_tables_[kNumWeakSelectors];
   WeakTable* old_weak_tables_[kNumWeakSelectors];
 
+  Monitor* barrier_;
+  Monitor* barrier_done_;
+
   // GC stats collection.
   GCStats stats_;
 
diff --git a/runtime/vm/instructions.h b/runtime/vm/instructions.h
index a271672..2274bec 100644
--- a/runtime/vm/instructions.h
+++ b/runtime/vm/instructions.h
@@ -17,6 +17,8 @@
 #include "vm/instructions_arm64.h"
 #elif defined(TARGET_ARCH_MIPS)
 #include "vm/instructions_mips.h"
+#elif defined(TARGET_ARCH_DBC)
+#include "vm/instructions_dbc.h"
 #else
 #error Unknown architecture.
 #endif
diff --git a/runtime/vm/instructions_dbc.cc b/runtime/vm/instructions_dbc.cc
new file mode 100644
index 0000000..38b69f4
--- /dev/null
+++ b/runtime/vm/instructions_dbc.cc
@@ -0,0 +1,180 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h"  // Needed here to get TARGET_ARCH_DBC.
+#if defined(TARGET_ARCH_DBC)
+
+#include "vm/instructions.h"
+#include "vm/instructions_dbc.h"
+
+#include "vm/assembler.h"
+#include "vm/constants_dbc.h"
+#include "vm/cpu.h"
+#include "vm/object.h"
+
+namespace dart {
+
+CallPattern::CallPattern(uword pc, const Code& code)
+    : object_pool_(ObjectPool::Handle(code.GetObjectPool())),
+      end_(pc),
+      ic_data_load_end_(0),
+      target_code_pool_index_(-1),
+      ic_data_(ICData::Handle()) {
+  UNIMPLEMENTED();
+}
+
+
+int CallPattern::DeoptCallPatternLengthInInstructions() {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+int CallPattern::DeoptCallPatternLengthInBytes() {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+NativeCallPattern::NativeCallPattern(uword pc, const Code& code)
+    : object_pool_(ObjectPool::Handle(code.GetObjectPool())),
+      end_(pc),
+      native_function_pool_index_(-1),
+      target_code_pool_index_(-1) {
+  UNIMPLEMENTED();
+}
+
+
+RawCode* NativeCallPattern::target() const {
+  return reinterpret_cast<RawCode*>(
+      object_pool_.ObjectAt(target_code_pool_index_));
+}
+
+
+void NativeCallPattern::set_target(const Code& new_target) const {
+  object_pool_.SetObjectAt(target_code_pool_index_, new_target);
+  // No need to flush the instruction cache, since the code is not modified.
+}
+
+
+NativeFunction NativeCallPattern::native_function() const {
+  return reinterpret_cast<NativeFunction>(
+      object_pool_.RawValueAt(native_function_pool_index_));
+}
+
+
+void NativeCallPattern::set_native_function(NativeFunction func) const {
+  object_pool_.SetRawValueAt(native_function_pool_index_,
+      reinterpret_cast<uword>(func));
+}
+
+
+// Decodes a load sequence ending at 'end' (the last instruction of the load
+// sequence is the instruction before the one at end).  Returns a pointer to
+// the first instruction in the sequence.  Returns the register being loaded
+// and the loaded object in the output parameters 'reg' and 'obj'
+// respectively.
+uword InstructionPattern::DecodeLoadObject(uword end,
+                                           const ObjectPool& object_pool,
+                                           Register* reg,
+                                           Object* obj) {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+// Decodes a load sequence ending at 'end' (the last instruction of the load
+// sequence is the instruction before the one at end).  Returns a pointer to
+// the first instruction in the sequence.  Returns the register being loaded
+// and the loaded immediate value in the output parameters 'reg' and 'value'
+// respectively.
+uword InstructionPattern::DecodeLoadWordImmediate(uword end,
+                                                  Register* reg,
+                                                  intptr_t* value) {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+// Decodes a load sequence ending at 'end' (the last instruction of the load
+// sequence is the instruction before the one at end).  Returns a pointer to
+// the first instruction in the sequence.  Returns the register being loaded
+// and the index in the pool being read from in the output parameters 'reg'
+// and 'index' respectively.
+uword InstructionPattern::DecodeLoadWordFromPool(uword end,
+                                                 Register* reg,
+                                                 intptr_t* index) {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+bool DecodeLoadObjectFromPoolOrThread(uword pc,
+                                      const Code& code,
+                                      Object* obj) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+RawICData* CallPattern::IcData() {
+  UNIMPLEMENTED();
+  return ICData::null();
+}
+
+
+RawCode* CallPattern::TargetCode() const {
+  return reinterpret_cast<RawCode*>(
+      object_pool_.ObjectAt(target_code_pool_index_));
+}
+
+
+void CallPattern::SetTargetCode(const Code& target_code) const {
+  object_pool_.SetObjectAt(target_code_pool_index_, target_code);
+}
+
+
+void CallPattern::InsertDeoptCallAt(uword pc, uword target_address) {
+  UNIMPLEMENTED();
+}
+
+
+SwitchableCallPattern::SwitchableCallPattern(uword pc, const Code& code)
+    : object_pool_(ObjectPool::Handle(code.GetObjectPool())),
+      cache_pool_index_(-1),
+      stub_pool_index_(-1) {
+  UNIMPLEMENTED();
+}
+
+
+RawObject* SwitchableCallPattern::cache() const {
+  return reinterpret_cast<RawCode*>(
+      object_pool_.ObjectAt(cache_pool_index_));
+}
+
+
+void SwitchableCallPattern::SetCache(const MegamorphicCache& cache) const {
+  ASSERT(Object::Handle(object_pool_.ObjectAt(cache_pool_index_)).IsICData());
+  object_pool_.SetObjectAt(cache_pool_index_, cache);
+}
+
+
+void SwitchableCallPattern::SetLookupStub(const Code& lookup_stub) const {
+  ASSERT(Object::Handle(object_pool_.ObjectAt(stub_pool_index_)).IsCode());
+  object_pool_.SetObjectAt(stub_pool_index_, lookup_stub);
+}
+
+
+ReturnPattern::ReturnPattern(uword pc) : pc_(pc) {
+  USE(pc_);
+}
+
+
+bool ReturnPattern::IsValid() const {
+  UNIMPLEMENTED();
+  return false;
+}
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/instructions_dbc.h b/runtime/vm/instructions_dbc.h
new file mode 100644
index 0000000..5eb0c6e
--- /dev/null
+++ b/runtime/vm/instructions_dbc.h
@@ -0,0 +1,138 @@
+// 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.
+// Classes that describe assembly patterns as used by inline caches.
+
+#ifndef VM_INSTRUCTIONS_DBC_H_
+#define VM_INSTRUCTIONS_DBC_H_
+
+#ifndef VM_INSTRUCTIONS_H_
+#error Do not include instructions_dbc.h directly; use instructions.h instead.
+#endif
+
+#include "vm/constants_dbc.h"
+#include "vm/native_entry.h"
+#include "vm/object.h"
+
+namespace dart {
+
+class InstructionPattern : public AllStatic {
+ public:
+  // Decodes a load sequence ending at 'end' (the last instruction of the
+  // load sequence is the instruction before the one at end).  Returns the
+  // address of the first instruction in the sequence.  Returns the register
+  // being loaded and the loaded object in the output parameters 'reg' and
+  // 'obj' respectively.
+  static uword DecodeLoadObject(uword end,
+                                const ObjectPool& object_pool,
+                                Register* reg,
+                                Object* obj);
+
+  // Decodes a load sequence ending at 'end' (the last instruction of the
+  // load sequence is the instruction before the one at end).  Returns the
+  // address of the first instruction in the sequence.  Returns the register
+  // being loaded and the loaded immediate value in the output parameters
+  // 'reg' and 'value' respectively.
+  static uword DecodeLoadWordImmediate(uword end,
+                                       Register* reg,
+                                       intptr_t* value);
+
+  // Decodes a load sequence ending at 'end' (the last instruction of the
+  // load sequence is the instruction before the one at end).  Returns the
+  // address of the first instruction in the sequence.  Returns the register
+  // being loaded and the index in the pool being read from in the output
+  // parameters 'reg' and 'index' respectively.
+  static uword DecodeLoadWordFromPool(uword end,
+                                      Register* reg,
+                                      intptr_t* index);
+};
+
+
+class CallPattern : public ValueObject {
+ public:
+  CallPattern(uword pc, const Code& code);
+
+  RawICData* IcData();
+
+  RawCode* TargetCode() const;
+  void SetTargetCode(const Code& code) const;
+
+  // This constant length is only valid for inserted call patterns used for
+  // lazy deoptimization. Regular call pattern may vary in length.
+  static int DeoptCallPatternLengthInBytes();
+  static int DeoptCallPatternLengthInInstructions();
+
+  static void InsertDeoptCallAt(uword pc, uword target_address);
+
+ private:
+  const ObjectPool& object_pool_;
+
+  uword end_;
+  uword ic_data_load_end_;
+
+  intptr_t target_code_pool_index_;
+  ICData& ic_data_;
+
+  DISALLOW_COPY_AND_ASSIGN(CallPattern);
+};
+
+
+class NativeCallPattern : public ValueObject {
+ public:
+  NativeCallPattern(uword pc, const Code& code);
+
+  RawCode* target() const;
+  void set_target(const Code& target) const;
+
+  NativeFunction native_function() const;
+  void set_native_function(NativeFunction target) const;
+
+ private:
+  const ObjectPool& object_pool_;
+
+  uword end_;
+  intptr_t native_function_pool_index_;
+  intptr_t target_code_pool_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(NativeCallPattern);
+};
+
+
+// Instance call that can switch from an IC call to a megamorphic call
+class SwitchableCallPattern : public ValueObject {
+ public:
+  SwitchableCallPattern(uword pc, const Code& code);
+
+  RawObject* cache() const;
+  void SetCache(const MegamorphicCache& cache) const;
+  void SetLookupStub(const Code& stub) const;
+
+ private:
+  const ObjectPool& object_pool_;
+  intptr_t cache_pool_index_;
+  intptr_t stub_pool_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(SwitchableCallPattern);
+};
+
+
+class ReturnPattern : public ValueObject {
+ public:
+  explicit ReturnPattern(uword pc);
+
+  static const int kLengthInBytes = 0;
+
+  int pattern_length_in_bytes() const {
+    UNIMPLEMENTED();
+    return kLengthInBytes;
+  }
+
+  bool IsValid() const;
+
+ private:
+  const uword pc_;
+};
+
+}  // namespace dart
+
+#endif  // VM_INSTRUCTIONS_DBC_H_
diff --git a/runtime/vm/instructions_x64.cc b/runtime/vm/instructions_x64.cc
index 3fa610a..950fd16 100644
--- a/runtime/vm/instructions_x64.cc
+++ b/runtime/vm/instructions_x64.cc
@@ -25,35 +25,44 @@
   ASSERT(code.ContainsInstructionAt(pc));
 
   uint8_t* bytes = reinterpret_cast<uint8_t*>(pc);
+
   COMPILE_ASSERT(PP == R15);
-  if (((bytes[0] == 0x49) && (bytes[1] == 0x8b) && (bytes[2] == 0x9f)) ||
-      ((bytes[0] == 0x49) && (bytes[1] == 0x8b) && (bytes[2] == 0x87)) ||
-      ((bytes[0] == 0x4d) && (bytes[1] == 0x8b) && (bytes[2] == 0xa7)) ||
-      ((bytes[0] == 0x4d) && (bytes[1] == 0x8b) && (bytes[2] == 0x9f)) ||
-      ((bytes[0] == 0x4d) && (bytes[1] == 0x8b) && (bytes[2] == 0x97))) {
-    intptr_t index = IndexFromPPLoad(pc + 3);
-    const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
-    if (pool.InfoAt(index) == ObjectPool::kTaggedObject) {
-      *obj = pool.ObjectAt(index);
-      return true;
+  if ((bytes[0] == 0x49) || (bytes[0] == 0x4d)) {
+    if ((bytes[1] == 0x8b) || (bytes[1] == 0x3b)) {  // movq, cmpq
+      if ((bytes[2] & 0xc7) == (0x80 | (PP & 7))) {  // [r15+disp32]
+        intptr_t index = IndexFromPPLoad(pc + 3);
+        const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
+        if (pool.InfoAt(index) == ObjectPool::kTaggedObject) {
+          *obj = pool.ObjectAt(index);
+          return true;
+        }
+      }
+      if ((bytes[2] & 0xc7) == (0x40 | (PP & 7))) {  // [r15+disp8]
+        intptr_t index = IndexFromPPLoadDisp8(pc + 3);
+        const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
+        if (pool.InfoAt(index) == ObjectPool::kTaggedObject) {
+          *obj = pool.ObjectAt(index);
+          return true;
+        }
+      }
     }
   }
+
   COMPILE_ASSERT(THR == R14);
-  if (((bytes[0] == 0x49) && (bytes[1] == 0x8b) && (bytes[2] == 0x86)) ||
-      ((bytes[0] == 0x49) && (bytes[1] == 0x8b) && (bytes[2] == 0xb6)) ||
-      ((bytes[0] == 0x49) && (bytes[1] == 0x8b) && (bytes[2] == 0x96)) ||
-      ((bytes[0] == 0x49) && (bytes[1] == 0x8b) && (bytes[2] == 0x9e)) ||
-      ((bytes[0] == 0x4d) && (bytes[1] == 0x8b) && (bytes[2] == 0x9e)) ||
-      ((bytes[0] == 0x4d) && (bytes[1] == 0x8b) && (bytes[2] == 0xa6))) {
-    int32_t offset = *reinterpret_cast<int32_t*>(pc + 3);
-    return Thread::ObjectAtOffset(offset, obj);
+  if ((bytes[0] == 0x49) || (bytes[0] == 0x4d)) {
+    if ((bytes[1] == 0x8b) || (bytes[1] == 0x3b)) {   // movq, cmpq
+      if ((bytes[2] & 0xc7) == (0x80 | (THR & 7))) {  // [r14+disp32]
+        int32_t offset = *reinterpret_cast<int32_t*>(pc + 3);
+        return Thread::ObjectAtOffset(offset, obj);
+      }
+      if ((bytes[2] & 0xc7) == (0x40 | (THR & 7))) {  // [r14+disp8]
+        uint8_t offset = *reinterpret_cast<uint8_t*>(pc + 3);
+        return Thread::ObjectAtOffset(offset, obj);
+      }
+    }
   }
-  if (((bytes[0] == 0x41) && (bytes[1] == 0xff) && (bytes[2] == 0x76)) ||
-      ((bytes[0] == 0x49) && (bytes[1] == 0x3b) && (bytes[2] == 0x66)) ||
-      ((bytes[0] == 0x49) && (bytes[1] == 0x8b) && (bytes[2] == 0x46)) ||
-      ((bytes[0] == 0x4d) && (bytes[1] == 0x8b) && (bytes[2] == 0x5e)) ||
-      ((bytes[0] == 0x4d) && (bytes[1] == 0x8b) && (bytes[2] == 0x66)) ||
-      ((bytes[0] == 0x4d) && (bytes[1] == 0x8b) && (bytes[2] == 0x6e))) {
+  if (((bytes[0] == 0x41) && (bytes[1] == 0xff) && (bytes[2] == 0x76))) {
+    // push [r14+disp8]
     uint8_t offset = *reinterpret_cast<uint8_t*>(pc + 3);
     return Thread::ObjectAtOffset(offset, obj);
   }
diff --git a/runtime/vm/instructions_x64.h b/runtime/vm/instructions_x64.h
index 5d7616d..8f1c073 100644
--- a/runtime/vm/instructions_x64.h
+++ b/runtime/vm/instructions_x64.h
@@ -22,6 +22,7 @@
 
 
 intptr_t IndexFromPPLoad(uword start);
+intptr_t IndexFromPPLoadDisp8(uword start);
 
 
 // Template class for all instruction pattern classes.
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index c68f277..3869329 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -33,7 +33,7 @@
     "Propagate IC data from unoptimized to optimized IC calls.");
 DEFINE_FLAG(bool, two_args_smi_icd, true,
     "Generate special IC stubs for two args Smi operations");
-DEFINE_FLAG(bool, unbox_numeric_fields, true,
+DEFINE_FLAG(bool, unbox_numeric_fields, !USING_DBC,
     "Support unboxed double and float32x4 fields.");
 DECLARE_FLAG(bool, eliminate_type_checks);
 DECLARE_FLAG(bool, support_externalizable_strings);
@@ -1651,12 +1651,14 @@
 
 
 RawInteger* UnaryIntegerOpInstr::Evaluate(const Integer& value) const {
-  Integer& result = Integer::Handle();
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  Integer& result = Integer::Handle(zone);
 
   switch (op_kind()) {
     case Token::kNEGATE:
       result = value.ArithmeticOp(Token::kMUL,
-                                  Smi::Handle(Smi::New(-1)),
+                                  Smi::Handle(zone, Smi::New(-1)),
                                   Heap::kOld);
       break;
 
@@ -1680,7 +1682,7 @@
       // specialized instructions that use this value under this assumption.
       return Integer::null();
     }
-    result ^= result.CheckAndCanonicalize(NULL);
+    result ^= result.CheckAndCanonicalize(thread, NULL);
   }
 
   return result.raw();
@@ -1689,7 +1691,9 @@
 
 RawInteger* BinaryIntegerOpInstr::Evaluate(const Integer& left,
                                            const Integer& right) const {
-  Integer& result = Integer::Handle();
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  Integer& result = Integer::Handle(zone);
 
   switch (op_kind()) {
     case Token::kTRUNCDIV:
@@ -1738,7 +1742,7 @@
       // specialized instructions that use this value under this assumption.
       return Integer::null();
     }
-    result ^= result.CheckAndCanonicalize(NULL);
+    result ^= result.CheckAndCanonicalize(thread, NULL);
   }
 
   return result.raw();
@@ -2586,6 +2590,28 @@
 }
 
 
+Definition* TestCidsInstr::Canonicalize(FlowGraph* flow_graph) {
+  CompileType* in_type = left()->Type();
+  intptr_t cid = in_type->ToCid();
+  if (cid == kDynamicCid) return this;
+
+  const ZoneGrowableArray<intptr_t>& data = cid_results();
+  const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0;
+  for (intptr_t i = 0; i < data.length(); i += 2) {
+    if (data[i] == cid) {
+      return (data[i + 1] == true_result)
+          ? flow_graph->GetConstant(Bool::True())
+          : flow_graph->GetConstant(Bool::False());
+    }
+  }
+
+  // TODO(sra): Handle misses if the instruction is not deoptimizing.
+  // TODO(sra): Handle nullable input, possibly canonicalizing to a compare
+  // against `null`.
+  return this;
+}
+
+
 Instruction* GuardFieldClassInstr::Canonicalize(FlowGraph* flow_graph) {
   if (field().guarded_cid() == kDynamicCid) {
     return NULL;  // Nothing to guard.
@@ -2766,9 +2792,14 @@
 void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   __ Bind(compiler->GetJumpLabel(this));
   if (!compiler->is_optimizing()) {
+#if !defined(TARGET_ARCH_DBC)
+    // TODO(vegorov) re-enable edge counters on DBC if we consider them
+    // beneficial for the quality of the optimized bytecode.
     if (compiler->NeedsEdgeCounter(this)) {
       compiler->EmitEdgeCounter(preorder_number());
     }
+#endif
+
     // The deoptimization descriptor points after the edge counter code for
     // uniformity with ARM and MIPS, where we can reuse pattern matching
     // code that matches backwards from the end of the pattern.
@@ -2968,10 +2999,23 @@
 
 
 void DropTempsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+#if defined(TARGET_ARCH_DBC)
+  // On DBC the action of poping the TOS value and then pushing it
+  // after all intermediates are poped is folded into a special
+  // bytecode (DropR). On other architectures this is handled by
+  // instruction prologue/epilogues.
+  ASSERT(!compiler->is_optimizing());
+  if ((InputCount() != 0) && HasTemp()) {
+    __ DropR(num_temps());
+  } else {
+    __ Drop(num_temps() + ((InputCount() != 0) ? 1 : 0));
+  }
+#else
   ASSERT(!compiler->is_optimizing());
   // Assert that register assignment is correct.
   ASSERT((InputCount() == 0) || (locs()->out(0).reg() == locs()->in(0).reg()));
   __ Drop(num_temps());
+#endif  // defined(TARGET_ARCH_DBC)
 }
 
 
@@ -2996,6 +3040,8 @@
 }
 
 
+// DBC does not use specialized inline cache stubs for smi operations.
+#if !defined(TARGET_ARCH_DBC)
 static const StubEntry* TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) {
   if (!FLAG_two_args_smi_icd) {
     return 0;
@@ -3007,6 +3053,7 @@
     default:          return NULL;
   }
 }
+#endif
 
 
 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
@@ -3023,6 +3070,8 @@
   } else {
     call_ic_data = &ICData::ZoneHandle(zone, ic_data()->raw());
   }
+
+#if !defined(TARGET_ARCH_DBC)
   if (compiler->is_optimizing() && HasICData()) {
     ASSERT(HasICData());
     if (ic_data()->NumberOfUsedChecks() > 0) {
@@ -3096,6 +3145,44 @@
                                      *call_ic_data);
     }
   }
+#else
+  // Emit smi fast path instruction. If fast-path succeeds it skips the next
+  // instruction otherwise it falls through.
+  if (function_name().raw() == Symbols::Plus().raw()) {
+    __ AddTOS();
+  } else if (function_name().raw() == Symbols::EqualOperator().raw()) {
+    __ EqualTOS();
+  } else if (function_name().raw() == Symbols::LAngleBracket().raw()) {
+    __ LessThanTOS();
+  } else if (function_name().raw() == Symbols::RAngleBracket().raw()) {
+    __ GreaterThanTOS();
+  } else if (function_name().raw() == Symbols::BitAnd().raw()) {
+    __ BitAndTOS();
+  } else if (function_name().raw() == Symbols::BitOr().raw()) {
+    __ BitOrTOS();
+  } else if (function_name().raw() == Symbols::Star().raw()) {
+    __ MulTOS();
+  }
+
+  const intptr_t call_ic_data_kidx = __ AddConstant(*call_ic_data);
+  switch (call_ic_data->NumArgsTested()) {
+    case 1:
+      __ InstanceCall(ArgumentCount(), call_ic_data_kidx);
+      break;
+    case 2:
+      __ InstanceCall2(ArgumentCount(), call_ic_data_kidx);
+      break;
+    case 3:
+      __ InstanceCall3(ArgumentCount(), call_ic_data_kidx);
+      break;
+    default:
+      UNIMPLEMENTED();
+      break;
+  }
+  compiler->AddCurrentDescriptor(RawPcDescriptors::kIcCall,
+                                 deopt_id(),
+                                 token_pos());
+#endif  // !defined(TARGET_ARCH_DBC)
 }
 
 
@@ -3118,6 +3205,10 @@
   return true;
 }
 
+
+// DBC does not support optimizing compiler and thus doesn't emit
+// PolymorphicInstanceCallInstr.
+#if !defined(TARGET_ARCH_DBC)
 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(ic_data().NumArgsTested() == 1);
   if (!with_checks()) {
@@ -3141,6 +3232,7 @@
                                         locs(),
                                         complete());
 }
+#endif
 
 
 LocationSummary* StaticCallInstr::MakeLocationSummary(Zone* zone,
@@ -3150,6 +3242,7 @@
 
 
 void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+#if !defined(TARGET_ARCH_DBC)
   const ICData* call_ic_data = NULL;
   if (!FLAG_propagate_ic_data || !compiler->is_optimizing() ||
       (ic_data() == NULL)) {
@@ -3182,6 +3275,20 @@
                                argument_names(),
                                locs(),
                                *call_ic_data);
+#else
+  const Array& arguments_descriptor =
+      (ic_data() == NULL) ?
+        Array::Handle(ArgumentsDescriptor::New(ArgumentCount(),
+                                               argument_names())) :
+        Array::Handle(ic_data()->arguments_descriptor());
+  const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor);
+
+  __ PushConstant(function());
+  __ StaticCall(ArgumentCount(), argdesc_kidx);
+  compiler->AddCurrentDescriptor(RawPcDescriptors::kUnoptStaticCall,
+                                 deopt_id(),
+                                 token_pos());
+#endif  // !defined(TARGET_ARCH_DBC)
 }
 
 
@@ -3191,7 +3298,11 @@
                                      dst_type(),
                                      dst_name(),
                                      locs());
+
+  // DBC does not use LocationSummaries in the same way as other architectures.
+#if !defined(TARGET_ARCH_DBC)
   ASSERT(locs()->in(0).reg() == locs()->out(0).reg());
+#endif
 }
 
 
@@ -3302,11 +3413,6 @@
 }
 
 
-static bool BindsToSmiConstant(Value* value) {
-  return value->BindsToConstant() && value->BoundConstant().IsSmi();
-}
-
-
 ComparisonInstr* EqualityCompareInstr::CopyWithNewOperands(Value* new_left,
                                                            Value* new_right) {
   return new EqualityCompareInstr(token_pos(),
@@ -3374,9 +3480,17 @@
 }
 
 
+#if !defined(TARGET_ARCH_DBC)
+static bool BindsToSmiConstant(Value* value) {
+  return value->BindsToConstant() && value->BoundConstant().IsSmi();
+}
+#endif
+
+
 bool IfThenElseInstr::Supports(ComparisonInstr* comparison,
                                Value* v1,
                                Value* v2) {
+#if !defined(TARGET_ARCH_DBC)
   bool is_smi_result = BindsToSmiConstant(v1) && BindsToSmiConstant(v2);
   if (comparison->IsStrictCompare()) {
     // Strict comparison with number checks calls a stub and is not supported
@@ -3389,6 +3503,9 @@
     return false;
   }
   return is_smi_result;
+#else
+  return false;
+#endif  // !defined(TARGET_ARCH_DBC)
 }
 
 
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 6e16c31..1536cf4 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -140,6 +140,9 @@
   // Create non-nullable Int type.
   static CompileType Int();
 
+  // Create non-nullable Smi type.
+  static CompileType Smi();
+
   // Create non-nullable String type.
   static CompileType String();
 
@@ -3047,6 +3050,8 @@
 
   virtual CompileType ComputeType() const;
 
+  virtual Definition* Canonicalize(FlowGraph* flow_graph);
+
   virtual bool CanDeoptimize() const {
     return GetDeoptId() != Thread::kNoDeoptId;
   }
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index c7591b5..2c7d44e 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -1075,7 +1075,14 @@
 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Register object = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
-  __ LoadTaggedClassIdMayBeSmi(result, object);
+  const AbstractType& value_type = *this->object()->Type()->ToAbstractType();
+  if (CompileType::Smi().IsAssignableTo(value_type) ||
+      value_type.IsTypeParameter()) {
+    __ LoadTaggedClassIdMayBeSmi(result, object);
+  } else {
+    __ LoadClassId(result, object);
+    __ SmiTag(result);
+  }
 }
 
 
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index 452b6ba..f627e6e 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -932,8 +932,14 @@
 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Register object = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
-
-  __ LoadTaggedClassIdMayBeSmi(result, object);
+  const AbstractType& value_type = *this->object()->Type()->ToAbstractType();
+  if (CompileType::Smi().IsAssignableTo(value_type) ||
+      value_type.IsTypeParameter()) {
+    __ LoadTaggedClassIdMayBeSmi(result, object);
+  } else {
+    __ LoadClassId(result, object);
+    __ SmiTag(result);
+  }
 }
 
 
diff --git a/runtime/vm/intermediate_language_dbc.cc b/runtime/vm/intermediate_language_dbc.cc
new file mode 100644
index 0000000..293d239
--- /dev/null
+++ b/runtime/vm/intermediate_language_dbc.cc
@@ -0,0 +1,703 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h"  // Needed here to get TARGET_ARCH_DBC.
+#if defined(TARGET_ARCH_DBC)
+
+#include "vm/intermediate_language.h"
+
+#include "vm/cpu.h"
+#include "vm/compiler.h"
+#include "vm/dart_entry.h"
+#include "vm/flow_graph.h"
+#include "vm/flow_graph_compiler.h"
+#include "vm/flow_graph_range_analysis.h"
+#include "vm/locations.h"
+#include "vm/object_store.h"
+#include "vm/parser.h"
+#include "vm/simulator.h"
+#include "vm/stack_frame.h"
+#include "vm/stub_code.h"
+#include "vm/symbols.h"
+
+#define __ compiler->assembler()->
+
+namespace dart {
+
+DECLARE_FLAG(bool, emit_edge_counters);
+DECLARE_FLAG(int, optimization_counter_threshold);
+
+// List of instructions that are still unimplemented by DBC backend.
+#define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M) \
+  M(Stop)                                                                      \
+  M(IndirectGoto)                                                              \
+  M(LoadCodeUnits)                                                             \
+  M(InstanceOf)                                                                \
+  M(LoadUntagged)                                                              \
+  M(AllocateUninitializedContext)                                              \
+  M(BinaryInt32Op)                                                             \
+  M(UnarySmiOp)                                                                \
+  M(UnaryDoubleOp)                                                             \
+  M(SmiToDouble)                                                               \
+  M(Int32ToDouble)                                                             \
+  M(MintToDouble)                                                              \
+  M(DoubleToInteger)                                                           \
+  M(DoubleToSmi)                                                               \
+  M(DoubleToDouble)                                                            \
+  M(DoubleToFloat)                                                             \
+  M(FloatToDouble)                                                             \
+  M(UnboxedConstant)                                                           \
+  M(CheckEitherNonSmi)                                                         \
+  M(BinaryDoubleOp)                                                            \
+  M(MathUnary)                                                                 \
+  M(MathMinMax)                                                                \
+  M(Box)                                                                       \
+  M(Unbox)                                                                     \
+  M(BoxInt64)                                                                  \
+  M(CaseInsensitiveCompareUC16)                                                \
+  M(BinaryMintOp)                                                              \
+  M(ShiftMintOp)                                                               \
+  M(UnaryMintOp)                                                               \
+  M(StringToCharCode)                                                          \
+  M(StringFromCharCode)                                                        \
+  M(InvokeMathCFunction)                                                       \
+  M(MergedMath)                                                                \
+  M(GuardFieldClass)                                                           \
+  M(GuardFieldLength)                                                          \
+  M(IfThenElse)                                                                \
+  M(BinaryFloat32x4Op)                                                         \
+  M(Simd32x4Shuffle)                                                           \
+  M(Simd32x4ShuffleMix)                                                        \
+  M(Simd32x4GetSignMask)                                                       \
+  M(Float32x4Constructor)                                                      \
+  M(Float32x4Zero)                                                             \
+  M(Float32x4Splat)                                                            \
+  M(Float32x4Comparison)                                                       \
+  M(Float32x4MinMax)                                                           \
+  M(Float32x4Scale)                                                            \
+  M(Float32x4Sqrt)                                                             \
+  M(Float32x4ZeroArg)                                                          \
+  M(Float32x4Clamp)                                                            \
+  M(Float32x4With)                                                             \
+  M(Float32x4ToInt32x4)                                                        \
+  M(Int32x4Constructor)                                                        \
+  M(Int32x4BoolConstructor)                                                    \
+  M(Int32x4GetFlag)                                                            \
+  M(Int32x4Select)                                                             \
+  M(Int32x4SetFlag)                                                            \
+  M(Int32x4ToFloat32x4)                                                        \
+  M(BinaryInt32x4Op)                                                           \
+  M(TestCids)                                                                  \
+  M(BinaryFloat64x2Op)                                                         \
+  M(Float64x2Zero)                                                             \
+  M(Float64x2Constructor)                                                      \
+  M(Float64x2Splat)                                                            \
+  M(Float32x4ToFloat64x2)                                                      \
+  M(Float64x2ToFloat32x4)                                                      \
+  M(Simd64x2Shuffle)                                                           \
+  M(Float64x2ZeroArg)                                                          \
+  M(Float64x2OneArg)                                                           \
+  M(ExtractNthOutput)                                                          \
+  M(BinaryUint32Op)                                                            \
+  M(ShiftUint32Op)                                                             \
+  M(UnaryUint32Op)                                                             \
+  M(UnboxedIntConverter)                                                       \
+  M(GrowRegExpStack)                                                           \
+  M(BoxInteger32)                                                              \
+  M(UnboxInteger32)                                                            \
+  M(CheckedSmiOp)                                                              \
+  M(CheckArrayBound)                                                           \
+  M(CheckSmi)        \
+  M(LoadClassId)     \
+  M(CheckClassId)    \
+  M(CheckClass)      \
+  M(BinarySmiOp)     \
+  M(TestSmi)         \
+  M(RelationalOp)    \
+  M(EqualityCompare) \
+  M(LoadIndexed)     \
+// Location summaries actually are not used by the unoptimizing DBC compiler
+// because we don't allocate any registers.
+static LocationSummary* CreateLocationSummary(Zone* zone,
+                                              intptr_t num_inputs,
+                                              bool has_result) {
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new(zone) LocationSummary(
+      zone, num_inputs, kNumTemps, LocationSummary::kNoCall);
+  for (intptr_t i = 0; i < num_inputs; i++) {
+    locs->set_in(i, Location::RequiresRegister());
+  }
+  if (has_result) {
+    locs->set_out(0, Location::RequiresRegister());
+  }
+  return locs;
+}
+
+
+#define DEFINE_MAKE_LOCATION_SUMMARY(Name, In, Out)                            \
+  LocationSummary* Name##Instr::MakeLocationSummary(Zone* zone, bool opt)      \
+      const {                                                                  \
+    return CreateLocationSummary(zone, In, Out);                               \
+  }                                                                            \
+
+#define EMIT_NATIVE_CODE(Name, In, Out)                                        \
+  DEFINE_MAKE_LOCATION_SUMMARY(Name, In, Out);                                 \
+  void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler)                \
+
+#define DEFINE_UNIMPLEMENTED_MAKE_LOCATION_SUMMARY(Name)                       \
+  LocationSummary* Name##Instr::MakeLocationSummary(Zone* zone, bool opt)      \
+      const {                                                                  \
+    UNIMPLEMENTED();                                                           \
+    return NULL;                                                               \
+  }                                                                            \
+
+#define DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name)                            \
+  void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) {              \
+    UNIMPLEMENTED();                                                           \
+  }
+
+#define DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(Name)                            \
+  void Name##Instr::EmitBranchCode(FlowGraphCompiler*, BranchInstr*) {         \
+    UNIMPLEMENTED();                                                           \
+  }                                                                            \
+  Condition Name##Instr::EmitComparisonCode(FlowGraphCompiler*,                \
+                                            BranchLabels) {                    \
+    UNIMPLEMENTED();                                                           \
+    return EQ;                                                                 \
+  }
+
+#define DEFINE_UNIMPLEMENTED(Name)                                             \
+  DEFINE_UNIMPLEMENTED_MAKE_LOCATION_SUMMARY(Name)                             \
+  DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name)                                  \
+
+FOR_EACH_UNIMPLEMENTED_INSTRUCTION(DEFINE_UNIMPLEMENTED)
+
+#undef DEFINE_UNIMPLEMENTED
+
+DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(TestCids)
+DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(TestSmi)
+DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(RelationalOp)
+DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(EqualityCompare)
+
+
+DEFINE_MAKE_LOCATION_SUMMARY(AssertAssignable, 2, true);
+
+
+EMIT_NATIVE_CODE(AssertBoolean, 1, true) {
+  __ AssertBoolean(Isolate::Current()->type_checks() ? 1 : 0);
+  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther,
+                                 deopt_id(),
+                                 token_pos());
+}
+
+
+LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary(Zone* zone,
+                                                        bool optimizing) const {
+  return MakeCallSummary(zone);
+}
+
+
+void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
+EMIT_NATIVE_CODE(CheckStackOverflow, 0, false) {
+  __ CheckStack();
+  compiler->AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall,
+                                 Thread::kNoDeoptId,
+                                 token_pos());
+}
+
+
+EMIT_NATIVE_CODE(PushArgument, 1, false) {
+  if (compiler->is_optimizing()) {
+    __ Push(locs()->in(0).reg());
+  }
+}
+
+
+EMIT_NATIVE_CODE(LoadLocal, 0, false) {
+  ASSERT(!compiler->is_optimizing());
+  ASSERT(local().index() != 0);
+  __ Push((local().index() > 0) ? (-local().index()) : (-local().index() - 1));
+}
+
+
+EMIT_NATIVE_CODE(StoreLocal, 0, false) {
+  ASSERT(!compiler->is_optimizing());
+  ASSERT(local().index() != 0);
+  if (HasTemp()) {
+    __ StoreLocal(
+      (local().index() > 0) ? (-local().index()) : (-local().index() - 1));
+  } else {
+    __ PopLocal(
+      (local().index() > 0) ? (-local().index()) : (-local().index() - 1));
+  }
+}
+
+
+EMIT_NATIVE_CODE(Constant, 0, true) {
+  const intptr_t kidx = __ AddConstant(value());
+  if (compiler->is_optimizing()) {
+    __ LoadConstant(locs()->out(0).reg(), kidx);
+  } else {
+    __ PushConstant(kidx);
+  }
+}
+
+
+EMIT_NATIVE_CODE(Return, 1, false) {
+  __ ReturnTOS();
+}
+
+
+EMIT_NATIVE_CODE(StoreStaticField, 1, false) {
+  const intptr_t kidx = __ AddConstant(field());
+  __ StoreStaticTOS(kidx);
+}
+
+
+EMIT_NATIVE_CODE(LoadStaticField, 1, true) {
+  const intptr_t kidx = __ AddConstant(StaticField());
+  __ PushStatic(kidx);
+}
+
+
+EMIT_NATIVE_CODE(InitStaticField, 0, false) {
+  ASSERT(!compiler->is_optimizing());
+  __ InitStaticTOS();
+}
+
+
+EMIT_NATIVE_CODE(ClosureCall, 0, false) {
+  intptr_t argument_count = ArgumentCount();
+  const Array& arguments_descriptor =
+      Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
+                                                 argument_names()));
+  const intptr_t argdesc_kidx =
+      compiler->assembler()->AddConstant(arguments_descriptor);
+  __ StaticCall(argument_count, argdesc_kidx);
+
+  compiler->RecordSafepoint(locs());
+  // Marks either the continuation point in unoptimized code or the
+  // deoptimization point in optimized code, after call.
+  const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id());
+  if (compiler->is_optimizing()) {
+    compiler->AddDeoptIndexAtCall(deopt_id_after, token_pos());
+  }
+  // Add deoptimization continuation point after the call and before the
+  // arguments are removed.
+  // In optimized code this descriptor is needed for exception handling.
+  compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt,
+                                 deopt_id_after,
+                                 token_pos());
+}
+
+
+static void EmitBranchOnCondition(FlowGraphCompiler* compiler,
+                                  Condition true_condition,
+                                  BranchLabels labels) {
+  if (labels.fall_through == labels.false_label) {
+    // If the next block is the false successor, fall through to it.
+    __ Jump(labels.true_label);
+  } else {
+    // If the next block is not the false successor, branch to it.
+    __ Jump(labels.false_label);
+
+    // Fall through or jump to the true successor.
+    if (labels.fall_through != labels.true_label) {
+      __ Jump(labels.true_label);
+    }
+  }
+}
+
+
+Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+                                                 BranchLabels labels) {
+  ASSERT((kind() == Token::kNE_STRICT) ||
+         (kind() == Token::kEQ_STRICT));
+  const Bytecode::Opcode eq_op = needs_number_check() ?
+      Bytecode::kIfEqStrictNumTOS : Bytecode::kIfEqStrictTOS;
+  const Bytecode::Opcode ne_op = needs_number_check() ?
+      Bytecode::kIfNeStrictNumTOS : Bytecode::kIfNeStrictTOS;
+
+  if (kind() == Token::kEQ_STRICT) {
+    __ Emit((labels.fall_through == labels.false_label) ? eq_op : ne_op);
+  } else {
+    __ Emit((labels.fall_through == labels.false_label) ? ne_op : eq_op);
+  }
+
+  if (needs_number_check() && token_pos().IsReal()) {
+    compiler->AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall,
+                                   Thread::kNoDeoptId,
+                                   token_pos());
+  }
+  return EQ;
+}
+
+
+void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
+                                        BranchInstr* branch) {
+  ASSERT((kind() == Token::kEQ_STRICT) ||
+         (kind() == Token::kNE_STRICT));
+
+  BranchLabels labels = compiler->CreateBranchLabels(branch);
+  Condition true_condition = EmitComparisonCode(compiler, labels);
+  EmitBranchOnCondition(compiler, true_condition, labels);
+}
+
+
+EMIT_NATIVE_CODE(StrictCompare, 2, true) {
+  ASSERT((kind() == Token::kEQ_STRICT) ||
+         (kind() == Token::kNE_STRICT));
+
+  Label is_true, is_false;
+  BranchLabels labels = { &is_true, &is_false, &is_false };
+  Condition true_condition = EmitComparisonCode(compiler, labels);
+  EmitBranchOnCondition(compiler, true_condition, labels);
+  Label done;
+  __ Bind(&is_false);
+  __ PushConstant(Bool::False());
+  __ Jump(&done);
+  __ Bind(&is_true);
+  __ PushConstant(Bool::True());
+  __ Bind(&done);
+}
+
+
+LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone,
+                                                  bool opt) const {
+  comparison()->InitializeLocationSummary(zone, opt);
+  // Branches don't produce a result.
+  comparison()->locs()->set_out(0, Location::NoLocation());
+  return comparison()->locs();
+}
+
+
+void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  comparison()->EmitBranchCode(compiler, this);
+}
+
+
+EMIT_NATIVE_CODE(Goto, 0, false) {
+  if (HasParallelMove()) {
+    compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
+  }
+  // We can fall through if the successor is the next block in the list.
+  // Otherwise, we need a jump.
+  if (!compiler->CanFallThroughTo(successor())) {
+    __ Jump(compiler->GetJumpLabel(successor()));
+  }
+}
+
+
+EMIT_NATIVE_CODE(CreateArray, 2, true) {
+  __ CreateArrayTOS();
+}
+
+
+EMIT_NATIVE_CODE(StoreIndexed, 3, false) {
+  ASSERT(class_id() == kArrayCid);
+  __ StoreIndexedTOS();
+}
+
+
+EMIT_NATIVE_CODE(StringInterpolate, 0, false) {
+  const intptr_t kArgumentCount = 1;
+  const Array& arguments_descriptor = Array::Handle(
+      ArgumentsDescriptor::New(kArgumentCount, Object::null_array()));
+  __ PushConstant(CallFunction());
+  const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor);
+  __ StaticCall(kArgumentCount, argdesc_kidx);
+}
+
+
+EMIT_NATIVE_CODE(NativeCall, 0, false) {
+  SetupNative();
+
+  const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());
+
+  ASSERT(!link_lazily());
+  const ExternalLabel label(reinterpret_cast<uword>(native_c_function()));
+  const intptr_t target_kidx =
+      __ object_pool_wrapper().FindImmediate(label.address());
+  const intptr_t argc_tag_kidx =
+      __ object_pool_wrapper().FindImmediate(static_cast<uword>(argc_tag));
+  __ PushConstant(target_kidx);
+  __ PushConstant(argc_tag_kidx);
+  if (is_bootstrap_native()) {
+    __ NativeBootstrapCall();
+  } else {
+    __ NativeCall();
+  }
+  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther,
+                                 Thread::kNoDeoptId,
+                                 token_pos());
+}
+
+
+EMIT_NATIVE_CODE(AllocateObject, 0, true) {
+  if (ArgumentCount() == 1) {
+    __ PushConstant(cls());
+    __ AllocateT();
+    compiler->AddCurrentDescriptor(RawPcDescriptors::kOther,
+                                   Thread::kNoDeoptId,
+                                   token_pos());
+  } else {
+    const intptr_t kidx = __ AddConstant(cls());
+    __ Allocate(kidx);
+    compiler->AddCurrentDescriptor(RawPcDescriptors::kOther,
+                                   Thread::kNoDeoptId,
+                                   token_pos());
+  }
+}
+
+
+EMIT_NATIVE_CODE(StoreInstanceField, 2, false) {
+  ASSERT(!HasTemp());
+  ASSERT(offset_in_bytes() % kWordSize == 0);
+  if (compiler->is_optimizing()) {
+    const Register value = locs()->in(1).reg();
+    const Register instance = locs()->in(0).reg();
+    __ StoreField(instance, offset_in_bytes() / kWordSize, value);
+  } else {
+    __ StoreFieldTOS(offset_in_bytes() / kWordSize);
+  }
+}
+
+
+EMIT_NATIVE_CODE(LoadField, 1, true) {
+  ASSERT(offset_in_bytes() % kWordSize == 0);
+  __ LoadFieldTOS(offset_in_bytes() / kWordSize);
+}
+
+
+EMIT_NATIVE_CODE(BooleanNegate, 1, true) {
+  __ BooleanNegateTOS();
+}
+
+
+EMIT_NATIVE_CODE(AllocateContext, 0, false) {
+  __ AllocateContext(num_context_variables());
+  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther,
+                                 Thread::kNoDeoptId,
+                                 token_pos());
+}
+
+
+EMIT_NATIVE_CODE(CloneContext, 0, false) {
+  __ CloneContext();
+  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther,
+                                 Thread::kNoDeoptId,
+                                 token_pos());
+}
+
+
+EMIT_NATIVE_CODE(CatchBlockEntry, 0, false) {
+  __ Bind(compiler->GetJumpLabel(this));
+  compiler->AddExceptionHandler(catch_try_index(),
+                                try_index(),
+                                compiler->assembler()->CodeSize(),
+                                catch_handler_types_,
+                                needs_stacktrace());
+  __ MoveSpecial(-exception_var().index()-1,
+                 Simulator::kExceptionSpecialIndex);
+  __ MoveSpecial(-stacktrace_var().index()-1,
+                 Simulator::kStacktraceSpecialIndex);
+  __ SetFrame(compiler->StackSize());
+}
+
+
+EMIT_NATIVE_CODE(Throw, 0, false) {
+  __ Throw(0);
+  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther,
+                                 deopt_id(),
+                                 token_pos());
+  __ Trap();
+}
+
+
+EMIT_NATIVE_CODE(ReThrow, 0, false) {
+  compiler->SetNeedsStacktrace(catch_try_index());
+  __ Throw(1);
+  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther,
+                                 deopt_id(),
+                                 token_pos());
+  __ Trap();
+}
+
+EMIT_NATIVE_CODE(InstantiateType, 1, true) {
+  __ InstantiateType(__ AddConstant(type()));
+  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther,
+                                 deopt_id(),
+                                 token_pos());
+}
+
+EMIT_NATIVE_CODE(InstantiateTypeArguments, 1, true) {
+  __ InstantiateTypeArgumentsTOS(
+      type_arguments().IsRawInstantiatedRaw(type_arguments().Length()),
+      __ AddConstant(type_arguments()));
+  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther,
+                                 deopt_id(),
+                                 token_pos());
+}
+
+
+void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  __ DebugStep();
+  compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos());
+}
+
+
+void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (!compiler->CanFallThroughTo(normal_entry())) {
+    __ Jump(compiler->GetJumpLabel(normal_entry()));
+  }
+}
+
+
+LocationSummary* Instruction::MakeCallSummary(Zone* zone) {
+  LocationSummary* result = new(zone) LocationSummary(
+      zone, 0, 0, LocationSummary::kCall);
+  result->set_out(0, Location::RequiresRegister());
+  return result;
+}
+
+
+CompileType BinaryUint32OpInstr::ComputeType() const {
+  return CompileType::Int();
+}
+
+
+CompileType ShiftUint32OpInstr::ComputeType() const {
+  return CompileType::Int();
+}
+
+
+CompileType UnaryUint32OpInstr::ComputeType() const {
+  return CompileType::Int();
+}
+
+
+static const intptr_t kMintShiftCountLimit = 63;
+
+
+bool ShiftMintOpInstr::has_shift_count_check() const {
+  return !RangeUtils::IsWithin(
+      right()->definition()->range(), 0, kMintShiftCountLimit);
+}
+
+
+CompileType LoadIndexedInstr::ComputeType() const {
+  switch (class_id_) {
+    case kArrayCid:
+    case kImmutableArrayCid:
+      return CompileType::Dynamic();
+
+    case kTypedDataFloat32ArrayCid:
+    case kTypedDataFloat64ArrayCid:
+      return CompileType::FromCid(kDoubleCid);
+    case kTypedDataFloat32x4ArrayCid:
+      return CompileType::FromCid(kFloat32x4Cid);
+    case kTypedDataInt32x4ArrayCid:
+      return CompileType::FromCid(kInt32x4Cid);
+    case kTypedDataFloat64x2ArrayCid:
+      return CompileType::FromCid(kFloat64x2Cid);
+
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+    case kOneByteStringCid:
+    case kTwoByteStringCid:
+      return CompileType::FromCid(kSmiCid);
+
+    case kTypedDataInt32ArrayCid:
+    case kTypedDataUint32ArrayCid:
+      return CompileType::Int();
+
+    default:
+      UNREACHABLE();
+      return CompileType::Dynamic();
+  }
+}
+
+
+Representation LoadIndexedInstr::representation() const {
+  switch (class_id_) {
+    case kArrayCid:
+    case kImmutableArrayCid:
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+    case kOneByteStringCid:
+    case kTwoByteStringCid:
+      return kTagged;
+    case kTypedDataInt32ArrayCid:
+      return kUnboxedInt32;
+    case kTypedDataUint32ArrayCid:
+      return kUnboxedUint32;
+    case kTypedDataFloat32ArrayCid:
+    case kTypedDataFloat64ArrayCid:
+      return kUnboxedDouble;
+    case kTypedDataInt32x4ArrayCid:
+      return kUnboxedInt32x4;
+    case kTypedDataFloat32x4ArrayCid:
+      return kUnboxedFloat32x4;
+    case kTypedDataFloat64x2ArrayCid:
+      return kUnboxedFloat64x2;
+    default:
+      UNREACHABLE();
+      return kTagged;
+  }
+}
+
+
+Representation StoreIndexedInstr::RequiredInputRepresentation(
+    intptr_t idx) const {
+  // Array can be a Dart object or a pointer to external data.
+  if (idx == 0)  return kNoRepresentation;  // Flexible input representation.
+  if (idx == 1) return kTagged;  // Index is a smi.
+  ASSERT(idx == 2);
+  switch (class_id_) {
+    case kArrayCid:
+    case kOneByteStringCid:
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+      return kTagged;
+    case kTypedDataInt32ArrayCid:
+      return kUnboxedInt32;
+    case kTypedDataUint32ArrayCid:
+      return kUnboxedUint32;
+    case kTypedDataFloat32ArrayCid:
+    case kTypedDataFloat64ArrayCid:
+      return kUnboxedDouble;
+    case kTypedDataFloat32x4ArrayCid:
+      return kUnboxedFloat32x4;
+    case kTypedDataInt32x4ArrayCid:
+      return kUnboxedInt32x4;
+    case kTypedDataFloat64x2ArrayCid:
+      return kUnboxedFloat64x2;
+    default:
+      UNREACHABLE();
+      return kTagged;
+  }
+}
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 8cae087..44d16ed 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -953,19 +953,25 @@
 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Register object = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
-  Label done;
-
-  // We don't use Assembler::LoadTaggedClassIdMayBeSmi() here---which uses
-  // a conditional move instead, and requires an additional register---because
-  // it is slower, probably due to branch prediction usually working just fine
-  // in this case.
-  ASSERT(result != object);
-  __ movl(result, Immediate(kSmiCid << 1));
-  __ testl(object, Immediate(kSmiTagMask));
-  __ j(EQUAL, &done, Assembler::kNearJump);
-  __ LoadClassId(result, object);
-  __ SmiTag(result);
-  __ Bind(&done);
+  const AbstractType& value_type = *this->object()->Type()->ToAbstractType();
+  if (CompileType::Smi().IsAssignableTo(value_type) ||
+      value_type.IsTypeParameter()) {
+    // We don't use Assembler::LoadTaggedClassIdMayBeSmi() here---which uses
+    // a conditional move instead, and requires an additional register---because
+    // it is slower, probably due to branch prediction usually working just fine
+    // in this case.
+    ASSERT(result != object);
+    Label done;
+    __ movl(result, Immediate(kSmiCid << 1));
+    __ testl(object, Immediate(kSmiTagMask));
+    __ j(EQUAL, &done, Assembler::kNearJump);
+    __ LoadClassId(result, object);
+    __ SmiTag(result);
+    __ Bind(&done);
+  } else {
+    __ LoadClassId(result, object);
+    __ SmiTag(result);
+  }
 }
 
 
@@ -2669,6 +2675,12 @@
     const intptr_t value = Smi::Cast(constant).Value();
     ASSERT((0 < value) && (value < kCountLimit));
     if (shift_left->can_overflow()) {
+      if (value == 1) {
+        // Use overflow flag.
+        __ shll(left, Immediate(1));
+        __ j(OVERFLOW, deopt);
+        return;
+      }
       // Check for overflow.
       Register temp = locs.temp(0).reg();
       __ movl(temp, left);
@@ -2772,6 +2784,12 @@
   UNIMPLEMENTED();
 }
 
+
+static bool IsSmiValue(const Object& constant, intptr_t value) {
+  return constant.IsSmi() && (Smi::Cast(constant).Value() == value);
+}
+
+
 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone,
                                                        bool opt) const {
   const intptr_t kNumInputs = 2;
@@ -2815,12 +2833,16 @@
     summary->set_out(0, Location::SameAsFirstInput());
     return summary;
   } else if (op_kind() == Token::kSHL) {
-    const intptr_t kNumTemps = can_overflow() ? 1 : 0;
+    ConstantInstr* right_constant = right()->definition()->AsConstant();
+    // Shift-by-1 overflow checking can use flags, otherwise we need a temp.
+    const bool shiftBy1 =
+        (right_constant != NULL) && IsSmiValue(right_constant->value(), 1);
+    const intptr_t kNumTemps = (can_overflow() && !shiftBy1) ? 1 : 0;
     LocationSummary* summary = new(zone) LocationSummary(
         zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
     summary->set_in(0, Location::RequiresRegister());
     summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
-    if (can_overflow()) {
+    if (kNumTemps == 1) {
       summary->set_temp(0, Location::RequiresRegister());
     }
     summary->set_out(0, Location::SameAsFirstInput());
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index a8595a8..7bbfb55 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -1135,7 +1135,14 @@
 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register object = locs()->in(0).reg();
   Register result = locs()->out(0).reg();
-  __ LoadTaggedClassIdMayBeSmi(result, object);
+  const AbstractType& value_type = *this->object()->Type()->ToAbstractType();
+  if (CompileType::Smi().IsAssignableTo(value_type) ||
+      value_type.IsTypeParameter()) {
+    __ LoadTaggedClassIdMayBeSmi(result, object);
+  } else {
+    __ LoadClassId(result, object);
+    __ SmiTag(result);
+  }
 }
 
 
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 8253b0c..87b1f2e 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -926,19 +926,25 @@
 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Register object = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
-  Label load, done;
-
-  // We don't use Assembler::LoadTaggedClassIdMayBeSmi() here---which uses
-  // a conditional move instead---because it is slower, probably due to
-  // branch prediction usually working just fine in this case.
-  __ testq(object, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, &load, Assembler::kNearJump);
-  __ LoadImmediate(result, Immediate(Smi::RawValue(kSmiCid)));
-  __ jmp(&done);
-  __ Bind(&load);
-  __ LoadClassId(result, object);
-  __ SmiTag(result);
-  __ Bind(&done);
+  const AbstractType& value_type = *this->object()->Type()->ToAbstractType();
+  if (CompileType::Smi().IsAssignableTo(value_type) ||
+      value_type.IsTypeParameter()) {
+    // We don't use Assembler::LoadTaggedClassIdMayBeSmi() here---which uses
+    // a conditional move instead---because it is slower, probably due to
+    // branch prediction usually working just fine in this case.
+    Label load, done;
+    __ testq(object, Immediate(kSmiTagMask));
+    __ j(NOT_ZERO, &load, Assembler::kNearJump);
+    __ LoadImmediate(result, Immediate(Smi::RawValue(kSmiCid)));
+    __ jmp(&done);
+    __ Bind(&load);
+    __ LoadClassId(result, object);
+    __ SmiTag(result);
+    __ Bind(&done);
+  } else {
+    __ LoadClassId(result, object);
+    __ SmiTag(result);
+  }
 }
 
 
@@ -2689,6 +2695,12 @@
     const intptr_t value = Smi::Cast(constant).Value();
     ASSERT((0 < value) && (value < kCountLimit));
     if (shift_left->can_overflow()) {
+      if (value == 1) {
+        // Use overflow flag.
+        __ shlq(left, Immediate(1));
+        __ j(OVERFLOW, deopt);
+        return;
+      }
       // Check for overflow.
       Register temp = locs.temp(0).reg();
       __ movq(temp, left);
@@ -2928,6 +2940,10 @@
     Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32();
 }
 
+static bool IsSmiValue(const Object& constant, intptr_t value) {
+  return constant.IsSmi() && (Smi::Cast(constant).Value() == value);
+}
+
 
 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone,
                                                        bool opt) const {
@@ -2988,12 +3004,15 @@
     summary->set_out(0, Location::SameAsFirstInput());
     return summary;
   } else if (op_kind() == Token::kSHL) {
-    const intptr_t kNumTemps = can_overflow() ? 1 : 0;
+    // Shift-by-1 overflow checking can use flags, otherwise we need a temp.
+    const bool shiftBy1 =
+        (right_constant != NULL) && IsSmiValue(right_constant->value(), 1);
+    const intptr_t kNumTemps = (can_overflow() && !shiftBy1) ? 1 : 0;
     LocationSummary* summary = new(zone) LocationSummary(
         zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
     summary->set_in(0, Location::RequiresRegister());
     summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX));
-    if (can_overflow()) {
+    if (kNumTemps == 1) {
       summary->set_temp(0, Location::RequiresRegister());
     }
     summary->set_out(0, Location::SameAsFirstInput());
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
index f42d85e..5615e58 100644
--- a/runtime/vm/intrinsifier.cc
+++ b/runtime/vm/intrinsifier.cc
@@ -119,6 +119,9 @@
 }
 #endif  // defined(DART_NO_SNAPSHOT).
 
+
+// DBC does not use graph intrinsics.
+#if !defined(TARGET_ARCH_DBC)
 static void EmitCodeFor(FlowGraphCompiler* compiler,
                         FlowGraph* graph) {
   // The FlowGraph here is constructed by the intrinsics builder methods, and
@@ -154,10 +157,12 @@
   }
   compiler->assembler()->Comment("Graph intrinsic end");
 }
+#endif
 
 
 bool Intrinsifier::GraphIntrinsify(const ParsedFunction& parsed_function,
                                    FlowGraphCompiler* compiler) {
+#if !defined(TARGET_ARCH_DBC)
   ZoneGrowableArray<const ICData*>* ic_data_array =
       new ZoneGrowableArray<const ICData*>();
   FlowGraphBuilder builder(parsed_function,
@@ -204,6 +209,9 @@
   }
   EmitCodeFor(compiler, graph);
   return true;
+#else
+  return false;
+#endif  // !defined(TARGET_ARCH_DBC)
 }
 
 
@@ -235,10 +243,22 @@
     default:
       break;
   }
+
+  // On DBC all graph intrinsics are handled in the same way as non-graph
+  // intrinsics.
+#if defined(TARGET_ARCH_DBC)
+  switch (function.recognized_kind()) {
+    GRAPH_INTRINSICS_LIST(EMIT_CASE)
+    default:
+      break;
+  }
+#endif
+
 #undef EMIT_INTRINSIC
 }
 
 
+#if !defined(TARGET_ARCH_DBC)
 static intptr_t CidForRepresentation(Representation rep) {
   switch (rep) {
     case kUnboxedDouble:
@@ -1138,5 +1158,7 @@
   return BuildInvokeMathCFunction(&builder,
                                   MethodRecognizer::kDoubleRound);
 }
+#endif  // !defined(TARGET_ARCH_DBC)
+
 
 }  // namespace dart
diff --git a/runtime/vm/intrinsifier.h b/runtime/vm/intrinsifier.h
index 1a7e07a..54eec6e 100644
--- a/runtime/vm/intrinsifier.h
+++ b/runtime/vm/intrinsifier.h
@@ -42,15 +42,21 @@
   static void enum_name(Assembler* assembler);
 
   ALL_INTRINSICS_LIST(DECLARE_FUNCTION)
+#if defined(TARGET_ARCH_DBC)
+  // On DBC graph intrinsics are handled in the same way as non-graph ones.
+  GRAPH_INTRINSICS_LIST(DECLARE_FUNCTION)
+#endif
 
 #undef DECLARE_FUNCTION
 
+#if !defined(TARGET_ARCH_DBC)
 #define DECLARE_FUNCTION(test_class_name, test_function_name, enum_name, fp)   \
   static bool Build_##enum_name(FlowGraph* flow_graph);
 
   GRAPH_INTRINSICS_LIST(DECLARE_FUNCTION)
 
 #undef DECLARE_FUNCTION
+#endif
 };
 
 }  // namespace dart
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index 2fec757..78ab5db 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -156,8 +156,7 @@
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift)           \
   Label fall_through;                                                          \
   const intptr_t kArrayLengthStackOffset = 0 * kWordSize;                      \
-  __ MaybeTraceAllocation(cid, R2, &fall_through,                              \
-                          /* inline_isolate = */ false);                       \
+  __ MaybeTraceAllocation(cid, R2, &fall_through);                             \
   __ ldr(R2, Address(SP, kArrayLengthStackOffset));  /* Array length. */       \
   /* Check that length is a positive Smi. */                                   \
   /* R2: requested array length argument. */                                   \
@@ -193,7 +192,7 @@
                                                                                \
   /* Successfully allocated the object(s), now update top to point to */       \
   /* next object start and initialize the object. */                           \
-  __ LoadAllocationStatsAddress(R4, cid, /* inline_isolate = */ false);        \
+  __ LoadAllocationStatsAddress(R4, cid);                                      \
   __ str(R1, Address(R3, Heap::TopOffset(space)));                             \
   __ AddImmediate(R0, kHeapObjectTag);                                         \
   /* Initialize the tags. */                                                   \
@@ -1847,8 +1846,7 @@
                                      Label* failure) {
   const Register length_reg = R2;
   Label fail;
-  __ MaybeTraceAllocation(kOneByteStringCid, R0, failure,
-                          /* inline_isolate = */ false);
+  __ MaybeTraceAllocation(kOneByteStringCid, R0, failure);
   __ mov(R8, Operand(length_reg));  // Save the length register.
   // TODO(koda): Protect against negative length and overflow here.
   __ SmiUntag(length_reg);
@@ -1876,7 +1874,7 @@
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ LoadAllocationStatsAddress(R4, cid, /* inline_isolate = */ false);
+  __ LoadAllocationStatsAddress(R4, cid);
   __ str(R1, Address(R3, Heap::TopOffset(space)));
   __ AddImmediate(R0, kHeapObjectTag);
 
diff --git a/runtime/vm/intrinsifier_arm64.cc b/runtime/vm/intrinsifier_arm64.cc
index fd0c053..ba2a6f1 100644
--- a/runtime/vm/intrinsifier_arm64.cc
+++ b/runtime/vm/intrinsifier_arm64.cc
@@ -168,8 +168,7 @@
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift)           \
   Label fall_through;                                                          \
   const intptr_t kArrayLengthStackOffset = 0 * kWordSize;                      \
-  __ MaybeTraceAllocation(cid, R2, &fall_through,                              \
-                          /* inline_isolate = */ false);                       \
+  __ MaybeTraceAllocation(cid, R2, &fall_through);                             \
   __ ldr(R2, Address(SP, kArrayLengthStackOffset));  /* Array length. */       \
   /* Check that length is a positive Smi. */                                   \
   /* R2: requested array length argument. */                                   \
@@ -207,8 +206,7 @@
   /* next object start and initialize the object. */                           \
   __ str(R1, Address(R3, Heap::TopOffset(space)));                             \
   __ AddImmediate(R0, R0, kHeapObjectTag);                                     \
-  __ UpdateAllocationStatsWithSize(cid, R2, space,                             \
-                                   /* inline_isolate = */ false);              \
+  __ UpdateAllocationStatsWithSize(cid, R2, space);                            \
   /* Initialize the tags. */                                                   \
   /* R0: new object start as a tagged pointer. */                              \
   /* R1: new object end address. */                                            \
@@ -1926,8 +1924,7 @@
                                      Label* failure) {
   const Register length_reg = R2;
   Label fail;
-  __ MaybeTraceAllocation(kOneByteStringCid, R0, failure,
-                          /* inline_isolate = */ false);
+  __ MaybeTraceAllocation(kOneByteStringCid, R0, failure);
   __ mov(R6, length_reg);  // Save the length register.
   // TODO(koda): Protect against negative length and overflow here.
   __ SmiUntag(length_reg);
@@ -1957,8 +1954,7 @@
   // next object start and initialize the object.
   __ str(R1, Address(R3, Heap::TopOffset(space)));
   __ AddImmediate(R0, R0, kHeapObjectTag);
-  __ UpdateAllocationStatsWithSize(cid, R2, space,
-                                   /* inline_isolate = */ false);
+  __ UpdateAllocationStatsWithSize(cid, R2, space);
 
   // Initialize the tags.
   // R0: new object start as a tagged pointer.
diff --git a/runtime/vm/intrinsifier_dbc.cc b/runtime/vm/intrinsifier_dbc.cc
new file mode 100644
index 0000000..21a3ae0
--- /dev/null
+++ b/runtime/vm/intrinsifier_dbc.cc
@@ -0,0 +1,39 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h"  // Needed here to get TARGET_ARCH_DBC.
+#if defined(TARGET_ARCH_DBC)
+
+#include "vm/intrinsifier.h"
+
+#include "vm/assembler.h"
+#include "vm/cpu.h"
+#include "vm/dart_entry.h"
+#include "vm/flow_graph_compiler.h"
+#include "vm/object.h"
+#include "vm/object_store.h"
+#include "vm/regexp_assembler.h"
+#include "vm/symbols.h"
+#include "vm/simulator.h"
+
+namespace dart {
+
+DECLARE_FLAG(bool, interpret_irregexp);
+
+intptr_t Intrinsifier::ParameterSlotFromSp() { return -1; }
+
+#define DEFINE_FUNCTION(test_class_name, test_function_name, enum_name, fp)    \
+  void Intrinsifier::enum_name(Assembler* assembler) {                         \
+    if (Simulator::IsSupportedIntrinsic(Simulator::k##enum_name##Intrinsic)) { \
+      assembler->Intrinsic(Simulator::k##enum_name##Intrinsic);                \
+    }                                                                          \
+  }                                                                            \
+
+ALL_INTRINSICS_LIST(DEFINE_FUNCTION)
+GRAPH_INTRINSICS_LIST(DEFINE_FUNCTION)
+#undef DEFINE_FUNCTION
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index fc1f3be..fd2bc9f 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -199,8 +199,7 @@
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor)          \
   Label fall_through;                                                          \
   const intptr_t kArrayLengthStackOffset = 1 * kWordSize;                      \
-  __ MaybeTraceAllocation(cid, EDI, &fall_through, false,                      \
-                          /* inline_isolate = */ false);                       \
+  __ MaybeTraceAllocation(cid, EDI, &fall_through, false);                     \
   __ movl(EDI, Address(ESP, kArrayLengthStackOffset));  /* Array length. */    \
   /* Check that length is a positive Smi. */                                   \
   /* EDI: requested array length argument. */                                  \
@@ -244,8 +243,7 @@
   /* next object start and initialize the object. */                           \
   __ movl(Address(ECX, Heap::TopOffset(space)), EBX);                          \
   __ addl(EAX, Immediate(kHeapObjectTag));                                     \
-  __ UpdateAllocationStatsWithSize(cid, EDI, ECX, space,                       \
-                                   /* inline_isolate = */ false);              \
+  __ UpdateAllocationStatsWithSize(cid, EDI, ECX, space);                      \
                                                                                \
   /* Initialize the tags. */                                                   \
   /* EAX: new object start as a tagged pointer. */                             \
@@ -1889,8 +1887,7 @@
                                      Label* ok,
                                      Label* failure,
                                      Register length_reg) {
-  __ MaybeTraceAllocation(kOneByteStringCid, EAX, failure, false,
-                          /* inline_isolate = */ false);
+  __ MaybeTraceAllocation(kOneByteStringCid, EAX, failure, false);
   if (length_reg != EDI) {
     __ movl(EDI, length_reg);
   }
@@ -1924,8 +1921,7 @@
   __ movl(Address(ECX, Heap::TopOffset(space)), EBX);
   __ addl(EAX, Immediate(kHeapObjectTag));
 
-  __ UpdateAllocationStatsWithSize(cid, EDI, ECX, space,
-                                   /* inline_isolate = */ false);
+  __ UpdateAllocationStatsWithSize(cid, EDI, ECX, space);
 
   // Initialize the tags.
   // EAX: new object start as a tagged pointer.
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index 2c13390..e98fc1d 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -150,8 +150,7 @@
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift)           \
   Label fall_through;                                                          \
   const intptr_t kArrayLengthStackOffset = 0 * kWordSize;                      \
-  __ MaybeTraceAllocation(cid, T2, &fall_through,                              \
-                          /* inline_isolate = */ false);                       \
+  __ MaybeTraceAllocation(cid, T2, &fall_through);                             \
   __ lw(T2, Address(SP, kArrayLengthStackOffset));  /* Array length. */        \
   /* Check that length is a positive Smi. */                                   \
   /* T2: requested array length argument. */                                   \
@@ -188,8 +187,7 @@
   /* next object start and initialize the object. */                           \
   __ sw(T1, Address(T3, Heap::TopOffset(space)));                              \
   __ AddImmediate(V0, kHeapObjectTag);                                         \
-  __ UpdateAllocationStatsWithSize(cid, T2, T4, space,                         \
-                                   /* inline_isolate = */ false);              \
+  __ UpdateAllocationStatsWithSize(cid, T2, T4, space);                        \
   /* Initialize the tags. */                                                   \
   /* V0: new object start as a tagged pointer. */                              \
   /* T1: new object end address. */                                            \
@@ -1967,8 +1965,7 @@
                                      Label* ok,
                                      Label* failure) {
   const Register length_reg = T2;
-  __ MaybeTraceAllocation(kOneByteStringCid, V0, failure,
-                          /* inline_isolate = */ false);
+  __ MaybeTraceAllocation(kOneByteStringCid, V0, failure);
   __ mov(T6, length_reg);  // Save the length register.
   // TODO(koda): Protect against negative length and overflow here.
   __ SmiUntag(length_reg);
@@ -1999,8 +1996,7 @@
   __ sw(T1, Address(T3, Heap::TopOffset(space)));
   __ AddImmediate(V0, kHeapObjectTag);
 
-  __ UpdateAllocationStatsWithSize(cid, T2, T3, space,
-                                   /* inline_isolate = */ false);
+  __ UpdateAllocationStatsWithSize(cid, T2, T3, space);
 
   // Initialize the tags.
   // V0: new object start as a tagged pointer.
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index 66bc4c2..ab2fa94 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -141,8 +141,7 @@
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor)          \
   Label fall_through;                                                          \
   const intptr_t kArrayLengthStackOffset = 1 * kWordSize;                      \
-  __ MaybeTraceAllocation(cid, &fall_through, false,                           \
-                          /* inline_isolate = */ false);                       \
+  __ MaybeTraceAllocation(cid, &fall_through, false);                          \
   __ movq(RDI, Address(RSP, kArrayLengthStackOffset));  /* Array length. */    \
   /* Check that length is a positive Smi. */                                   \
   /* RDI: requested array length argument. */                                  \
@@ -186,8 +185,7 @@
   /* next object start and initialize the object. */                           \
   __ movq(Address(R13, Heap::TopOffset(space)), RCX);                          \
   __ addq(RAX, Immediate(kHeapObjectTag));                                     \
-  __ UpdateAllocationStatsWithSize(cid, RDI, space,                            \
-                                   /* inline_isolate = */ false);              \
+  __ UpdateAllocationStatsWithSize(cid, RDI, space);                           \
   /* Initialize the tags. */                                                   \
   /* RAX: new object start as a tagged pointer. */                             \
   /* RCX: new object end address. */                                           \
@@ -1845,8 +1843,7 @@
                                      Label* ok,
                                      Label* failure,
                                      Register length_reg) {
-  __ MaybeTraceAllocation(kOneByteStringCid, failure, false,
-                          /* inline_isolate = */ false);
+  __ MaybeTraceAllocation(kOneByteStringCid, failure, false);
   if (length_reg != RDI) {
     __ movq(RDI, length_reg);
   }
@@ -1879,8 +1876,7 @@
   // next object start and initialize the object.
   __ movq(Address(R13, Heap::TopOffset(space)), RCX);
   __ addq(RAX, Immediate(kHeapObjectTag));
-  __ UpdateAllocationStatsWithSize(cid, RDI, space,
-                                   /* inline_isolate = */ false);
+  __ UpdateAllocationStatsWithSize(cid, RDI, space);
 
   // Initialize the tags.
   // RAX: new object start as a tagged pointer.
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 51e0c7e..287079a 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -993,6 +993,7 @@
     if (lib.LoadInProgress()) {
       lib.SetLoaded();
     }
+    lib.InitExportedNamesCache();
   }
   TokenStream::CloseSharedTokenList(this);
 }
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 3250082..8061619 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -381,6 +381,8 @@
     return background_compiler_;
   }
   void set_background_compiler(BackgroundCompiler* value) {
+    // Do not overwrite a background compiler (memory leak).
+    ASSERT((value == NULL) || (background_compiler_ == NULL));
     background_compiler_ = value;
   }
 
diff --git a/runtime/vm/jit_optimizer.cc b/runtime/vm/jit_optimizer.cc
index 8a22c85..b0be614 100644
--- a/runtime/vm/jit_optimizer.cc
+++ b/runtime/vm/jit_optimizer.cc
@@ -1881,71 +1881,6 @@
     return TryInlineFloat64x2Method(call, recognized_kind);
   }
 
-  if (recognized_kind == MethodRecognizer::kIntegerLeftShiftWithMask32) {
-    ASSERT(call->ArgumentCount() == 3);
-    ASSERT(ic_data.NumArgsTested() == 2);
-    Definition* value = call->ArgumentAt(0);
-    Definition* count = call->ArgumentAt(1);
-    Definition* int32_mask = call->ArgumentAt(2);
-    if (HasOnlyTwoOf(ic_data, kSmiCid)) {
-      if (ic_data.HasDeoptReason(ICData::kDeoptBinaryMintOp)) {
-        return false;
-      }
-      // We cannot overflow. The input value must be a Smi
-      AddCheckSmi(value, call->deopt_id(), call->env(), call);
-      AddCheckSmi(count, call->deopt_id(), call->env(), call);
-      ASSERT(int32_mask->IsConstant());
-      const Integer& mask_literal = Integer::Cast(
-          int32_mask->AsConstant()->value());
-      const int64_t mask_value = mask_literal.AsInt64Value();
-      ASSERT(mask_value >= 0);
-      if (mask_value > Smi::kMaxValue) {
-        // The result will not be Smi.
-        return false;
-      }
-      BinarySmiOpInstr* left_shift =
-          new(Z) BinarySmiOpInstr(Token::kSHL,
-                                  new(Z) Value(value),
-                                  new(Z) Value(count),
-                                  call->deopt_id());
-      left_shift->mark_truncating();
-      if ((kBitsPerWord == 32) && (mask_value == 0xffffffffLL)) {
-        // No BIT_AND operation needed.
-        ReplaceCall(call, left_shift);
-      } else {
-        InsertBefore(call, left_shift, call->env(), FlowGraph::kValue);
-        BinarySmiOpInstr* bit_and =
-            new(Z) BinarySmiOpInstr(Token::kBIT_AND,
-                                    new(Z) Value(left_shift),
-                                    new(Z) Value(int32_mask),
-                                    call->deopt_id());
-        ReplaceCall(call, bit_and);
-      }
-      return true;
-    }
-
-    if (HasTwoMintOrSmi(ic_data) &&
-        HasOnlyOneSmi(ICData::Handle(Z,
-                                     ic_data.AsUnaryClassChecksForArgNr(1)))) {
-      if (!FlowGraphCompiler::SupportsUnboxedMints() ||
-          ic_data.HasDeoptReason(ICData::kDeoptBinaryMintOp)) {
-        return false;
-      }
-      ShiftMintOpInstr* left_shift =
-          new(Z) ShiftMintOpInstr(Token::kSHL,
-                                  new(Z) Value(value),
-                                  new(Z) Value(count),
-                                  call->deopt_id());
-      InsertBefore(call, left_shift, call->env(), FlowGraph::kValue);
-      BinaryMintOpInstr* bit_and =
-          new(Z) BinaryMintOpInstr(Token::kBIT_AND,
-                                   new(Z) Value(left_shift),
-                                   new(Z) Value(int32_mask),
-                                   call->deopt_id());
-      ReplaceCall(call, bit_and);
-      return true;
-    }
-  }
   return false;
 }
 
@@ -2991,7 +2926,8 @@
       // - deoptimize dependent code.
       if (Compiler::IsBackgroundCompilation()) {
         isolate()->AddDeoptimizingBoxedField(field);
-        Compiler::AbortBackgroundCompilation(Thread::kNoDeoptId);
+        Compiler::AbortBackgroundCompilation(Thread::kNoDeoptId,
+            "Unboxing instance field while compiling");
         UNREACHABLE();
       }
       if (FLAG_trace_optimization || FLAG_trace_field_guards) {
diff --git a/runtime/vm/locations.cc b/runtime/vm/locations.cc
index 8a9499e..5603a1c 100644
--- a/runtime/vm/locations.cc
+++ b/runtime/vm/locations.cc
@@ -118,6 +118,8 @@
 }
 
 
+// DBC does not have an notion of 'address' in its instruction set.
+#if !defined(TARGET_ARCH_DBC)
 Address Location::ToStackSlotAddress() const {
   const intptr_t index = stack_index();
   const Register base = base_reg();
@@ -134,7 +136,7 @@
     return Address(base, index * kWordSize);
   }
 }
-
+#endif
 
 intptr_t Location::ToStackSlotOffset() const {
   const intptr_t index = stack_index();
diff --git a/runtime/vm/locations.h b/runtime/vm/locations.h
index 963c4b4..fae87a7 100644
--- a/runtime/vm/locations.h
+++ b/runtime/vm/locations.h
@@ -341,8 +341,11 @@
     return IsStackSlot() || IsDoubleStackSlot() || IsQuadStackSlot();
   }
 
+  // DBC does not have an notion of 'address' in its instruction set.
+#if !defined(TARGET_ARCH_DBC)
   // Return a memory operand for stack slot locations.
   Address ToStackSlotAddress() const;
+#endif
 
   // Returns the offset from the frame pointer for stack slot locations.
   intptr_t ToStackSlotOffset() const;
@@ -650,9 +653,13 @@
 
   void set_out(intptr_t index, Location loc) {
     ASSERT(index == 0);
+    // DBC calls are different from call on other architectures so this
+    // assert doesn't make sense.
+#if !defined(TARGET_ARCH_DBC)
     ASSERT(!always_calls() ||
            (loc.IsMachineRegister() || loc.IsInvalid() ||
             loc.IsPairLocation()));
+#endif
     output_location_ = loc;
   }
 
diff --git a/runtime/vm/log.cc b/runtime/vm/log.cc
index 91be51d..f5247c7 100644
--- a/runtime/vm/log.cc
+++ b/runtime/vm/log.cc
@@ -31,6 +31,11 @@
 
 Log* Log::Current() {
   Thread* thread = Thread::Current();
+  if (thread == NULL) {
+    OSThread* os_thread = OSThread::Current();
+    ASSERT(os_thread != NULL);
+    return os_thread->log();
+  }
   Isolate* isolate = thread->isolate();
   if (isolate != NULL && Log::ShouldLogForIsolate(isolate)) {
     OSThread* os_thread = thread->os_thread();
diff --git a/runtime/vm/method_recognizer.h b/runtime/vm/method_recognizer.h
index 7efa6e7..a3e0eda 100644
--- a/runtime/vm/method_recognizer.h
+++ b/runtime/vm/method_recognizer.h
@@ -41,8 +41,6 @@
   V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, 2075229300)              \
   V(_StringBase, _interpolate, StringBaseInterpolate, 1597087225)              \
   V(_IntegerImplementation, toDouble, IntegerToDouble, 150718448)              \
-  V(_IntegerImplementation, _leftShiftWithMask32,                              \
-      IntegerLeftShiftWithMask32, 1634465017)                                  \
   V(_Double, _add, DoubleAdd, 1190606283)                                      \
   V(_Double, _sub, DoubleSub, 1086286468)                                      \
   V(_Double, _mul, DoubleMul, 166332351)                                       \
@@ -256,7 +254,7 @@
   V(Int32x4List, ., TypedData_Int32x4Array_factory, 504220232)                 \
   V(Float64x2List, ., TypedData_Float64x2Array_factory, 416019673)             \
 
-#define GRAPH_TYPED_DATA_INTRINSICS_LIST(V) \
+#define GRAPH_TYPED_DATA_INTRINSICS_LIST(V)                                    \
   V(Uint8List, [], Uint8ArrayGetIndexed, 513704632)                            \
   V(Uint8List, []=, Uint8ArraySetIndexed, 2123520783)                          \
   V(_ExternalUint8Array, [], ExternalUint8ArrayGetIndexed, 513704632)          \
@@ -310,7 +308,6 @@
   MATH_LIB_INTRINSIC_LIST(V)                                                   \
   TYPED_DATA_LIB_INTRINSIC_LIST(V)                                             \
 
-
 #define ALL_INTRINSICS_LIST(V)                                                 \
   ALL_INTRINSICS_NO_INTEGER_LIB_LIST(V)                                        \
   CORE_INTEGER_LIB_INTRINSIC_LIST(V)
diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h
index 88bc411..7035a50 100644
--- a/runtime/vm/native_arguments.h
+++ b/runtime/vm/native_arguments.h
@@ -25,7 +25,10 @@
 
 #if defined(TESTING) || defined(DEBUG)
 
-#if defined(USING_SIMULATOR)
+#if defined(TARGET_ARCH_DBC)
+// C-stack is always aligned on DBC because we don't have any native code.
+#define CHECK_STACK_ALIGNMENT
+#elif defined(USING_SIMULATOR)
 #define CHECK_STACK_ALIGNMENT {                                                \
   uword current_sp = Simulator::Current()->get_register(SPREG);                \
   ASSERT(Utils::IsAligned(current_sp, OS::ActivationFrameAlignment()));        \
@@ -92,7 +95,13 @@
 
   RawObject* ArgAt(int index) const {
     ASSERT((index >= 0) && (index < ArgCount()));
-    RawObject** arg_ptr = &((*argv_)[-index]);
+#if defined(TARGET_ARCH_DBC)
+    // On DBC stack is growing upwards, in reverse direction from all other
+    // architectures.
+    RawObject** arg_ptr = &(argv_[index]);
+#else
+    RawObject** arg_ptr = &(argv_[-index]);
+#endif
     // Tell MemorySanitizer the RawObject* was initialized (by generated code).
     MSAN_UNPOISON(arg_ptr, kWordSize);
     return *arg_ptr;
@@ -204,6 +213,16 @@
   friend class BootstrapNatives;
   friend class Simulator;
 
+#if defined(TARGET_ARCH_DBC)
+  // Allow simulator to create NativeArguments on the stack.
+  NativeArguments(Thread* thread,
+                  int argc_tag,
+                  RawObject** argv,
+                  RawObject** retval)
+      : thread_(thread), argc_tag_(argc_tag), argv_(argv), retval_(retval) {
+  }
+#endif
+
   // Since this function is passed a RawObject directly, we need to be
   // exceedingly careful when we use it.  If there are any other side
   // effects in the statement that may cause GC, it could lead to
@@ -235,7 +254,7 @@
 
   Thread* thread_;  // Current thread pointer.
   intptr_t argc_tag_;  // Encodes argument count and invoked native call type.
-  RawObject*(*argv_)[];  // Pointer to an array of arguments to runtime call.
+  RawObject** argv_;  // Pointer to an array of arguments to runtime call.
   RawObject** retval_;  // Pointer to the return value area.
 };
 
diff --git a/runtime/vm/native_entry.cc b/runtime/vm/native_entry.cc
index a5c79d3..e1e7e45 100644
--- a/runtime/vm/native_entry.cc
+++ b/runtime/vm/native_entry.cc
@@ -90,7 +90,8 @@
 
 uword NativeEntry::NativeCallWrapperEntry() {
   uword entry = reinterpret_cast<uword>(NativeEntry::NativeCallWrapper);
-#if defined(USING_SIMULATOR)
+#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
+  // DBC does not use redirections unlike other simulators.
   entry = Simulator::RedirectExternalReference(
       entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments);
 #endif
@@ -177,6 +178,8 @@
 }
 
 
+// DBC does not support lazy native call linking.
+#if !defined(TARGET_ARCH_DBC)
 static NativeFunction ResolveNativeFunction(Zone* zone,
                                             const Function& func,
                                             bool* is_bootstrap_native) {
@@ -260,9 +263,10 @@
 #endif
 
     call_through_wrapper = !is_bootstrap_native;
-    const Code& trampoline = Code::Handle(call_through_wrapper ?
-        StubCode::CallNativeCFunction_entry()->code() :
-        StubCode::CallBootstrapCFunction_entry()->code());
+    const Code& trampoline =
+        Code::Handle(call_through_wrapper ?
+            StubCode::CallNativeCFunction_entry()->code() :
+            StubCode::CallBootstrapCFunction_entry()->code());
 
     NativeFunction patch_target_function = target_function;
 #if defined(USING_SIMULATOR)
@@ -295,6 +299,7 @@
     target_function(arguments);
   }
 }
+#endif  // !defined(TARGET_ARCH_DBC)
 
 
 }  // namespace dart
diff --git a/runtime/vm/native_entry.h b/runtime/vm/native_entry.h
index 9557073..4be2cc3 100644
--- a/runtime/vm/native_entry.h
+++ b/runtime/vm/native_entry.h
@@ -118,8 +118,11 @@
   static void NativeCallWrapper(Dart_NativeArguments args,
                                 Dart_NativeFunction func);
 
+  // DBC does not support lazy native call linking.
+#if !defined(TARGET_ARCH_DBC)
   static uword LinkNativeCallEntry();
   static void LinkNativeCall(Dart_NativeArguments args);
+#endif
 
  private:
   static void NativeCallWrapperNoStackCheck(Dart_NativeArguments args,
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 2ce486b..cc566b7 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -57,6 +57,7 @@
     "Show names of internal classes (e.g. \"OneByteString\") in error messages "
     "instead of showing the corresponding interface names (e.g. \"String\")");
 DEFINE_FLAG(bool, use_lib_cache, true, "Use library name cache");
+DEFINE_FLAG(bool, use_exp_cache, true, "Use library exported name cache");
 DEFINE_FLAG(bool, ignore_patch_signature_mismatch, false,
             "Ignore patch file member signature mismatch.");
 
@@ -705,6 +706,7 @@
         empty_array_,
         reinterpret_cast<RawArray*>(address + kHeapObjectTag));
     empty_array_->StoreSmi(&empty_array_->raw_ptr()->length_, Smi::New(0));
+    empty_array_->SetCanonical();
   }
 
   Smi& smi = Smi::Handle();
@@ -718,6 +720,7 @@
     zero_array_->StoreSmi(&zero_array_->raw_ptr()->length_, Smi::New(1));
     smi = Smi::New(0);
     zero_array_->SetAt(0, smi);
+    zero_array_->SetCanonical();
   }
 
   // Allocate and initialize the canonical empty context scope object.
@@ -734,6 +737,7 @@
         &empty_context_scope_->raw_ptr()->num_variables_, 0);
     empty_context_scope_->StoreNonPointer(
         &empty_context_scope_->raw_ptr()->is_implicit_, true);
+    empty_context_scope_->SetCanonical();
   }
 
   // Allocate and initialize the canonical empty object pool object.
@@ -749,6 +753,7 @@
         reinterpret_cast<RawObjectPool*>(address + kHeapObjectTag));
     empty_object_pool_->StoreNonPointer(
         &empty_object_pool_->raw_ptr()->length_, 0);
+    empty_object_pool_->SetCanonical();
   }
 
   // Allocate and initialize the empty_descriptors instance.
@@ -762,6 +767,7 @@
         reinterpret_cast<RawPcDescriptors*>(address + kHeapObjectTag));
     empty_descriptors_->StoreNonPointer(&empty_descriptors_->raw_ptr()->length_,
                                         0);
+    empty_descriptors_->SetCanonical();
   }
 
   // Allocate and initialize the canonical empty variable descriptor object.
@@ -777,6 +783,7 @@
         reinterpret_cast<RawLocalVarDescriptors*>(address + kHeapObjectTag));
     empty_var_descriptors_->StoreNonPointer(
         &empty_var_descriptors_->raw_ptr()->num_entries_, 0);
+    empty_var_descriptors_->SetCanonical();
   }
 
   // Allocate and initialize the canonical empty exception handler info object.
@@ -794,6 +801,7 @@
         reinterpret_cast<RawExceptionHandlers*>(address + kHeapObjectTag));
     empty_exception_handlers_->StoreNonPointer(
         &empty_exception_handlers_->raw_ptr()->num_entries_, 0);
+    empty_exception_handlers_->SetCanonical();
   }
 
   // The VM isolate snapshot object table is initialized to an empty array
@@ -2089,6 +2097,7 @@
 class ClassFunctionsTraits {
  public:
   static const char* Name() { return "ClassFunctionsTraits"; }
+  static bool ReportStats() { return false; }
 
   // Called when growing the table.
   static bool IsMatch(const Object& a, const Object& b) {
@@ -3040,6 +3049,7 @@
 RawObject* Class::Evaluate(const String& expr,
                            const Array& param_names,
                            const Array& param_values) const {
+  ASSERT(Thread::Current()->IsMutatorThread());
   const Function& eval_func =
       Function::Handle(EvaluateHelper(*this, expr, param_names, true));
   const Object& result =
@@ -3055,7 +3065,8 @@
     return Error::null();
   }
   if (Compiler::IsBackgroundCompilation()) {
-    Compiler::AbortBackgroundCompilation(Thread::kNoDeoptId);
+    Compiler::AbortBackgroundCompilation(Thread::kNoDeoptId,
+        "Class finalization while compiling");
   }
   ASSERT(thread->IsMutatorThread());
   ASSERT(thread != NULL);
@@ -4420,44 +4431,88 @@
 }
 
 
-RawInstance* Class::LookupCanonicalInstance(Zone* zone,
-                                            const Instance& value,
-                                            intptr_t* index) const {
-  ASSERT(this->raw() == value.clazz());
-  const Array& constants = Array::Handle(zone, this->constants());
-  const intptr_t constants_len = constants.Length();
-  // Linear search to see whether this value is already present in the
-  // list of canonicalized constants.
-  Instance& canonical_value = Instance::Handle(zone);
-  while (*index < constants_len) {
-    canonical_value ^= constants.At(*index);
-    if (canonical_value.IsNull()) {
-      break;
-    }
-    if (value.CanonicalizeEquals(canonical_value)) {
-      ASSERT(canonical_value.IsCanonical());
-      return canonical_value.raw();
-    }
-    *index = *index + 1;
+class CanonicalInstanceKey {
+ public:
+  explicit CanonicalInstanceKey(const Instance& key) : key_(key) {
+    ASSERT(!(key.IsString() || key.IsInteger() || key.IsAbstractType()));
   }
-  return Instance::null();
+  bool Matches(const Instance& obj) const {
+    ASSERT(!(obj.IsString() || obj.IsInteger() || obj.IsAbstractType()));
+    if (key_.CanonicalizeEquals(obj)) {
+      ASSERT(obj.IsCanonical());
+      return true;
+    }
+    return false;
+  }
+  uword Hash() const {
+    return key_.ComputeCanonicalTableHash();
+  }
+  const Instance& key_;
+
+ private:
+  DISALLOW_ALLOCATION();
+};
+
+
+// Traits for looking up Canonical Instances based on a hash of the fields.
+class CanonicalInstanceTraits {
+ public:
+  static const char* Name() { return "CanonicalInstanceTraits"; }
+  static bool ReportStats() { return false; }
+
+  // Called when growing the table.
+  static bool IsMatch(const Object& a, const Object& b) {
+    ASSERT(!(a.IsString() || a.IsInteger() || a.IsAbstractType()));
+    ASSERT(!(b.IsString() || b.IsInteger() || b.IsAbstractType()));
+    return a.raw() == b.raw();
+  }
+  static bool IsMatch(const CanonicalInstanceKey& a, const Object& b) {
+    return a.Matches(Instance::Cast(b));
+  }
+  static uword Hash(const Object& key) {
+    ASSERT(!(key.IsString() || key.IsNumber() || key.IsAbstractType()));
+    ASSERT(key.IsInstance());
+    return Instance::Cast(key).ComputeCanonicalTableHash();
+  }
+  static uword Hash(const CanonicalInstanceKey& key) {
+    return key.Hash();
+  }
+  static RawObject* NewKey(const CanonicalInstanceKey& obj) {
+    return obj.key_.raw();
+  }
+};
+typedef UnorderedHashSet <CanonicalInstanceTraits> CanonicalInstancesSet;
+
+
+RawInstance* Class::LookupCanonicalInstance(Zone* zone,
+                                            const Instance& value) const {
+  ASSERT(this->raw() == value.clazz());
+  Instance& canonical_value = Instance::Handle(zone);
+  if (this->constants() != Object::empty_array().raw()) {
+    CanonicalInstancesSet constants(zone, this->constants());
+    canonical_value ^= constants.GetOrNull(CanonicalInstanceKey(value));
+    this->set_constants(constants.Release());
+  }
+  return canonical_value.raw();
 }
 
 
-void Class::InsertCanonicalConstant(intptr_t index,
-                                    const Instance& constant) const {
-  // The constant needs to be added to the list. Grow the list if it is full.
-  Array& canonical_list = Array::Handle(constants());
-  const intptr_t list_len = canonical_list.Length();
-  if (index >= list_len) {
-    const intptr_t new_length = (list_len == 0) ? 4 : list_len + 4;
-    const Array& new_canonical_list =
-        Array::Handle(Array::Grow(canonical_list, new_length, Heap::kOld));
-    set_constants(new_canonical_list);
-    new_canonical_list.SetAt(index, constant);
+RawInstance* Class::InsertCanonicalConstant(Zone* zone,
+                                            const Instance& constant) const {
+  ASSERT(this->raw() == constant.clazz());
+  Instance& canonical_value = Instance::Handle(zone);
+  if (this->constants() == Object::empty_array().raw()) {
+    CanonicalInstancesSet constants(
+        HashTables::New<CanonicalInstancesSet>(128, Heap::kOld));
+    canonical_value ^= constants.InsertNewOrGet(CanonicalInstanceKey(constant));
+    this->set_constants(constants.Release());
   } else {
-    canonical_list.SetAt(index, constant);
+    CanonicalInstancesSet constants(Thread::Current()->zone(),
+                                    this->constants());
+    canonical_value ^= constants.InsertNewOrGet(CanonicalInstanceKey(constant));
+    this->set_constants(constants.Release());
   }
+  return canonical_value.raw();
 }
 
 
@@ -4476,6 +4531,29 @@
 }
 
 
+void Class::RehashConstants(Zone* zone) const {
+  intptr_t cid = id();
+  if ((cid == kMintCid) || (cid == kBigintCid) || (cid == kDoubleCid)) {
+    // Constants stored as a plain list, no rehashing needed.
+    return;
+  }
+
+  const Array& old_constants = Array::Handle(zone, constants());
+  if (old_constants.Length() == 0) return;
+
+  set_constants(Object::empty_array());
+  CanonicalInstancesSet set(zone, old_constants.raw());
+  Instance& constant = Instance::Handle(zone);
+  CanonicalInstancesSet::Iterator it(&set);
+  while (it.MoveNext()) {
+    constant ^= set.GetKey(it.Current());
+    ASSERT(!constant.IsNull());
+    InsertCanonicalConstant(zone, constant);
+  }
+  set.Release();
+}
+
+
 RawUnresolvedClass* UnresolvedClass::New(const LibraryPrefix& library_prefix,
                                          const String& ident,
                                          TokenPosition token_pos) {
@@ -8333,6 +8411,7 @@
 class CompressedTokenTraits {
  public:
   static const char* Name() { return "CompressedTokenTraits"; }
+  static bool ReportStats() { return false; }
 
   static bool IsMatch(const Scanner::TokenDescriptor& descriptor,
                       const Object& key) {
@@ -9263,6 +9342,7 @@
 class LibraryUrlTraits {
  public:
   static const char* Name() { return "LibraryUrlTraits"; }
+  static bool ReportStats() { return false; }
 
   // Called when growing the table.
   static bool IsMatch(const Object& a, const Object& b) {
@@ -9312,6 +9392,7 @@
 
 
 void Library::AddPatchClass(const Class& cls) const {
+  ASSERT(Thread::Current()->IsMutatorThread());
   ASSERT(cls.is_patch());
   ASSERT(GetPatchClass(String::Handle(cls.Name())) == Class::null());
   const GrowableObjectArray& patch_classes =
@@ -9321,6 +9402,7 @@
 
 
 RawClass* Library::GetPatchClass(const String& name) const {
+  ASSERT(Thread::Current()->IsMutatorThread());
   const GrowableObjectArray& patch_classes =
       GrowableObjectArray::Handle(this->patch_classes());
   Object& obj = Object::Handle();
@@ -9336,6 +9418,7 @@
 
 
 void Library::RemovePatchClass(const Class& cls) const {
+  ASSERT(Thread::Current()->IsMutatorThread());
   ASSERT(cls.is_patch());
   const GrowableObjectArray& patch_classes =
       GrowableObjectArray::Handle(this->patch_classes());
@@ -9403,6 +9486,7 @@
                           const String& name,
                           TokenPosition token_pos) const {
   Thread* thread = Thread::Current();
+  ASSERT(thread->IsMutatorThread());
   Zone* zone = thread->zone();
   const String& metaname = String::Handle(zone, Symbols::New(thread, name));
   const Field& field = Field::Handle(zone,
@@ -9490,6 +9574,7 @@
 
 
 RawField* Library::GetMetadataField(const String& metaname) const {
+  ASSERT(Thread::Current()->IsMutatorThread());
   const GrowableObjectArray& metadata =
       GrowableObjectArray::Handle(this->metadata());
   Field& entry = Field::Handle();
@@ -9574,6 +9659,7 @@
 class StringEqualsTraits {
  public:
   static const char* Name() { return "StringEqualsTraits"; }
+  static bool ReportStats() { return false; }
 
   static bool IsMatch(const Object& a, const Object& b) {
     return String::Cast(a).Equals(String::Cast(b));
@@ -9595,8 +9681,15 @@
   *obj = cache.GetOrNull(name, &present);
   // Mutator compiler thread may add entries and therefore
   // change 'resolved_names()' while running a background compilation;
-  // do not ASSERT that 'resolved_names()' has not changed.
-  cache.Release();
+  // ASSERT that 'resolved_names()' has not changed only in mutator.
+#if defined(DEBUG)
+  if (Thread::Current()->IsMutatorThread()) {
+    ASSERT(cache.Release().raw() == resolved_names());
+  } else {
+    // Release must be called in debug mode.
+    cache.Release();
+  }
+#endif
   return present;
 }
 
@@ -9606,8 +9699,7 @@
 // the name does not resolve to anything in this library scope.
 void Library::AddToResolvedNamesCache(const String& name,
                                       const Object& obj) const {
-  ASSERT(!Compiler::IsBackgroundCompilation());
-  if (!FLAG_use_lib_cache) {
+  if (!FLAG_use_lib_cache || Compiler::IsBackgroundCompilation()) {
     return;
   }
   ResolvedNamesMap cache(resolved_names());
@@ -9616,12 +9708,64 @@
 }
 
 
+bool Library::LookupExportedNamesCache(const String& name,
+                                       Object* obj) const {
+  ASSERT(FLAG_use_exp_cache);
+  if (exported_names() == Array::null()) {
+    return false;
+  }
+  ResolvedNamesMap cache(exported_names());
+  bool present = false;
+  *obj = cache.GetOrNull(name, &present);
+  // Mutator compiler thread may add entries and therefore
+  // change 'exported_names()' while running a background compilation;
+  // do not ASSERT that 'exported_names()' has not changed.
+#if defined(DEBUG)
+  if (Thread::Current()->IsMutatorThread()) {
+    ASSERT(cache.Release().raw() == exported_names());
+  } else {
+    // Release must be called in debug mode.
+    cache.Release();
+  }
+#endif
+  return present;
+}
+
+void Library::AddToExportedNamesCache(const String& name,
+                                      const Object& obj) const {
+  if (!FLAG_use_exp_cache || Compiler::IsBackgroundCompilation()) {
+    return;
+  }
+  if (exported_names() == Array::null()) {
+    AllocateExportedNamesCache();
+  }
+  ResolvedNamesMap cache(exported_names());
+  cache.UpdateOrInsert(name, obj);
+  StorePointer(&raw_ptr()->exported_names_, cache.Release().raw());
+}
+
+
 void Library::InvalidateResolvedName(const String& name) const {
-  Object& entry = Object::Handle();
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  Object& entry = Object::Handle(zone);
   if (LookupResolvedNamesCache(name, &entry)) {
     // TODO(koda): Support deleted sentinel in snapshots and remove only 'name'.
     InvalidateResolvedNamesCache();
   }
+  // When a new name is added to a library, we need to invalidate all
+  // caches that contain an entry for this name. If the name was previously
+  // looked up but could not be resolved, the cache contains a null entry.
+  GrowableObjectArray& libs = GrowableObjectArray::Handle(
+      zone, thread->isolate()->object_store()->libraries());
+  Library& lib = Library::Handle(zone);
+  intptr_t num_libs = libs.Length();
+  for (intptr_t i = 0; i < num_libs; i++) {
+    lib ^= libs.At(i);
+    if (lib.LookupExportedNamesCache(name, &entry)) {
+      lib.InitExportedNamesCache();
+    }
+  }
 }
 
 
@@ -9631,6 +9775,19 @@
 }
 
 
+// Invalidate all exported names caches in the isolate.
+void Library::InvalidateExportedNamesCaches() {
+  GrowableObjectArray& libs = GrowableObjectArray::Handle(
+      Isolate::Current()->object_store()->libraries());
+  Library& lib = Library::Handle();
+  intptr_t num_libs = libs.Length();
+  for (intptr_t i = 0; i < num_libs; i++) {
+    lib ^= libs.At(i);
+    lib.InitExportedNamesCache();
+  }
+}
+
+
 void Library::GrowDictionary(const Array& dict, intptr_t dict_size) const {
   // TODO(iposva): Avoid exponential growth.
   intptr_t new_dict_size = dict_size * 2;
@@ -9665,7 +9822,7 @@
 
 
 void Library::AddObject(const Object& obj, const String& name) const {
-  ASSERT(!Compiler::IsBackgroundCompilation());
+  ASSERT(Thread::Current()->IsMutatorThread());
   ASSERT(obj.IsClass() ||
          obj.IsFunction() ||
          obj.IsField() ||
@@ -9706,42 +9863,45 @@
 // Lookup a name in the library's re-export namespace.
 // This lookup can occur from two different threads: background compiler and
 // mutator thread.
-RawObject* Library::LookupReExport(const String& name) const {
-  if (HasExports()) {
-    const bool is_background_compiler = Compiler::IsBackgroundCompilation();
-    Array& exports = Array::Handle();
-    if (is_background_compiler) {
-      exports = this->exports2();
-      // Break potential export cycle while looking up name.
-      StorePointer(&raw_ptr()->exports2_, Object::empty_array().raw());
-    } else {
-      exports = this->exports();
-      // Break potential export cycle while looking up name.
-      StorePointer(&raw_ptr()->exports_, Object::empty_array().raw());
-    }
-    Namespace& ns = Namespace::Handle();
-    Object& obj = Object::Handle();
-    for (int i = 0; i < exports.Length(); i++) {
-      ns ^= exports.At(i);
-      obj = ns.Lookup(name);
-      if (!obj.IsNull()) {
-        // The Lookup call above may return a setter x= when we are looking
-        // for the name x. Make sure we only return when a matching name
-        // is found.
-        String& obj_name = String::Handle(obj.DictionaryName());
-        if (Field::IsSetterName(obj_name) == Field::IsSetterName(name)) {
-          break;
-        }
-      }
-    }
-    if (is_background_compiler) {
-      StorePointer(&raw_ptr()->exports2_, exports.raw());
-    } else {
-      StorePointer(&raw_ptr()->exports_, exports.raw());
-    }
+RawObject* Library::LookupReExport(const String& name,
+                                   ZoneGrowableArray<intptr_t>* trail) const {
+  if (!HasExports()) {
+    return Object::null();
+  }
+
+  if (trail == NULL) {
+    trail = new ZoneGrowableArray<intptr_t>();
+  }
+  Object& obj = Object::Handle();
+  if (FLAG_use_exp_cache && LookupExportedNamesCache(name, &obj)) {
     return obj.raw();
   }
-  return Object::null();
+
+  const intptr_t lib_id = this->index();
+  ASSERT(lib_id >= 0);  // We use -1 to indicate that a cycle was found.
+  trail->Add(lib_id);
+  const Array& exports = Array::Handle(this->exports());
+  Namespace& ns = Namespace::Handle();
+  for (int i = 0; i < exports.Length(); i++) {
+    ns ^= exports.At(i);
+    obj = ns.Lookup(name, trail);
+    if (!obj.IsNull()) {
+      // The Lookup call above may return a setter x= when we are looking
+      // for the name x. Make sure we only return when a matching name
+      // is found.
+      String& obj_name = String::Handle(obj.DictionaryName());
+      if (Field::IsSetterName(obj_name) == Field::IsSetterName(name)) {
+        break;
+      }
+    }
+  }
+  bool in_cycle = (trail->RemoveLast() < 0);
+  if (FLAG_use_exp_cache &&
+      !in_cycle &&
+      !Compiler::IsBackgroundCompilation()) {
+    AddToExportedNamesCache(name, obj);
+  }
+  return obj.raw();
 }
 
 
@@ -9785,8 +9945,10 @@
 
 
 bool Library::RemoveObject(const Object& obj, const String& name) const {
-  ASSERT(!Compiler::IsBackgroundCompilation());
-  Object& entry = Object::Handle();
+  Thread* thread = Thread::Current();
+  ASSERT(thread->IsMutatorThread());
+  Zone* zone = thread->zone();
+  Object& entry = Object::Handle(zone);
 
   intptr_t index;
   entry = LookupEntry(name, &index);
@@ -9794,12 +9956,12 @@
     return false;
   }
 
-  const Array& dict = Array::Handle(dictionary());
+  const Array& dict = Array::Handle(zone, dictionary());
   dict.SetAt(index, Object::null_object());
   intptr_t dict_size = dict.Length() - 1;
 
   // Fix any downstream collisions.
-  String& key = String::Handle();
+  String& key = String::Handle(zone);
   for (;;) {
     index = (index + 1) % dict_size;
     entry = dict.At(index);
@@ -9822,9 +9984,10 @@
 
   // Update used count.
   intptr_t used_elements = Smi::Value(Smi::RawCast(dict.At(dict_size))) - 1;
-  dict.SetAt(dict_size, Smi::Handle(Smi::New(used_elements)));
+  dict.SetAt(dict_size, Smi::Handle(zone, Smi::New(used_elements)));
 
   InvalidateResolvedNamesCache();
+  InvalidateExportedNamesCaches();
 
   return true;
 }
@@ -9860,6 +10023,7 @@
 
 
 RawArray* Library::LoadedScripts() const {
+  ASSERT(Thread::Current()->IsMutatorThread());
   // We compute the list of loaded scripts lazily. The result is
   // cached in loaded_scripts_.
   if (loaded_scripts() == Array::null()) {
@@ -10190,7 +10354,6 @@
 void Library::DropDependencies() const {
   StorePointer(&raw_ptr()->imports_, Array::null());
   StorePointer(&raw_ptr()->exports_, Array::null());
-  StorePointer(&raw_ptr()->exports2_, Array::null());
 }
 
 
@@ -10223,7 +10386,6 @@
   intptr_t num_exports = exports.Length();
   exports = Array::Grow(exports, num_exports + 1);
   StorePointer(&raw_ptr()->exports_, exports.raw());
-  StorePointer(&raw_ptr()->exports2_, exports.raw());
   exports.SetAt(num_exports, ns);
 }
 
@@ -10238,6 +10400,7 @@
 
 void Library::InitResolvedNamesCache(intptr_t size,
                                      SnapshotReader* reader) const {
+  ASSERT(Thread::Current()->IsMutatorThread());
   if (reader == NULL) {
     StorePointer(&raw_ptr()->resolved_names_,
                  HashTables::New<ResolvedNamesMap>(size));
@@ -10250,6 +10413,20 @@
 }
 
 
+void Library::AllocateExportedNamesCache() const {
+  StorePointer(&raw_ptr()->exported_names_,
+               HashTables::New<ResolvedNamesMap>(16));
+}
+
+
+void Library::InitExportedNamesCache() const {
+  if (exported_names() != Array::null()) {
+    StorePointer(&raw_ptr()->exported_names_,
+                 HashTables::New<ResolvedNamesMap>(16));
+  }
+}
+
+
 void Library::InitClassDictionary() const {
   // TODO(iposva): Find reasonable initial size.
   const int kInitialElementCount = 16;
@@ -10276,11 +10453,16 @@
 
 RawLibrary* Library::NewLibraryHelper(const String& url,
                                       bool import_core_lib) {
-  const Library& result = Library::Handle(Library::New());
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  ASSERT(thread->IsMutatorThread());
+  const Library& result = Library::Handle(zone, Library::New());
   result.StorePointer(&result.raw_ptr()->name_, Symbols::Empty().raw());
   result.StorePointer(&result.raw_ptr()->url_, url.raw());
   result.StorePointer(&result.raw_ptr()->resolved_names_,
                       Object::empty_array().raw());
+  result.StorePointer(&result.raw_ptr()->exported_names_,
+                      Array::null());
   result.StorePointer(&result.raw_ptr()->dictionary_,
                       Object::empty_array().raw());
   result.StorePointer(&result.raw_ptr()->metadata_,
@@ -10291,8 +10473,6 @@
                                                Heap::kOld));
   result.StorePointer(&result.raw_ptr()->imports_, Object::empty_array().raw());
   result.StorePointer(&result.raw_ptr()->exports_, Object::empty_array().raw());
-  result.StorePointer(&result.raw_ptr()->exports2_,
-      Object::empty_array().raw());
   result.StorePointer(&result.raw_ptr()->loaded_scripts_, Array::null());
   result.StorePointer(&result.raw_ptr()->load_error_, Instance::null());
   result.set_native_entry_resolver(NULL);
@@ -10310,9 +10490,9 @@
   result.InitImportList();
   result.AllocatePrivateKey();
   if (import_core_lib) {
-    const Library& core_lib = Library::Handle(Library::CoreLibrary());
+    const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
     ASSERT(!core_lib.IsNull());
-    const Namespace& ns = Namespace::Handle(
+    const Namespace& ns = Namespace::Handle(zone,
         Namespace::New(core_lib, Object::null_array(), Object::null_array()));
     result.AddImport(ns);
   }
@@ -10930,10 +11110,10 @@
 void Namespace::AddMetadata(const Object& owner, TokenPosition token_pos) {
   ASSERT(Field::Handle(metadata_field()).IsNull());
   Field& field = Field::Handle(Field::NewTopLevel(Symbols::TopLevel(),
-                                          false,  // is_final
-                                          false,  // is_const
-                                          owner,
-                                          token_pos));
+                                                  false,  // is_final
+                                                  false,  // is_const
+                                                  owner,
+                                                  token_pos));
   field.set_is_reflectable(false);
   field.SetFieldType(Object::dynamic_type());
   field.SetStaticValue(Array::empty_array(), true);
@@ -11014,11 +11194,24 @@
 
 // Look up object with given name in library and filter out hidden
 // names. Also look up getters and setters.
-RawObject* Namespace::Lookup(const String& name) const {
+RawObject* Namespace::Lookup(const String& name,
+                             ZoneGrowableArray<intptr_t>* trail) const {
   Zone* zone = Thread::Current()->zone();
   const Library& lib = Library::Handle(zone, library());
-  intptr_t ignore = 0;
 
+  if (trail != NULL) {
+    // Look for cycle in reexport graph.
+    for (int i = 0; i < trail->length(); i++) {
+      if (trail->At(i) == lib.index()) {
+        for (int j = i+1; j < trail->length(); j++) {
+          (*trail)[j] = -1;
+        }
+        return Object::null();
+      }
+    }
+  }
+
+  intptr_t ignore = 0;
   // Lookup the name in the library's symbols.
   Object& obj = Object::Handle(zone, lib.LookupEntry(name, &ignore));
   if (!Field::IsGetterName(name) &&
@@ -11040,14 +11233,14 @@
   // Library prefixes are not exported.
   if (obj.IsNull() || obj.IsLibraryPrefix()) {
     // Lookup in the re-exported symbols.
-    obj = lib.LookupReExport(name);
+    obj = lib.LookupReExport(name, trail);
     if (obj.IsNull() && !Field::IsSetterName(name)) {
       // LookupReExport() only returns objects that match the given name.
       // If there is no field/func/getter, try finding a setter.
       const String& setter_name =
           String::Handle(zone, Field::LookupSetterSymbol(name));
       if (!setter_name.IsNull()) {
-        obj = lib.LookupReExport(setter_name);
+        obj = lib.LookupReExport(setter_name, trail);
       }
     }
   }
@@ -13743,8 +13936,9 @@
     Zone* zone = thread->zone();
     const char* name = StubCode::NameOfStub(EntryPoint());
     ASSERT(name != NULL);
-    const String& stub_name = String::Handle(zone, String::New(name));
-    return Symbols::FromConcat(thread, Symbols::StubPrefix(), stub_name);
+    char* stub_name = OS::SCreate(zone,
+        "%s%s", Symbols::StubPrefix().ToCString(), name);
+    return Symbols::New(thread, stub_name, strlen(stub_name));
   } else if (obj.IsClass()) {
     // Allocation stub.
     Thread* thread = Thread::Current();
@@ -13800,6 +13994,7 @@
 
 
 void Code::DisableStubCode() const {
+#if !defined(TARGET_ARCH_DBC)
   ASSERT(Thread::Current()->IsMutatorThread());
   ASSERT(IsAllocationStubCode());
   ASSERT(!IsDisabled());
@@ -13807,6 +14002,10 @@
       Code::Handle(StubCode::FixAllocationStubTarget_entry()->code());
   ASSERT(new_code.instructions()->IsVMHeapObject());
   SetActiveInstructions(new_code.instructions());
+#else
+  // DBC does not use allocation stubs.
+  UNIMPLEMENTED();
+#endif  // !defined(TARGET_ARCH_DBC)
 }
 
 
@@ -14749,8 +14948,13 @@
   {
     NoSafepointScope no_safepoint;
     // Raw bits compare.
-    const intptr_t instance_size = Class::Handle(this->clazz()).instance_size();
+    const intptr_t instance_size = SizeFromClass();
     ASSERT(instance_size != 0);
+    const intptr_t other_instance_size = other.SizeFromClass();
+    ASSERT(other_instance_size != 0);
+    if (instance_size != other_instance_size) {
+      return false;
+    }
     uword this_addr = reinterpret_cast<uword>(this->raw_ptr());
     uword other_addr = reinterpret_cast<uword>(other.raw_ptr());
     for (intptr_t offset = Instance::NextFieldOffset();
@@ -14766,6 +14970,24 @@
 }
 
 
+uword Instance::ComputeCanonicalTableHash() const {
+  ASSERT(!IsNull());
+  NoSafepointScope no_safepoint;
+  const intptr_t instance_size = SizeFromClass();
+  ASSERT(instance_size != 0);
+  uword hash = instance_size;
+  uword this_addr = reinterpret_cast<uword>(this->raw_ptr());
+  for (intptr_t offset = Instance::NextFieldOffset();
+       offset < instance_size;
+       offset += kWordSize) {
+    uword value = reinterpret_cast<uword>(
+        *reinterpret_cast<RawObject**>(this_addr + offset));
+    hash = CombineHashes(hash, value);
+  }
+  return FinalizeHash(hash);
+}
+
+
 #if defined(DEBUG)
 class CheckForPointers : public ObjectPointerVisitor {
  public:
@@ -14788,21 +15010,21 @@
 #endif  // DEBUG
 
 
-bool Instance::CheckAndCanonicalizeFields(Zone* zone,
+bool Instance::CheckAndCanonicalizeFields(Thread* thread,
                                           const char** error_str) const {
-  const Class& cls = Class::Handle(zone, this->clazz());
-  if (cls.id() >= kNumPredefinedCids) {
+  if (GetClassId() >= kNumPredefinedCids) {
     // Iterate over all fields, canonicalize numbers and strings, expect all
     // other instances to be canonical otherwise report error (return false).
+    Zone* zone = thread->zone();
     Object& obj = Object::Handle(zone);
-    intptr_t end_field_offset = cls.instance_size() - kWordSize;
+    intptr_t end_field_offset = SizeFromClass() - kWordSize;
     for (intptr_t field_offset = 0;
          field_offset <= end_field_offset;
          field_offset += kWordSize) {
       obj = *this->FieldAddrAtOffset(field_offset);
       if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) {
         if (obj.IsNumber() || obj.IsString()) {
-          obj = Instance::Cast(obj).CheckAndCanonicalize(NULL);
+          obj = Instance::Cast(obj).CheckAndCanonicalize(thread, NULL);
           ASSERT(!obj.IsNull());
           this->SetFieldAtOffset(field_offset, obj);
         } else {
@@ -14825,46 +15047,35 @@
 }
 
 
-RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const {
+RawInstance* Instance::CheckAndCanonicalize(Thread* thread,
+                                            const char** error_str) const {
   ASSERT(!IsNull());
   if (this->IsCanonical()) {
     return this->raw();
   }
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-  if (!CheckAndCanonicalizeFields(zone, error_str)) {
+  if (!CheckAndCanonicalizeFields(thread, error_str)) {
     return Instance::null();
   }
+  Zone* zone = thread->zone();
   Isolate* isolate = thread->isolate();
   Instance& result = Instance::Handle(zone);
   const Class& cls = Class::Handle(zone, this->clazz());
-  intptr_t index = 0;
-  result ^= cls.LookupCanonicalInstance(zone, *this, &index);
-  if (!result.IsNull()) {
-    return result.raw();
-  }
   {
     SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
-    // Retry lookup.
-    {
-      result ^= cls.LookupCanonicalInstance(zone, *this, &index);
+    if (IsNew()) {
+      result ^= cls.LookupCanonicalInstance(zone, *this);
       if (!result.IsNull()) {
         return result.raw();
       }
-    }
-
-    // The value needs to be added to the list. Grow the list if
-    // it is full.
-    result ^= this->raw();
-    ASSERT((isolate == Dart::vm_isolate()) || !result.InVMHeap());
-    if (result.IsNew()) {
+      ASSERT((isolate == Dart::vm_isolate()) || !InVMHeap());
       // Create a canonical object in old space.
-      result ^= Object::Clone(result, Heap::kOld);
+      result ^= Object::Clone(*this, Heap::kOld);
+    } else {
+      result ^= this->raw();
     }
     ASSERT(result.IsOld());
     result.SetCanonical();
-    cls.InsertCanonicalConstant(index, result);
-    return result.raw();
+    return cls.InsertCanonicalConstant(zone, result);
   }
 }
 
@@ -14945,7 +15156,9 @@
   Zone* zone = Thread::Current()->zone();
   const Class& cls = Class::Handle(zone, clazz());
   if (cls.IsClosureClass()) {
-    if (other.IsObjectType() || other.IsDartFunctionType()) {
+    if (other.IsObjectType() ||
+        other.IsDartFunctionType() ||
+        other.IsDartClosureType()) {
       return true;
     }
     Function& other_signature = Function::Handle(zone);
@@ -15302,6 +15515,13 @@
 
 bool AbstractType::IsInstantiated(TrailPtr trail) const {
   // AbstractType is an abstract class.
+  // TODO(srdjan) : Remove temporary code.
+NOT_IN_PRODUCT(
+  Profiler::DumpStackTrace(true);  // Only native stack trace.
+)
+  if (Compiler::IsBackgroundCompilation()) {
+    UNREACHABLE();
+  }
   UNREACHABLE();
   return false;
 }
@@ -15732,6 +15952,13 @@
 }
 
 
+bool AbstractType::IsDartClosureType() const {
+  return !IsFunctionType() &&
+      HasResolvedTypeClass() &&
+      (type_class() == Isolate::Current()->object_store()->closure_class());
+}
+
+
 bool AbstractType::TypeTest(TypeTestKind test_kind,
                             const AbstractType& other,
                             Error* bound_error,
@@ -16509,8 +16736,8 @@
     return Object::dynamic_type().raw();
   }
   // Fast canonical lookup/registry for simple types.
-  if (!cls.IsGeneric() && !cls.IsClosureClass()) {
-    ASSERT(!IsFunctionType() || cls.IsTypedefClass());
+  if (!cls.IsGeneric() && !cls.IsClosureClass() && !cls.IsTypedefClass()) {
+    ASSERT(!IsFunctionType());
     type = cls.CanonicalType();
     if (type.IsNull()) {
       ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate()));
@@ -17236,7 +17463,9 @@
 
 
 void BoundedType::set_type(const AbstractType& value) const {
-  ASSERT(value.IsFinalized() || value.IsBeingFinalized());
+  ASSERT(value.IsFinalized() ||
+         value.IsBeingFinalized() ||
+         value.IsTypeParameter());
   ASSERT(!value.IsMalformed());
   StorePointer(&raw_ptr()->type_, value.raw());
 }
@@ -17305,8 +17534,8 @@
         return bounded_type.raw();
       }
       const TypeParameter& type_param = TypeParameter::Handle(type_parameter());
-      if (instantiated_bounded_type.IsBeingFinalized() ||
-          instantiated_upper_bound.IsBeingFinalized() ||
+      if (!instantiated_bounded_type.IsFinalized() ||
+          !instantiated_upper_bound.IsFinalized() ||
           (!type_param.CheckBound(instantiated_bounded_type,
                                   instantiated_upper_bound,
                                   bound_error,
@@ -17315,7 +17544,8 @@
            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
-        // uninstantiated.
+        // uninstantiated. For example, instantiated_bounded_type may be the
+        // still unfinalized cloned type parameter of a mixin application class.
         ASSERT(instantiated_bounded_type.IsBeingFinalized() ||
                instantiated_upper_bound.IsBeingFinalized() ||
                !instantiated_bounded_type.IsInstantiated() ||
@@ -17483,7 +17713,8 @@
 }
 
 
-RawInstance* Number::CheckAndCanonicalize(const char** error_str) const {
+RawInstance* Number::CheckAndCanonicalize(Thread* thread,
+                                          const char** error_str) const {
   intptr_t cid = GetClassId();
   switch (cid) {
     case kSmiCid:
@@ -17493,10 +17724,9 @@
     case kDoubleCid:
       return Double::NewCanonical(Double::Cast(*this).value());
     case kBigintCid: {
-      Thread* thread = Thread::Current();
       Zone* zone = thread->zone();
       Isolate* isolate = thread->isolate();
-      if (!CheckAndCanonicalizeFields(zone, error_str)) {
+      if (!CheckAndCanonicalizeFields(thread, error_str)) {
         return Instance::null();
       }
       Bigint& result = Bigint::Handle(zone);
@@ -18249,15 +18479,16 @@
 }
 
 
-bool Bigint::CheckAndCanonicalizeFields(Zone* zone,
+bool Bigint::CheckAndCanonicalizeFields(Thread* thread,
                                         const char** error_str) const {
+  Zone* zone = thread->zone();
   // Bool field neg should always be canonical.
   ASSERT(Bool::Handle(zone, neg()).IsCanonical());
   // Smi field used is canonical by definition.
   if (Used() > 0) {
     // Canonicalize TypedData field digits.
     TypedData& digits_ = TypedData::Handle(zone, digits());
-    digits_ ^= digits_.CheckAndCanonicalize(NULL);
+    digits_ ^= digits_.CheckAndCanonicalize(thread, NULL);
     ASSERT(!digits_.IsNull());
     set_digits(digits_);
   } else {
@@ -19229,7 +19460,8 @@
 }
 
 
-RawInstance* String::CheckAndCanonicalize(const char** error_str) const {
+RawInstance* String::CheckAndCanonicalize(Thread* thread,
+                                          const char** error_str) const {
   if (IsCanonical()) {
     return this->raw();
   }
@@ -20686,6 +20918,9 @@
   }
 
   // Now check if both arrays have the same type arguments.
+  if (GetTypeArguments() == other.GetTypeArguments()) {
+    return true;
+  }
   const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
   const TypeArguments& other_type_args = TypeArguments::Handle(
       other.GetTypeArguments());
@@ -20696,6 +20931,20 @@
 }
 
 
+uword Array::ComputeCanonicalTableHash() const {
+  ASSERT(!IsNull());
+  intptr_t len = Length();
+  uword hash = len;
+  uword value = reinterpret_cast<uword>(GetTypeArguments());
+  hash = CombineHashes(hash, value);
+  for (intptr_t i = 0; i < len; i++) {
+    value = reinterpret_cast<uword>(At(i));
+    hash = CombineHashes(hash, value);
+  }
+  return FinalizeHash(hash);
+}
+
+
 RawArray* Array::New(intptr_t len, Heap::Space space) {
   ASSERT(Isolate::Current()->object_store()->array_class() != Class::null());
   return New(kClassId, len, space);
@@ -20837,24 +21086,28 @@
 }
 
 
-bool Array::CheckAndCanonicalizeFields(Zone* zone,
+bool Array::CheckAndCanonicalizeFields(Thread* thread,
                                        const char** error_str) const {
-  Object& obj = Object::Handle(zone);
-  // Iterate over all elements, canonicalize numbers and strings, expect all
-  // other instances to be canonical otherwise report error (return false).
-  for (intptr_t i = 0; i < Length(); i++) {
-    obj = At(i);
-    if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) {
-      if (obj.IsNumber() || obj.IsString()) {
-        obj = Instance::Cast(obj).CheckAndCanonicalize(NULL);
-        ASSERT(!obj.IsNull());
-        this->SetAt(i, obj);
-      } else {
-        ASSERT(error_str != NULL);
-        char* chars = OS::SCreate(Thread::Current()->zone(),
-            "element at index %" Pd ": %s\n", i, obj.ToCString());
-        *error_str = chars;
-        return false;
+  intptr_t len = Length();
+  if (len > 0) {
+    Zone* zone = thread->zone();
+    Object& obj = Object::Handle(zone);
+    // Iterate over all elements, canonicalize numbers and strings, expect all
+    // other instances to be canonical otherwise report error (return false).
+    for (intptr_t i = 0; i < len; i++) {
+      obj = At(i);
+      if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) {
+        if (obj.IsNumber() || obj.IsString()) {
+          obj = Instance::Cast(obj).CheckAndCanonicalize(thread, NULL);
+          ASSERT(!obj.IsNull());
+          this->SetAt(i, obj);
+        } else {
+          ASSERT(error_str != NULL);
+          char* chars = OS::SCreate(
+              zone, "element at index %" Pd ": %s\n", i, obj.ToCString());
+          *error_str = chars;
+          return false;
+        }
       }
     }
   }
@@ -20946,6 +21199,9 @@
 // Equivalent to Dart's operator "==" and hashCode.
 class DefaultHashTraits {
  public:
+  static const char* Name() { return "DefaultHashTraits"; }
+  static bool ReportStats() { return false; }
+
   static bool IsMatch(const Object& a, const Object& b) {
     if (a.IsNull() || b.IsNull()) {
       return (a.IsNull() && b.IsNull());
@@ -21335,6 +21591,17 @@
 }
 
 
+uword TypedData::ComputeCanonicalTableHash() const {
+  const intptr_t len = this->LengthInBytes();
+  ASSERT(len != 0);
+  uword hash = len;
+  for (intptr_t i = 0; i < len; i++) {
+    hash = CombineHashes(len, GetUint8(i));
+  }
+  return FinalizeHash(hash);
+}
+
+
 RawTypedData* TypedData::New(intptr_t class_id,
                              intptr_t len,
                              Heap::Space space) {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 6a2008f..53a22fc 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1213,10 +1213,10 @@
                                    const Bigint& value, intptr_t* index) const;
   // The methods above are more efficient than this generic one.
   RawInstance* LookupCanonicalInstance(Zone* zone,
-                                       const Instance& value,
-                                       intptr_t* index) const;
+                                       const Instance& value) const;
 
-  void InsertCanonicalConstant(intptr_t index, const Instance& constant) const;
+  RawInstance* InsertCanonicalConstant(Zone* zone,
+                                       const Instance& constant) const;
   void InsertCanonicalNumber(Zone* zone,
                              intptr_t index,
                              const Number& constant) const;
@@ -1224,6 +1224,8 @@
   intptr_t FindCanonicalTypeIndex(const AbstractType& needle) const;
   RawAbstractType* CanonicalTypeFromIndex(intptr_t idx) const;
 
+  void RehashConstants(Zone* zone) const;
+
   static intptr_t InstanceSize() {
     return RoundedAllocationSize(sizeof(RawClass));
   }
@@ -3529,7 +3531,8 @@
   void AddObject(const Object& obj, const String& name) const;
   void ReplaceObject(const Object& obj, const String& name) const;
   bool RemoveObject(const Object& obj, const String& name) const;
-  RawObject* LookupReExport(const String& name) const;
+  RawObject* LookupReExport(const String& name,
+                            ZoneGrowableArray<intptr_t>* visited = NULL) const;
   RawObject* LookupObjectAllowPrivate(const String& name) const;
   RawObject* LookupLocalObjectAllowPrivate(const String& name) const;
   RawObject* LookupLocalObject(const String& name) const;
@@ -3582,7 +3585,6 @@
   // Library imports.
   RawArray* imports() const { return raw_ptr()->imports_; }
   RawArray* exports() const { return raw_ptr()->exports_; }
-  RawArray* exports2() const { return raw_ptr()->exports2_; }
   void AddImport(const Namespace& ns) const;
   intptr_t num_imports() const { return raw_ptr()->num_imports_; }
   RawNamespace* ImportAt(intptr_t index) const;
@@ -3708,12 +3710,19 @@
   RawArray* resolved_names() const { return raw_ptr()->resolved_names_; }
   void InitResolvedNamesCache(intptr_t size,
                               SnapshotReader* reader = NULL) const;
-  void GrowResolvedNamesCache() const;
+  void AllocateExportedNamesCache() const;
+  void InitExportedNamesCache() const;
+  static void InvalidateExportedNamesCaches();
   bool LookupResolvedNamesCache(const String& name, Object* obj) const;
   void AddToResolvedNamesCache(const String& name, const Object& obj) const;
   void InvalidateResolvedName(const String& name) const;
   void InvalidateResolvedNamesCache() const;
 
+  RawArray* exported_names() const { return raw_ptr()->exported_names_; }
+  bool LookupExportedNamesCache(const String& name, Object* obj) const;
+  void AddToExportedNamesCache(const String& name, const Object& obj) const;
+
+
   void InitImportList() const;
   void GrowDictionary(const Array& dict, intptr_t dict_size) const;
   static RawLibrary* NewLibraryHelper(const String& url,
@@ -3734,6 +3743,7 @@
   friend class Bootstrap;
   friend class Class;
   friend class Debugger;
+  friend class Isolate;
   friend class DictionaryIterator;
   friend class Namespace;
   friend class Object;
@@ -3756,7 +3766,8 @@
   }
 
   bool HidesName(const String& name) const;
-  RawObject* Lookup(const String& name) const;
+  RawObject* Lookup(const String& name,
+                    ZoneGrowableArray<intptr_t>* trail = NULL) const;
 
   static RawNamespace* New(const Library& library,
                            const Array& show_names,
@@ -5153,16 +5164,26 @@
   virtual bool OperatorEquals(const Instance& other) const;
   bool IsIdenticalTo(const Instance& other) const;
   virtual bool CanonicalizeEquals(const Instance& other) const;
+  virtual uword ComputeCanonicalTableHash() const;
+
+  intptr_t SizeFromClass() const {
+#if defined(DEBUG)
+    const Class& cls = Class::Handle(clazz());
+    ASSERT(cls.is_finalized() || cls.is_prefinalized());
+#endif
+    return (clazz()->ptr()->instance_size_in_words_ * kWordSize);
+  }
 
   // Returns Instance::null() if instance cannot be canonicalized.
   // Any non-canonical number of string will be canonicalized here.
   // An instance cannot be canonicalized if it still contains non-canonical
   // instances in its fields.
   // Returns error in error_str, pass NULL if an error cannot occur.
-  virtual RawInstance* CheckAndCanonicalize(const char** error_str) const;
+  virtual RawInstance* CheckAndCanonicalize(Thread* thread,
+                                            const char** error_str) const;
 
   // Returns true if all fields are OK for canonicalization.
-  virtual bool CheckAndCanonicalizeFields(Zone* zone,
+  virtual bool CheckAndCanonicalizeFields(Thread* thread,
                                           const char** error_str) const;
 
   RawObject* GetField(const Field& field) const {
@@ -5382,7 +5403,8 @@
   virtual RawAbstractType* CloneUninstantiated(
       const Class& new_owner, TrailPtr trail = NULL) const;
 
-  virtual RawInstance* CheckAndCanonicalize(const char** error_str) const {
+  virtual RawInstance* CheckAndCanonicalize(Thread* thread,
+                                            const char** error_str) const {
     return Canonicalize();
   }
 
@@ -5485,6 +5507,9 @@
   // Check if this type represents the Dart 'Function' type.
   bool IsDartFunctionType() const;
 
+  // Check if this type represents the Dart '_Closure' type.
+  bool IsDartClosureType() const;
+
   // Check the subtype relationship.
   bool IsSubtypeOf(const AbstractType& other,
                    Error* bound_error,
@@ -5951,7 +5976,8 @@
   RawString* ToString(Heap::Space space) const;
 
   // Numbers are canonicalized differently from other instances/strings.
-  virtual RawInstance* CheckAndCanonicalize(const char** error_str) const;
+  virtual RawInstance* CheckAndCanonicalize(Thread* thread,
+                                            const char** error_str) const;
 
  private:
   OBJECT_IMPLEMENTATION(Number, Instance);
@@ -5977,6 +6003,10 @@
   virtual bool CanonicalizeEquals(const Instance& other) const {
     return Equals(other);
   }
+  virtual uword ComputeCanonicalTableHash() const {
+    UNREACHABLE();
+    return 0;
+  }
   virtual bool Equals(const Instance& other) const;
 
   virtual RawObject* HashCode() const { return raw(); }
@@ -6162,7 +6192,7 @@
 
   virtual int CompareWith(const Integer& other) const;
 
-  virtual bool CheckAndCanonicalizeFields(Zone* zone,
+  virtual bool CheckAndCanonicalizeFields(Thread* thread,
                                           const char** error_str) const;
 
   virtual bool FitsIntoSmi() const;
@@ -6254,6 +6284,10 @@
   bool BitwiseEqualsToDouble(double value) const;
   virtual bool OperatorEquals(const Instance& other) const;
   virtual bool CanonicalizeEquals(const Instance& other) const;
+  virtual uword ComputeCanonicalTableHash() const {
+    UNREACHABLE();
+    return 0;
+  }
 
   static RawDouble* New(double d, Heap::Space space = Heap::kNew);
 
@@ -6404,6 +6438,10 @@
   virtual bool CanonicalizeEquals(const Instance& other) const {
     return Equals(other);
   }
+  virtual uword ComputeCanonicalTableHash() const {
+    UNREACHABLE();
+    return 0;
+  }
   virtual bool Equals(const Instance& other) const;
 
   intptr_t CompareTo(const String& other) const;
@@ -6411,7 +6449,8 @@
   bool StartsWith(const String& other) const;
 
   // Strings are canonicalized using the symbol table.
-  virtual RawInstance* CheckAndCanonicalize(const char** error_str) const;
+  virtual RawInstance* CheckAndCanonicalize(Thread* thread,
+                                            const char** error_str) const;
 
   bool IsSymbol() const { return raw()->IsCanonical(); }
 
@@ -7093,6 +7132,7 @@
   }
 
   virtual bool CanonicalizeEquals(const Instance& other) const;
+  virtual uword ComputeCanonicalTableHash() const;
 
   static const intptr_t kBytesPerElement = kWordSize;
   static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
@@ -7114,7 +7154,7 @@
   }
 
   // Returns true if all elements are OK for canonicalization.
-  virtual bool CheckAndCanonicalizeFields(Zone* zone,
+  virtual bool CheckAndCanonicalizeFields(Thread* thread,
                                           const char** error_str) const;
 
   // Make the array immutable to Dart code by switching the class pointer
@@ -7266,9 +7306,14 @@
     UNREACHABLE();
     return false;
   }
+  virtual uword ComputeCanonicalTableHash() const {
+    UNREACHABLE();
+    return 0;
+  }
 
   // We don't expect a growable object array to be canonicalized.
-  virtual RawInstance* CheckAndCanonicalize(const char** error_str) const {
+  virtual RawInstance* CheckAndCanonicalize(Thread* thread,
+                                            const char** error_str) const {
     UNREACHABLE();
     return Instance::null();
   }
@@ -7442,6 +7487,7 @@
   }
 
   virtual bool CanonicalizeEquals(const Instance& other) const;
+  virtual uword ComputeCanonicalTableHash() const;
 
 #define TYPED_GETTER_SETTER(name, type)                                        \
   type Get##name(intptr_t byte_offset) const {                                 \
@@ -7957,7 +8003,7 @@
   }
 
   // Returns true if all elements are OK for canonicalization.
-  virtual bool CheckAndCanonicalizeFields(Zone* zone,
+  virtual bool CheckAndCanonicalizeFields(Thread* thread,
                                           const char** error_str) const {
     // None of the fields of a closure are instances.
     return true;
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 90f9e1d..3cfc25b 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -1034,27 +1034,34 @@
     return;
   }
 
-  // Walk the superclass chain, adding all instance fields.
+  // Add all fields in layout order, from superclass to subclass.
+  GrowableArray<Class*> classes;
   Class& cls = Class::Handle(this->clazz());
+  do {
+    cls.Print();
+    classes.Add(&Class::Handle(cls.raw()));
+    cls = cls.SuperClass();
+  } while (!cls.IsNull());
+
+  Array& field_array = Array::Handle();
+  Field& field = Field::Handle();
+  Instance& field_value = Instance::Handle();
   {
-    Instance& fieldValue = Instance::Handle();
     JSONArray jsarr(jsobj, "fields");
-    while (!cls.IsNull()) {
-      const Array& field_array = Array::Handle(cls.fields());
-      Field& field = Field::Handle();
+    for (intptr_t i = classes.length() - 1; i >= 0; i--) {
+      field_array = classes[i]->fields();
       if (!field_array.IsNull()) {
-        for (intptr_t i = 0; i < field_array.Length(); i++) {
-          field ^= field_array.At(i);
+        for (intptr_t j = 0; j < field_array.Length(); j++) {
+          field ^= field_array.At(j);
           if (!field.is_static()) {
-            fieldValue ^= GetField(field);
+            field_value ^= GetField(field);
             JSONObject jsfield(&jsarr);
             jsfield.AddProperty("type", "BoundField");
             jsfield.AddProperty("decl", field);
-            jsfield.AddProperty("value", fieldValue);
+            jsfield.AddProperty("value", field_value);
           }
         }
       }
-      cls = cls.SuperClass();
     }
   }
 
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 62718be..aa75ee9 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -21,10 +21,6 @@
 
 DECLARE_FLAG(bool, write_protect_code);
 
-static RawLibrary* CreateDummyLibrary(const String& library_name) {
-  return Library::New(library_name);
-}
-
 
 static RawClass* CreateDummyClass(const String& class_name,
                                   const Script& script) {
@@ -2690,6 +2686,12 @@
 }
 
 
+#if !defined(TARGET_ARCH_DBC)
+static RawLibrary* CreateDummyLibrary(const String& library_name) {
+  return Library::New(library_name);
+}
+
+
 static RawFunction* CreateFunction(const char* name) {
   Thread* thread = Thread::Current();
   const String& class_name = String::Handle(Symbols::New(thread, "ownerClass"));
@@ -2966,6 +2968,7 @@
 
   EXPECT_EQ(false, iter.MoveNext());
 }
+#endif  // !defined(TARGET_ARCH_DBC)
 
 
 static RawClass* CreateTestClass(const char* name) {
diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc
index 03540bb..3269b12 100644
--- a/runtime/vm/os_android.cc
+++ b/runtime/vm/os_android.cc
@@ -191,7 +191,7 @@
 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) || \
     defined(TARGET_ARCH_ARM64)
   const int kMinimumAlignment = 16;
-#elif defined(TARGET_ARCH_ARM)
+#elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_DBC)
   const int kMinimumAlignment = 8;
 #else
 #error Unsupported architecture.
@@ -212,6 +212,8 @@
   const int kMinimumAlignment = 16;
 #elif defined(TARGET_ARCH_ARM)
   const int kMinimumAlignment = 16;
+#elif defined(TARGET_ARCH_DBC)
+  const int kMinimumAlignment = 16;
 #else
 #error Unsupported architecture.
 #endif
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index edfb890..0fc90c7 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -197,7 +197,8 @@
 intptr_t OS::ActivationFrameAlignment() {
 #if defined(TARGET_ARCH_IA32) ||                                               \
     defined(TARGET_ARCH_X64) ||                                                \
-    defined(TARGET_ARCH_ARM64)
+    defined(TARGET_ARCH_ARM64) ||                                              \
+    defined(TARGET_ARCH_DBC)
   const int kMinimumAlignment = 16;
 #elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_MIPS)
   const int kMinimumAlignment = 8;
@@ -217,7 +218,8 @@
 intptr_t OS::PreferredCodeAlignment() {
 #if defined(TARGET_ARCH_IA32) ||                                               \
     defined(TARGET_ARCH_X64) ||                                                \
-    defined(TARGET_ARCH_ARM64)
+    defined(TARGET_ARCH_ARM64) ||                                              \
+    defined(TARGET_ARCH_DBC)
   const int kMinimumAlignment = 32;
 #elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_MIPS)
   const int kMinimumAlignment = 16;
diff --git a/runtime/vm/os_macos.cc b/runtime/vm/os_macos.cc
index 3393cb0..d2d5576 100644
--- a/runtime/vm/os_macos.cc
+++ b/runtime/vm/os_macos.cc
@@ -169,6 +169,8 @@
   return 16;  // iOS simulator
 #elif TARGET_ARCH_X64
   return 16;  // iOS simulator
+#elif TARGET_ARCH_DBC
+  return 16;
 #else
 #error Unimplemented
 #endif
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 87146f6..14446d9 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -5062,18 +5062,22 @@
       &Symbols::ClosureParameter(),
       &Object::dynamic_type());
 
-  const bool no_explicit_default_values = false;
-  ParseFormalParameterList(no_explicit_default_values, false, &func_params);
-  ExpectSemicolon();
+  // Mark the current class as a typedef class (by setting its signature
+  // function field to a non-null function) before parsing its formal parameters
+  // so that parsed function types are aware that their owner class is a
+  // typedef class.
   Function& signature_function =
       Function::Handle(Z, Function::NewSignatureFunction(function_type_alias,
                                                          alias_name_pos));
-  signature_function.set_result_type(result_type);
-  AddFormalParamsToFunction(&func_params, signature_function);
-
   // Set the signature function in the function type alias class.
   function_type_alias.set_signature_function(signature_function);
 
+  const bool no_explicit_default_values = false;
+  ParseFormalParameterList(no_explicit_default_values, false, &func_params);
+  ExpectSemicolon();
+  signature_function.set_result_type(result_type);
+  AddFormalParamsToFunction(&func_params, signature_function);
+
   if (FLAG_trace_parser) {
     OS::Print("TopLevel parsing function type alias '%s'\n",
               String::Handle(Z, signature_function.Signature()).ToCString());
@@ -10520,7 +10524,6 @@
 }
 
 
-// TODO(srdjan): Implement other optimizations.
 AstNode* Parser::OptimizeBinaryOpNode(TokenPosition op_pos,
                                       Token::Kind binary_op,
                                       AstNode* lhs,
@@ -10547,20 +10550,6 @@
       rhs_literal = lhs_literal;
       lhs_literal = temp;
     }
-    if ((rhs_literal != NULL) &&
-        (rhs_literal->literal().IsSmi() || rhs_literal->literal().IsMint())) {
-      const int64_t val = Integer::Cast(rhs_literal->literal()).AsInt64Value();
-      if ((0 <= val) && (Utils::IsUint(32, val))) {
-        if (lhs->IsBinaryOpNode() &&
-            (lhs->AsBinaryOpNode()->kind() == Token::kSHL)) {
-          // Merge SHL and BIT_AND into one "SHL with mask" node.
-          BinaryOpNode* old = lhs->AsBinaryOpNode();
-          BinaryOpWithMask32Node* binop = new(Z) BinaryOpWithMask32Node(
-              old->token_pos(), old->kind(), old->left(), old->right(), val);
-          return binop;
-        }
-      }
-    }
   }
   if (binary_op == Token::kIFNULL) {
     // Handle a ?? b.
@@ -11980,6 +11969,7 @@
 class ConstMapKeyEqualsTraits {
  public:
   static const char* Name() { return "ConstMapKeyEqualsTraits"; }
+  static bool ReportStats() { return false; }
 
   static bool IsMatch(const Object& a, const Object& b) {
     const Array& key1 = Array::Cast(a);
@@ -12063,7 +12053,7 @@
   }
   const char* error_str = NULL;
   Instance& result =
-      Instance::Handle(Z, instance.CheckAndCanonicalize(&error_str));
+      Instance::Handle(Z, instance.CheckAndCanonicalize(thread(), &error_str));
   if (result.IsNull()) {
     ReportError(token_pos, "Invalid const object %s", error_str);
   }
@@ -12748,6 +12738,9 @@
 
   if (is_const) {
     // Allocate and initialize the const list at compile time.
+    if ((element_list.length() == 0) && list_type_arguments.IsNull()) {
+      return new(Z) LiteralNode(literal_pos, Object::empty_array());
+    }
     Array& const_list = Array::ZoneHandle(Z,
         Array::New(element_list.length(), Heap::kOld));
     const_list.SetTypeArguments(
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index fc83b31..0bb6669 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -146,6 +146,7 @@
     sent_selectors_(),
     enqueued_functions_(),
     fields_to_retain_(),
+    functions_to_retain_(),
     classes_to_retain_(),
     typeargs_to_retain_(),
     types_to_retain_(),
@@ -199,6 +200,7 @@
 
     I->set_compilation_allowed(false);
 
+    TraceForRetainedFunctions();
     DropFunctions();
     DropFields();
     TraceTypesFromRetainedClasses();
@@ -583,6 +585,10 @@
 
 
 void Precompiler::AddTypesOf(const Function& function) {
+  if (function.IsNull()) return;
+  if (functions_to_retain_.Lookup(&function) != NULL) return;
+  functions_to_retain_.Insert(&Function::ZoneHandle(Z, function.raw()));
+
   AbstractType& type = AbstractType::Handle(Z);
   type = function.result_type();
   AddType(type);
@@ -1058,6 +1064,7 @@
 class NameFunctionsTraits {
  public:
   static const char* Name() { return "NameFunctionsTraits"; }
+  static bool ReportStats() { return false; }
 
   static bool IsMatch(const Object& a, const Object& b) {
     return a.IsString() && b.IsString() &&
@@ -1209,12 +1216,71 @@
 }
 
 
-void Precompiler::DropFunctions() {
+void Precompiler::TraceForRetainedFunctions() {
   Library& lib = Library::Handle(Z);
   Class& cls = Class::Handle(Z);
   Array& functions = Array::Handle(Z);
   Function& function = Function::Handle(Z);
   Function& function2 = Function::Handle(Z);
+  GrowableObjectArray& closures = GrowableObjectArray::Handle(Z);
+
+  for (intptr_t i = 0; i < libraries_.Length(); i++) {
+    lib ^= libraries_.At(i);
+    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+    while (it.HasNext()) {
+      cls = it.GetNextClass();
+      if (cls.IsDynamicClass()) {
+        continue;  // class 'dynamic' is in the read-only VM isolate.
+      }
+
+      functions = cls.functions();
+      for (intptr_t j = 0; j < functions.Length(); j++) {
+        function ^= functions.At(j);
+        bool retain = function.HasCode();
+        if (!retain && function.HasImplicitClosureFunction()) {
+          // It can happen that all uses of an implicit closure inline their
+          // target function, leaving the target function uncompiled. Keep
+          // the target function anyway so we can enumerate it to bind its
+          // static calls, etc.
+          function2 = function.ImplicitClosureFunction();
+          retain = function2.HasCode();
+        }
+        if (retain) {
+          function.DropUncompiledImplicitClosureFunction();
+          AddTypesOf(function);
+        }
+      }
+    }
+  }
+
+  closures = isolate()->object_store()->closure_functions();
+  for (intptr_t j = 0; j < closures.Length(); j++) {
+    function ^= closures.At(j);
+    bool retain = function.HasCode();
+    if (retain) {
+      AddTypesOf(function);
+
+      cls = function.Owner();
+      AddTypesOf(cls);
+
+      // It can happen that all uses of a function are inlined, leaving
+      // a compiled local function with an uncompiled parent. Retain such
+      // parents and their enclosing classes and libraries.
+      function = function.parent_function();
+      while (!function.IsNull()) {
+        AddTypesOf(function);
+        function = function.parent_function();
+      }
+    }
+  }
+}
+
+
+void Precompiler::DropFunctions() {
+  Library& lib = Library::Handle(Z);
+  Class& cls = Class::Handle(Z);
+  Array& functions = Array::Handle(Z);
+  Function& function = Function::Handle(Z);
   GrowableObjectArray& retained_functions = GrowableObjectArray::Handle(Z);
   GrowableObjectArray& closures = GrowableObjectArray::Handle(Z);
   String& name = String::Handle(Z);
@@ -1232,19 +1298,10 @@
       retained_functions = GrowableObjectArray::New();
       for (intptr_t j = 0; j < functions.Length(); j++) {
         function ^= functions.At(j);
-        bool retain = function.HasCode();
-        if (!retain && function.HasImplicitClosureFunction()) {
-          // It can happen that all uses of an implicit closure inline their
-          // target function, leaving the target function uncompiled. Keep
-          // the target function anyway so we can enumerate it to bind its
-          // static calls, etc.
-          function2 = function.ImplicitClosureFunction();
-          retain = function2.HasCode();
-        }
+        bool retain = functions_to_retain_.Lookup(&function) != NULL;
+        function.DropUncompiledImplicitClosureFunction();
         if (retain) {
           retained_functions.Add(function);
-          function.DropUncompiledImplicitClosureFunction();
-          AddTypesOf(function);
         } else {
           bool top_level = cls.IsTopLevel();
           if (top_level &&
@@ -1276,10 +1333,9 @@
   retained_functions = GrowableObjectArray::New();
   for (intptr_t j = 0; j < closures.Length(); j++) {
     function ^= closures.At(j);
-    bool retain = function.HasCode();
+    bool retain = functions_to_retain_.Lookup(&function) != NULL;
     if (retain) {
       retained_functions.Add(function);
-      AddTypesOf(function);
     } else {
       dropped_function_count_++;
       if (FLAG_trace_precompiler) {
@@ -1482,15 +1538,21 @@
           retained_constants.Add(constant);
         }
       }
-      if (retained_constants.Length() > 0) {
+      intptr_t cid = cls.id();
+      if ((cid == kMintCid) || (cid == kBigintCid) || (cid == kDoubleCid)) {
+        // Constants stored as a plain list, no rehashing needed.
         constants = Array::MakeArray(retained_constants);
         cls.set_constants(constants);
       } else {
-        constants = Object::empty_array().raw();
+        // Rehash.
         cls.set_constants(Object::empty_array());
+        for (intptr_t j = 0; j < retained_constants.Length(); j++) {
+          constant ^= retained_constants.At(j);
+          cls.InsertCanonicalConstant(Z, constant);
+        }
       }
 
-      if (constants.Length() > 0) {
+      if (retained_constants.Length() > 0) {
         ASSERT(retain);  // This shouldn't be the reason we keep a class.
         retain = true;
       }
@@ -1576,6 +1638,7 @@
 void Precompiler::DropLibraries() {
   const GrowableObjectArray& retained_libraries =
       GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
+  Library& root_lib = Library::Handle(Z, I->object_store()->root_library());
   Library& lib = Library::Handle(Z);
 
   for (intptr_t i = 0; i < libraries_.Length(); i++) {
@@ -1587,7 +1650,12 @@
       it.GetNext();
       entries++;
     }
-    bool retain = (entries > 0) || lib.is_dart_scheme();
+    // The root library might have no surviving members if it only exports main
+    // from another library. It will still be referenced from the object store,
+    // so retain it.
+    bool retain = (entries > 0) ||
+                  lib.is_dart_scheme() ||
+                  (lib.raw() == root_lib.raw());
     if (retain) {
       lib.set_index(retained_libraries.Length());
       retained_libraries.Add(lib);
@@ -1618,7 +1686,6 @@
 
     void VisitFunction(const Function& function) {
       if (!function.HasCode()) {
-        ASSERT(function.HasImplicitClosureFunction());
         return;
       }
       code_ = function.CurrentCode();
@@ -1666,6 +1733,7 @@
 
 
 void Precompiler::SwitchICCalls() {
+#if !defined(TARGET_ARCH_DBC)
   // Now that all functions have been compiled, we can switch to an instance
   // call sequence that loads the Code object and entry point directly from
   // the ic data array instead indirectly through a Function in the ic data
@@ -1687,7 +1755,6 @@
 
     void VisitFunction(const Function& function) {
       if (!function.HasCode()) {
-        ASSERT(function.HasImplicitClosureFunction());
         return;
       }
 
@@ -1740,6 +1807,7 @@
   ASSERT(!I->compilation_allowed());
   SwitchICCallsVisitor visitor(Z);
   VisitFunctions(&visitor);
+#endif
 }
 
 
@@ -1756,7 +1824,6 @@
 
     void VisitFunction(const Function& function) {
       if (!function.HasCode()) {
-        ASSERT(function.HasImplicitClosureFunction());
         return;
       }
       code_ = function.CurrentCode();
@@ -1807,7 +1874,6 @@
 
     void VisitFunction(const Function& function) {
       if (!function.HasCode()) {
-        ASSERT(function.HasImplicitClosureFunction());
         return;
       }
       code_ = function.CurrentCode();
diff --git a/runtime/vm/precompiler.h b/runtime/vm/precompiler.h
index 5799819..5b6c7ac 100644
--- a/runtime/vm/precompiler.h
+++ b/runtime/vm/precompiler.h
@@ -309,6 +309,7 @@
   void CheckForNewDynamicFunctions();
   void TraceConstFunctions();
 
+  void TraceForRetainedFunctions();
   void DropFunctions();
   void DropFields();
   void TraceTypesFromRetainedClasses();
@@ -362,6 +363,7 @@
   SymbolSet sent_selectors_;
   FunctionSet enqueued_functions_;
   FieldSet fields_to_retain_;
+  FunctionSet functions_to_retain_;
   ClassSet classes_to_retain_;
   TypeArgumentsSet typeargs_to_retain_;
   AbstractTypeSet types_to_retain_;
@@ -373,6 +375,7 @@
 class FunctionsTraits {
  public:
   static const char* Name() { return "FunctionsTraits"; }
+  static bool ReportStats() { return false; }
 
   static bool IsMatch(const Object& a, const Object& b) {
     Zone* zone = Thread::Current()->zone();
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index e597260..394d795 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -290,6 +290,11 @@
   ASSERT(return_address != NULL);
   return false;
 }
+#elif defined(TARGET_ARCH_DBC)
+bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) {
+  ASSERT(return_address != NULL);
+  return false;
+}
 #else
 #error ReturnAddressLocator implementation missing for this architecture.
 #endif
@@ -323,6 +328,33 @@
 }
 
 
+static void DumpStackFrame(intptr_t frame_index, uword pc) {
+  uintptr_t start = 0;
+  char* native_symbol_name =
+      NativeSymbolResolver::LookupSymbolName(pc, &start);
+  if (native_symbol_name == NULL) {
+    OS::Print("Frame[%" Pd "] = `unknown symbol` [0x%" Px "]\n",
+              frame_index, pc);
+  } else {
+    OS::Print("Frame[%" Pd "] = `%s` [0x%" Px "]\n",
+              frame_index, native_symbol_name, pc);
+    free(native_symbol_name);
+  }
+}
+
+
+static void DumpStackFrame(intptr_t frame_index,
+                           uword pc,
+                           const Code& code) {
+  if (code.IsNull()) {
+    DumpStackFrame(frame_index, pc);
+  } else {
+    OS::Print("Frame[%" Pd "] = Dart:`%s` [0x%" Px "]\n",
+              frame_index, code.ToCString(), pc);
+  }
+}
+
+
 class ProfilerStackWalker : public ValueObject {
  public:
   ProfilerStackWalker(Isolate* isolate,
@@ -334,12 +366,31 @@
       frame_index_(0),
       total_frames_(0) {
     ASSERT(isolate_ != NULL);
-    ASSERT(sample_ != NULL);
-    ASSERT(sample_buffer_ != NULL);
-    ASSERT(sample_->head_sample());
+    if (sample_ == NULL) {
+      ASSERT(sample_buffer_ == NULL);
+    } else {
+      ASSERT(sample_buffer_ != NULL);
+      ASSERT(sample_->head_sample());
+    }
+  }
+
+  bool Append(uword pc, const Code& code) {
+    if (sample_ == NULL) {
+      DumpStackFrame(frame_index_, pc, code);
+      frame_index_++;
+      total_frames_++;
+      return true;
+    }
+    return Append(pc);
   }
 
   bool Append(uword pc) {
+    if (sample_ == NULL) {
+      DumpStackFrame(frame_index_, pc);
+      frame_index_++;
+      total_frames_++;
+      return true;
+    }
     if (total_frames_ >= FLAG_max_profile_depth) {
       sample_->set_truncated_trace(true);
       return false;
@@ -387,11 +438,23 @@
     sample_->set_exit_frame_sample(true);
 
     StackFrame* frame = frame_iterator_.NextFrame();
-    while (frame != NULL) {
-      if (!Append(frame->pc())) {
-        return;
+    if (sample_ == NULL) {
+      // Only when we are dumping the stack trace for debug purposes.
+      Code& code = Code::Handle();
+      while (frame != NULL) {
+        code ^= frame->LookupDartCode();
+        if (!Append(frame->pc(), code)) {
+          return;
+        }
+        frame = frame_iterator_.NextFrame();
       }
-      frame = frame_iterator_.NextFrame();
+    } else {
+      while (frame != NULL) {
+        if (!Append(frame->pc())) {
+          return;
+        }
+        frame = frame_iterator_.NextFrame();
+      }
     }
   }
 
@@ -576,7 +639,6 @@
 
   void walk() {
     const uword kMaxStep = VirtualMemory::PageSize();
-
     Append(original_pc_);
 
     uword* pc = reinterpret_cast<uword*>(original_pc_);
@@ -839,7 +901,7 @@
   Sample* sample = sample_buffer->ReserveSample();
   sample->Init(isolate, OS::GetCurrentMonotonicMicros(), tid);
   uword vm_tag = thread->vm_tag();
-#if defined(USING_SIMULATOR)
+#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
   // When running in the simulator, the runtime entry function address
   // (stored as the vm tag) is the address of a redirect function.
   // Attempt to find the real runtime entry function address and use that.
@@ -876,6 +938,78 @@
 }
 #endif
 
+
+void Profiler::DumpStackTrace(bool native_stack_trace) {
+  Thread* thread = Thread::Current();
+  ASSERT(thread != NULL);
+  OSThread* os_thread = thread->os_thread();
+  ASSERT(os_thread != NULL);
+  Isolate* isolate = thread->isolate();
+  if (!CheckIsolate(isolate)) {
+    return;
+  }
+
+  const bool exited_dart_code = thread->HasExitedDartCode();
+
+  OS::Print("Dumping %s stack trace for thread %" Px "\n",
+            native_stack_trace ? "native" : "dart-only",
+            OSThread::ThreadIdToIntPtr(os_thread->trace_id()));
+
+  uintptr_t sp = Thread::GetCurrentStackPointer();
+  uintptr_t fp = 0;
+  uintptr_t pc = GetProgramCounter();
+
+  COPY_FP_REGISTER(fp);
+
+  uword stack_lower = 0;
+  uword stack_upper = 0;
+
+  if (!InitialRegisterCheck(pc, fp, sp)) {
+    OS::Print(
+        "Stack dump aborted because InitialRegisterCheck.\n");
+    return;
+  }
+
+  if (!GetAndValidateIsolateStackBounds(thread,
+                                        fp,
+                                        sp,
+                                        &stack_lower,
+                                        &stack_upper)) {
+    OS::Print(
+        "Stack dump aborted because GetAndValidateIsolateStackBounds.\n");
+    return;
+  }
+
+  if (native_stack_trace) {
+    ProfilerNativeStackWalker native_stack_walker(isolate,
+                                                  NULL,
+                                                  NULL,
+                                                  stack_lower,
+                                                  stack_upper,
+                                                  pc,
+                                                  fp,
+                                                  sp);
+    native_stack_walker.walk();
+  } else if (exited_dart_code) {
+    ProfilerDartExitStackWalker dart_exit_stack_walker(thread,
+                                                       isolate,
+                                                       NULL,
+                                                       NULL);
+    dart_exit_stack_walker.walk();
+  } else {
+    ProfilerDartStackWalker dart_stack_walker(isolate,
+                                              NULL,
+                                              NULL,
+                                              stack_lower,
+                                              stack_upper,
+                                              pc,
+                                              fp,
+                                              sp);
+  }
+  OS::Print("-- End of DumpStackTrace");
+}
+
+
 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) {
   ASSERT(thread != NULL);
   OSThread* os_thread = thread->os_thread();
@@ -973,6 +1107,11 @@
 
 void Profiler::SampleThread(Thread* thread,
                             const InterruptedThreadState& state) {
+#if defined(TARGET_ARCH_DBC)
+  // TODO(vegorov) implement simulator stack sampling.
+  return;
+#endif
+
   ASSERT(thread != NULL);
   OSThread* os_thread = thread->os_thread();
   ASSERT(os_thread != NULL);
@@ -996,13 +1135,15 @@
   uintptr_t sp = 0;
   uintptr_t fp = state.fp;
   uintptr_t pc = state.pc;
-#if defined(USING_SIMULATOR)
+#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
   Simulator* simulator = NULL;
 #endif
 
   if (in_dart_code) {
     // If we're in Dart code, use the Dart stack pointer.
-#if defined(USING_SIMULATOR)
+#if defined(TARGET_ARCH_DBC)
+    UNIMPLEMENTED();
+#elif defined(USING_SIMULATOR)
     simulator = isolate->simulator();
     sp = simulator->get_register(SPREG);
     fp = simulator->get_register(FPREG);
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index 096d429..32b4ec4 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -39,6 +39,8 @@
     return sample_buffer_;
   }
 
+  static void DumpStackTrace(bool native_stack_trace = true);
+
   static void SampleAllocation(Thread* thread, intptr_t cid);
 
   // SampleThread is called from inside the signal handler and hence it is very
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 6a5d626..2e67ee2 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -231,6 +231,8 @@
   friend class object;                                                         \
   friend class RawObject;                                                      \
   friend class Heap;                                                           \
+  friend class Simulator;                                                      \
+  friend class SimulatorHelpers;                                               \
   DISALLOW_ALLOCATION();                                                       \
   DISALLOW_IMPLICIT_CONSTRUCTORS(Raw##object)
 
@@ -654,7 +656,8 @@
   friend class RetainingPathVisitor;  // GetClassId
   friend class SkippedCodeFunctions;  // StorePointer
   friend class InstructionsReader;  // tags_ check
-  friend class InstructionsWriter;
+  friend class AssemblyInstructionsWriter;
+  friend class BlobInstructionsWriter;
   friend class SnapshotReader;
   friend class SnapshotWriter;
   friend class String;
@@ -665,6 +668,8 @@
   friend class StackFrame;  // GetCodeObject assertion.
   friend class CodeLookupTableBuilder;  // profiler
   friend class NativeEntry;  // GetClassId
+  friend class Simulator;
+  friend class SimulatorHelpers;
 
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(RawObject);
@@ -1025,14 +1030,12 @@
   RawGrowableObjectArray* patch_classes_;
   RawArray* imports_;            // List of Namespaces imported without prefix.
   RawArray* exports_;            // List of re-exported Namespaces.
-  RawArray* exports2_;           // Copy of exports_, used by background
-                                 // compiler to detect cycles without colliding
-                                 // with mutator thread lookups.
   RawInstance* load_error_;      // Error iff load_state_ == kLoadError.
   RawObject** to_snapshot() {
     return reinterpret_cast<RawObject**>(&ptr()->load_error_);
   }
   RawArray* resolved_names_;     // Cache of resolved names in library scope.
+  RawArray* exported_names_;     // Cache of exported names by library.
   RawArray* loaded_scripts_;     // Array of scripts loaded in this library.
   RawObject** to() {
     return reinterpret_cast<RawObject**>(&ptr()->loaded_scripts_);
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 0ca54d8..40c1e34 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -1182,6 +1182,7 @@
     } else {
       library.InitResolvedNamesCache(kInitialNameCacheSize, reader);
     }
+    library.StorePointer(&library.raw_ptr()->exported_names_, Array::null());
     // Initialize cache of loaded scripts.
     library.StorePointer(&library.raw_ptr()->loaded_scripts_, Array::null());
   }
@@ -1540,9 +1541,13 @@
           break;
         }
         case ObjectPool::kNativeEntry: {
+#if !defined(TARGET_ARCH_DBC)
           // Read nothing. Initialize with the lazy link entry.
           uword new_entry = NativeEntry::LinkNativeCallEntry();
           result->SetRawValueAt(i, static_cast<intptr_t>(new_entry));
+#else
+          UNREACHABLE();  // DBC does not support lazy native call linking.
+#endif
           break;
         }
         default:
@@ -1592,14 +1597,16 @@
       Entry& entry = ptr()->data()[i];
       switch (entry_type) {
         case ObjectPool::kTaggedObject: {
+#if !defined(TARGET_ARCH_DBC)
           if (entry.raw_obj_ == StubCode::CallNativeCFunction_entry()->code()) {
             // Natives can run while precompiling, becoming linked and switching
             // their stub. Reset to the initial stub used for lazy-linking.
             writer->WriteObjectImpl(
                 StubCode::CallBootstrapCFunction_entry()->code(), kAsReference);
-          } else {
-            writer->WriteObjectImpl(entry.raw_obj_, kAsReference);
+            break;
           }
+#endif
+          writer->WriteObjectImpl(entry.raw_obj_, kAsReference);
           break;
         }
         case ObjectPool::kImmediate: {
@@ -1608,6 +1615,9 @@
         }
         case ObjectPool::kNativeEntry: {
           // Write nothing. Will initialize with the lazy link entry.
+#if defined(TARGET_ARCH_DBC)
+          UNREACHABLE();   // DBC does not support lazy native call linking.
+#endif
           break;
         }
         default:
@@ -2293,7 +2303,7 @@
                             Instance::InstanceSize(),
                             HEAP_SPACE(kind));
     if (RawObject::IsCanonical(tags)) {
-      obj = obj.CheckAndCanonicalize(NULL);
+      obj = obj.CheckAndCanonicalize(reader->thread(), NULL);
     }
   }
   reader->AddBackRef(object_id, &obj, kIsDeserialized);
@@ -2404,7 +2414,7 @@
       // Set the canonical bit.
       obj.SetCanonical();
     } else {
-      obj ^= obj.CheckAndCanonicalize(NULL);
+      obj ^= obj.CheckAndCanonicalize(reader->thread(), NULL);
       ASSERT(!obj.IsNull());
       ASSERT(obj.IsCanonical());
     }
@@ -2831,7 +2841,7 @@
       if (kind == Snapshot::kFull) {
         array->SetCanonical();
       } else {
-        *array ^= array->CheckAndCanonicalize(NULL);
+        *array ^= array->CheckAndCanonicalize(reader->thread(), NULL);
       }
     }
   }
@@ -3247,7 +3257,7 @@
       // Set the canonical bit.
       result.SetCanonical();
     } else {
-      result ^= result.CheckAndCanonicalize(NULL);
+      result ^= result.CheckAndCanonicalize(reader->thread(), NULL);
       ASSERT(!result.IsNull());
       ASSERT(result.IsCanonical());
     }
diff --git a/runtime/vm/runtime_entry_dbc.cc b/runtime/vm/runtime_entry_dbc.cc
new file mode 100644
index 0000000..8e03f1a
--- /dev/null
+++ b/runtime/vm/runtime_entry_dbc.cc
@@ -0,0 +1,29 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h"
+#if defined(TARGET_ARCH_DBC)
+
+#include "vm/runtime_entry.h"
+
+#include "vm/assembler.h"
+#include "vm/simulator.h"
+#include "vm/stub_code.h"
+
+namespace dart {
+
+
+uword RuntimeEntry::GetEntryPoint() const {
+  return reinterpret_cast<uword>(function());
+}
+
+
+void RuntimeEntry::Call(Assembler* assembler, intptr_t argument_count) const {
+  UNIMPLEMENTED();
+}
+
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index ee6d8e9..47e77f4 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.3
+# Dart VM Service Protocol 3.4
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes of _version 3.3_ of the Dart VM Service Protocol. This
+This document describes of _version 3.4_ of the Dart VM Service Protocol. This
 protocol is used to communicate with a running Dart Virtual Machine.
 
 To use the Service Protocol, start the VM with the *--observe* flag.
@@ -512,7 +512,7 @@
 FlagList getFlagList()
 ```
 
-The _getFlagList RPC returns a list of all command line flags in the
+The _getFlagList_ RPC returns a list of all command line flags in the
 VM along with their current values.
 
 See [FlagList](#flaglist).
diff --git a/runtime/vm/simulator.h b/runtime/vm/simulator.h
index 8a859e3..b73bd97 100644
--- a/runtime/vm/simulator.h
+++ b/runtime/vm/simulator.h
@@ -17,6 +17,8 @@
 #include "vm/simulator_arm64.h"
 #elif defined(TARGET_ARCH_MIPS)
 #include "vm/simulator_mips.h"
+#elif defined(TARGET_ARCH_DBC)
+#include "vm/simulator_dbc.h"
 #else
 #error Unknown architecture.
 #endif  // defined(TARGET_ARCH_...)
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 1fcb66b..f11bab7 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -44,7 +44,6 @@
 // The runtime then does a Longjmp on that buffer to return to the simulator.
 class SimulatorSetjmpBuffer {
  public:
-  int Setjmp() { return setjmp(buffer_); }
   void Longjmp() {
     // "This" is now the last setjmp buffer.
     simulator_->set_last_setjmp_buffer(this);
@@ -1546,7 +1545,7 @@
           ASSERT(sizeof(NativeArguments) == 4*kWordSize);
           arguments.thread_ = reinterpret_cast<Thread*>(get_register(R0));
           arguments.argc_tag_ = get_register(R1);
-          arguments.argv_ = reinterpret_cast<RawObject*(*)[]>(get_register(R2));
+          arguments.argv_ = reinterpret_cast<RawObject**>(get_register(R2));
           arguments.retval_ = reinterpret_cast<RawObject**>(get_register(R3));
           SimulatorRuntimeCall target =
               reinterpret_cast<SimulatorRuntimeCall>(external);
diff --git a/runtime/vm/simulator_arm.h b/runtime/vm/simulator_arm.h
index af3cb09..ce18ac0 100644
--- a/runtime/vm/simulator_arm.h
+++ b/runtime/vm/simulator_arm.h
@@ -52,6 +52,10 @@
   void set_register(Register reg, int32_t value);
   int32_t get_register(Register reg) const;
 
+  int32_t get_sp() const {
+    return get_register(SPREG);
+  }
+
   // Special case of set_register and get_register to access the raw PC value.
   void set_pc(int32_t value);
   int32_t get_pc() const;
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index cef6aa2..36f5f9c 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -43,7 +43,6 @@
 // The runtime then does a Longjmp on that buffer to return to the simulator.
 class SimulatorSetjmpBuffer {
  public:
-  int Setjmp() { return setjmp(buffer_); }
   void Longjmp() {
     // "This" is now the last setjmp buffer.
     simulator_->set_last_setjmp_buffer(this);
diff --git a/runtime/vm/simulator_arm64.h b/runtime/vm/simulator_arm64.h
index bf3572c..78c1812 100644
--- a/runtime/vm/simulator_arm64.h
+++ b/runtime/vm/simulator_arm64.h
@@ -65,6 +65,10 @@
   void get_vregister(VRegister reg, simd_value_t* value) const;
   void set_vregister(VRegister reg, const simd_value_t& value);
 
+  int64_t get_sp() const {
+    return get_register(SPREG);
+  }
+
   int64_t get_pc() const;
   int64_t get_last_pc() const;
   void set_pc(int64_t pc);
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
new file mode 100644
index 0000000..7329114
--- /dev/null
+++ b/runtime/vm/simulator_dbc.cc
@@ -0,0 +1,1902 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include <setjmp.h>  // NOLINT
+#include <stdlib.h>
+
+#include "vm/globals.h"
+#if defined(TARGET_ARCH_DBC)
+
+#if !defined(USING_SIMULATOR)
+#error "DBC is a simulated architecture"
+#endif
+
+#include "vm/simulator.h"
+
+#include "vm/assembler.h"
+#include "vm/compiler.h"
+#include "vm/constants_dbc.h"
+#include "vm/cpu.h"
+#include "vm/dart_entry.h"
+#include "vm/debugger.h"
+#include "vm/disassembler.h"
+#include "vm/lockers.h"
+#include "vm/native_arguments.h"
+#include "vm/native_entry.h"
+#include "vm/object.h"
+#include "vm/object_store.h"
+#include "vm/os_thread.h"
+#include "vm/stack_frame.h"
+
+namespace dart {
+
+DEFINE_FLAG(uint64_t, trace_sim_after, ULLONG_MAX,
+            "Trace simulator execution after instruction count reached.");
+DEFINE_FLAG(uint64_t, stop_sim_at, ULLONG_MAX,
+            "Instruction address or instruction count to stop simulator at.");
+
+// SimulatorSetjmpBuffer are linked together, and the last created one
+// is referenced by the Simulator. When an exception is thrown, the exception
+// runtime looks at where to jump and finds the corresponding
+// SimulatorSetjmpBuffer based on the stack pointer of the exception handler.
+// The runtime then does a Longjmp on that buffer to return to the simulator.
+class SimulatorSetjmpBuffer {
+ public:
+  void Longjmp() {
+    // "This" is now the last setjmp buffer.
+    simulator_->set_last_setjmp_buffer(this);
+    longjmp(buffer_, 1);
+  }
+
+  explicit SimulatorSetjmpBuffer(Simulator* sim) {
+    simulator_ = sim;
+    link_ = sim->last_setjmp_buffer();
+    sim->set_last_setjmp_buffer(this);
+    sp_ = sim->sp_;
+    fp_ = sim->fp_;
+  }
+
+  ~SimulatorSetjmpBuffer() {
+    ASSERT(simulator_->last_setjmp_buffer() == this);
+    simulator_->set_last_setjmp_buffer(link_);
+  }
+
+  SimulatorSetjmpBuffer* link() const { return link_; }
+
+  uword sp() const { return reinterpret_cast<uword>(sp_); }
+  uword fp() const { return reinterpret_cast<uword>(fp_); }
+
+  jmp_buf buffer_;
+
+ private:
+  RawObject** sp_;
+  RawObject** fp_;
+  Simulator* simulator_;
+  SimulatorSetjmpBuffer* link_;
+
+  friend class Simulator;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(SimulatorSetjmpBuffer);
+};
+
+
+DART_FORCE_INLINE static RawObject** SavedCallerFP(RawObject** FP) {
+  return reinterpret_cast<RawObject**>(FP[kSavedCallerFpSlotFromFp]);
+}
+
+
+DART_FORCE_INLINE static RawCode* FrameCode(RawObject** FP) {
+  return static_cast<RawCode*>(FP[kPcMarkerSlotFromFp]);
+}
+
+
+DART_FORCE_INLINE static void SetFrameCode(RawObject** FP, RawCode* code) {
+  FP[kPcMarkerSlotFromFp] = code;
+}
+
+
+DART_FORCE_INLINE static RawObject** FrameArguments(RawObject** FP,
+                                                    intptr_t argc) {
+  return FP - (kDartFrameFixedSize + argc);
+}
+
+
+class SimulatorHelpers {
+ public:
+  DART_FORCE_INLINE static RawSmi* GetClassIdAsSmi(RawObject* obj) {
+    return Smi::New(obj->IsHeapObject() ? obj->GetClassId()
+                                        : static_cast<intptr_t>(kSmiCid));
+  }
+
+  DART_FORCE_INLINE static intptr_t GetClassId(RawObject* obj) {
+    return obj->IsHeapObject() ? obj->GetClassId()
+                               : static_cast<intptr_t>(kSmiCid);
+  }
+
+  DART_FORCE_INLINE static void IncrementUsageCounter(RawICData* icdata) {
+    reinterpret_cast<RawFunction*>(icdata->ptr()->owner_)
+        ->ptr()
+        ->usage_counter_++;
+  }
+
+  DART_FORCE_INLINE static bool IsStrictEqualWithNumberCheck(RawObject* lhs,
+                                                             RawObject* rhs) {
+    if (lhs == rhs) {
+      return true;
+    }
+
+    if (lhs->IsHeapObject() && rhs->IsHeapObject()) {
+      const intptr_t lhs_cid = lhs->GetClassId();
+      const intptr_t rhs_cid = rhs->GetClassId();
+      if (lhs_cid == rhs_cid) {
+        switch (lhs_cid) {
+          case kDoubleCid:
+            return (bit_cast<uint64_t, double>(
+                        static_cast<RawDouble*>(lhs)->ptr()->value_) ==
+                    bit_cast<uint64_t, double>(
+                        static_cast<RawDouble*>(rhs)->ptr()->value_));
+
+          case kMintCid:
+            return (static_cast<RawMint*>(lhs)->ptr()->value_ ==
+                    static_cast<RawMint*>(rhs)->ptr()->value_);
+
+          case kBigintCid:
+            return (DLRT_BigintCompare(static_cast<RawBigint*>(lhs),
+                                       static_cast<RawBigint*>(rhs)) == 0);
+        }
+      }
+    }
+
+    return false;
+  }
+
+  template <typename T>
+  DART_FORCE_INLINE static T* Untag(T* tagged) {
+    return tagged->ptr();
+  }
+
+  DART_FORCE_INLINE static bool CheckIndex(RawSmi* index, RawSmi* length) {
+    return !index->IsHeapObject() &&
+           (reinterpret_cast<intptr_t>(index) >= 0) &&
+           (reinterpret_cast<intptr_t>(index) <
+                reinterpret_cast<intptr_t>(length));
+  }
+
+  static bool ObjectArraySetIndexed(Thread* thread,
+                                    RawObject** FP,
+                                    RawObject** result) {
+    if (thread->isolate()->type_checks()) {
+      return false;
+    }
+
+    RawObject** args = FrameArguments(FP, 3);
+    RawSmi* index = static_cast<RawSmi*>(args[1]);
+    RawArray* array = static_cast<RawArray*>(args[0]);
+    if (CheckIndex(index, array->ptr()->length_)) {
+      array->StorePointer(array->ptr()->data() + Smi::Value(index), args[2]);
+      return true;
+    }
+    return false;
+  }
+
+  static bool ObjectArrayGetIndexed(Thread* thread,
+                                    RawObject** FP,
+                                    RawObject** result) {
+    RawObject** args = FrameArguments(FP, 2);
+    RawSmi* index = static_cast<RawSmi*>(args[1]);
+    RawArray* array = static_cast<RawArray*>(args[0]);
+    if (CheckIndex(index, array->ptr()->length_)) {
+      *result = array->ptr()->data()[Smi::Value(index)];
+      return true;
+    }
+    return false;
+  }
+
+  static bool GrowableArraySetIndexed(Thread* thread,
+                                      RawObject** FP,
+                                      RawObject** result) {
+    if (thread->isolate()->type_checks()) {
+      return false;
+    }
+
+    RawObject** args = FrameArguments(FP, 3);
+    RawSmi* index = static_cast<RawSmi*>(args[1]);
+    RawGrowableObjectArray* array =
+        static_cast<RawGrowableObjectArray*>(args[0]);
+    if (CheckIndex(index, array->ptr()->length_)) {
+      RawArray* data = array->ptr()->data_;
+      data->StorePointer(data->ptr()->data() + Smi::Value(index), args[2]);
+      return true;
+    }
+    return false;
+  }
+
+  static bool GrowableArrayGetIndexed(Thread* thread,
+                                      RawObject** FP,
+                                      RawObject** result) {
+    RawObject** args = FrameArguments(FP, 2);
+    RawSmi* index = static_cast<RawSmi*>(args[1]);
+    RawGrowableObjectArray* array =
+        static_cast<RawGrowableObjectArray*>(args[0]);
+    if (CheckIndex(index, array->ptr()->length_)) {
+      *result = array->ptr()->data_->ptr()->data()[Smi::Value(index)];
+      return true;
+    }
+    return false;
+  }
+};
+
+
+DART_FORCE_INLINE static uint32_t* SavedCallerPC(RawObject** FP) {
+  return reinterpret_cast<uint32_t*>(FP[kSavedCallerPcSlotFromFp]);
+}
+
+
+DART_FORCE_INLINE static RawFunction* FrameFunction(RawObject** FP) {
+  RawFunction* function = static_cast<RawFunction*>(FP[kFunctionSlotFromFp]);
+  ASSERT(SimulatorHelpers::GetClassId(function) == kFunctionCid);
+  return function;
+}
+
+
+IntrinsicHandler Simulator::intrinsics_[Simulator::kIntrinsicCount];
+
+
+// Synchronization primitives support.
+void Simulator::InitOnce() {
+  for (intptr_t i = 0; i < kIntrinsicCount; i++) {
+    intrinsics_[i] = 0;
+  }
+
+  intrinsics_[kObjectArraySetIndexedIntrinsic] =
+      SimulatorHelpers::ObjectArraySetIndexed;
+  intrinsics_[kObjectArrayGetIndexedIntrinsic] =
+      SimulatorHelpers::ObjectArrayGetIndexed;
+  intrinsics_[kGrowableArraySetIndexedIntrinsic] =
+      SimulatorHelpers::GrowableArraySetIndexed;
+  intrinsics_[kGrowableArrayGetIndexedIntrinsic] =
+      SimulatorHelpers::GrowableArrayGetIndexed;
+}
+
+
+Simulator::Simulator()
+    : stack_(NULL),
+      fp_(NULL),
+      sp_(NULL) {
+  // Setup simulator support first. Some of this information is needed to
+  // setup the architecture state.
+  // We allocate the stack here, the size is computed as the sum of
+  // the size specified by the user and the buffer space needed for
+  // handling stack overflow exceptions. To be safe in potential
+  // stack underflows we also add some underflow buffer space.
+  stack_ = new uintptr_t[(OSThread::GetSpecifiedStackSize() +
+                          OSThread::kStackSizeBuffer +
+                          kSimulatorStackUnderflowSize) /
+                         sizeof(uintptr_t)];
+  last_setjmp_buffer_ = NULL;
+  top_exit_frame_info_ = 0;
+}
+
+
+Simulator::~Simulator() {
+  delete[] stack_;
+  Isolate* isolate = Isolate::Current();
+  if (isolate != NULL) {
+    isolate->set_simulator(NULL);
+  }
+}
+
+
+// Get the active Simulator for the current isolate.
+Simulator* Simulator::Current() {
+  Simulator* simulator = Isolate::Current()->simulator();
+  if (simulator == NULL) {
+    simulator = new Simulator();
+    Isolate::Current()->set_simulator(simulator);
+  }
+  return simulator;
+}
+
+
+// Returns the top of the stack area to enable checking for stack pointer
+// validity.
+uword Simulator::StackTop() const {
+  // To be safe in potential stack underflows we leave some buffer above and
+  // set the stack top.
+  return StackBase() +
+         (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer);
+}
+
+
+// Calls into the Dart runtime are based on this interface.
+typedef void (*SimulatorRuntimeCall)(NativeArguments arguments);
+
+// Calls to leaf Dart runtime functions are based on this interface.
+typedef intptr_t (*SimulatorLeafRuntimeCall)(intptr_t r0,
+                                             intptr_t r1,
+                                             intptr_t r2,
+                                             intptr_t r3);
+
+// Calls to leaf float Dart runtime functions are based on this interface.
+typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1);
+
+// Calls to native Dart functions are based on this interface.
+typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments);
+typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target);
+
+
+void Simulator::Exit(Thread* thread,
+                     RawObject** base,
+                     RawObject** frame,
+                     uint32_t* pc) {
+  frame[0] = Function::null();
+  frame[1] = Code::null();
+  frame[2] = reinterpret_cast<RawObject*>(pc);
+  frame[3] = reinterpret_cast<RawObject*>(base);
+  fp_ = sp_ = frame + kDartFrameFixedSize;
+  thread->set_top_exit_frame_info(reinterpret_cast<uword>(sp_));
+}
+
+// TODO(vegorov): Investigate advantages of using
+// __builtin_s{add,sub,mul}_overflow() intrinsics here and below.
+// Note that they may clobber the output location even when there is overflow:
+// https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html
+DART_FORCE_INLINE static bool SignedAddWithOverflow(intptr_t lhs,
+                                                    intptr_t rhs,
+                                                    intptr_t* out) {
+  intptr_t res = 1;
+#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
+  asm volatile(
+      "add %2, %1\n"
+      "jo 1f;\n"
+      "xor %0, %0\n"
+      "mov %1, 0(%3)\n"
+      "1: "
+      : "+r"(res), "+r"(lhs)
+      : "r"(rhs), "r"(out)
+      : "cc");
+#elif defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64)
+  asm volatile(
+      "adds %1, %1, %2;\n"
+      "bvs 1f;\n"
+      "mov %0, #0;\n"
+      "str %1, [%3, #0]\n"
+      "1:"
+      : "+r"(res), "+r"(lhs)
+      : "r"(rhs), "r"(out)
+      : "cc");
+#else
+#error "Unsupported platform"
+#endif
+  return (res != 0);
+}
+
+
+DART_FORCE_INLINE static bool SignedSubWithOverflow(intptr_t lhs,
+                                                    intptr_t rhs,
+                                                    intptr_t* out) {
+  intptr_t res = 1;
+#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
+  asm volatile(
+      "sub %2, %1\n"
+      "jo 1f;\n"
+      "xor %0, %0\n"
+      "mov %1, 0(%3)\n"
+      "1: "
+      : "+r"(res), "+r"(lhs)
+      : "r"(rhs), "r"(out)
+      : "cc");
+#elif defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64)
+  asm volatile(
+      "subs %1, %1, %2;\n"
+      "bvs 1f;\n"
+      "mov %0, #0;\n"
+      "str %1, [%3, #0]\n"
+      "1:"
+      : "+r"(res), "+r"(lhs)
+      : "r"(rhs), "r"(out)
+      : "cc");
+#else
+#error "Unsupported platform"
+#endif
+  return (res != 0);
+}
+
+
+DART_FORCE_INLINE static bool SignedMulWithOverflow(intptr_t lhs,
+                                                    intptr_t rhs,
+                                                    intptr_t* out) {
+  intptr_t res = 1;
+#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
+  asm volatile(
+      "imul %2, %1\n"
+      "jo 1f;\n"
+      "xor %0, %0\n"
+      "mov %1, 0(%3)\n"
+      "1: "
+      : "+r"(res), "+r"(lhs)
+      : "r"(rhs), "r"(out)
+      : "cc");
+#elif defined(HOST_ARCH_ARM)
+  asm volatile(
+      "smull %1, ip, %1, %2;\n"
+      "cmp ip, %1, ASR #31;\n"
+      "bne 1f;\n"
+      "mov %0, $0;\n"
+      "str %1, [%3, #0]\n"
+      "1:"
+      : "+r"(res), "+r"(lhs)
+      : "r"(rhs), "r"(out)
+      : "cc", "r12");
+#elif defined(HOST_ARCH_ARM64)
+  int64_t prod_lo;
+  asm volatile(
+      "mul %1, %2, %3\n"
+      "smulh %2, %2, %3\n"
+      "cmp %2, %1, ASR #63;\n"
+      "bne 1f;\n"
+      "mov %0, #0;\n"
+      "str %1, [%4, #0]\n"
+      "1:"
+      : "+r"(res), "=r"(prod_lo), "+r"(lhs)
+      : "r"(rhs), "r"(out)
+      : "cc");
+#else
+#error "Unsupported platform"
+#endif
+  return (res != 0);
+}
+
+
+#define LIKELY(cond) __builtin_expect((cond), 1)
+
+
+DART_FORCE_INLINE static bool AreBothSmis(intptr_t a, intptr_t b) {
+  return ((a | b) & kHeapObjectTag) == 0;
+}
+
+
+#define SMI_MUL(lhs, rhs, pres) SignedMulWithOverflow((lhs), (rhs) >> 1, pres)
+#define SMI_COND(cond, lhs, rhs, pres) \
+  ((*(pres) = ((lhs cond rhs) ? true_value : false_value)), false)
+#define SMI_EQ(lhs, rhs, pres) SMI_COND(==, lhs, rhs, pres)
+#define SMI_LT(lhs, rhs, pres) SMI_COND(<, lhs, rhs, pres)
+#define SMI_GT(lhs, rhs, pres) SMI_COND(>, lhs, rhs, pres)
+#define SMI_BITOR(lhs, rhs, pres) ((*(pres) = (lhs | rhs)), false)
+#define SMI_BITAND(lhs, rhs, pres) ((*(pres) = ((lhs) & (rhs))), false)
+
+
+void Simulator::CallRuntime(Thread* thread,
+                            RawObject** base,
+                            RawObject** exit_frame,
+                            uint32_t* pc,
+                            intptr_t argc_tag,
+                            RawObject** args,
+                            RawObject** result,
+                            uword target) {
+  Exit(thread, base, exit_frame, pc);
+  NativeArguments native_args(thread, argc_tag, args, result);
+  reinterpret_cast<RuntimeFunction>(target)(native_args);
+}
+
+
+DART_FORCE_INLINE void Simulator::Invoke(Thread* thread,
+                                         RawObject** call_base,
+                                         RawObject** call_top,
+                                         RawObjectPool** pp,
+                                         uint32_t** pc,
+                                         RawObject*** FP,
+                                         RawObject*** SP) {
+  RawObject** callee_fp = call_top + kDartFrameFixedSize;
+
+  RawFunction* function = FrameFunction(callee_fp);
+  RawCode* code = function->ptr()->code_;
+  callee_fp[kPcMarkerSlotFromFp] = code;
+  callee_fp[kSavedCallerPcSlotFromFp] = reinterpret_cast<RawObject*>(*pc);
+  callee_fp[kSavedCallerFpSlotFromFp] = reinterpret_cast<RawObject*>(*FP);
+  *pp = code->ptr()->object_pool_->ptr();
+  *pc = reinterpret_cast<uint32_t*>(code->ptr()->entry_point_);
+  *FP = callee_fp;
+  *SP = *FP - 1;
+}
+
+
+void Simulator::InlineCacheMiss(int checked_args,
+                                Thread* thread,
+                                RawICData* icdata,
+                                RawObject** args,
+                                RawObject** top,
+                                uint32_t* pc,
+                                RawObject** FP,
+                                RawObject** SP) {
+  RawObject** result = top;
+  RawObject** miss_handler_args = top + 1;
+  for (intptr_t i = 0; i < checked_args; i++) {
+    miss_handler_args[i] = args[i];
+  }
+  miss_handler_args[checked_args] = icdata;
+  RuntimeFunction handler = NULL;
+  switch (checked_args) {
+    case 1:
+      handler = DRT_InlineCacheMissHandlerOneArg;
+      break;
+    case 2:
+      handler = DRT_InlineCacheMissHandlerTwoArgs;
+      break;
+    case 3:
+      handler = DRT_InlineCacheMissHandlerThreeArgs;
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+
+  // Handler arguments: arguments to check and an ICData object.
+  const intptr_t miss_handler_argc = checked_args + 1;
+  RawObject** exit_frame = miss_handler_args + miss_handler_argc;
+  CallRuntime(thread,
+              FP,
+              exit_frame,
+              pc,
+              miss_handler_argc,
+              miss_handler_args,
+              result,
+              reinterpret_cast<uword>(handler));
+}
+
+
+DART_FORCE_INLINE void Simulator::InstanceCall1(Thread* thread,
+                                                RawICData* icdata,
+                                                RawObject** call_base,
+                                                RawObject** top,
+                                                RawArray** argdesc,
+                                                RawObjectPool** pp,
+                                                uint32_t** pc,
+                                                RawObject*** FP,
+                                                RawObject*** SP) {
+  ASSERT(icdata->GetClassId() == kICDataCid);
+  SimulatorHelpers::IncrementUsageCounter(icdata);
+
+  const intptr_t kCheckedArgs = 1;
+  RawObject** args = call_base;
+  RawArray* cache = icdata->ptr()->ic_data_->ptr();
+
+  RawSmi* receiver_cid = SimulatorHelpers::GetClassIdAsSmi(args[0]);
+
+  bool found = false;
+  const intptr_t length = Smi::Value(cache->length_);
+  for (intptr_t i = 0;
+       i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) {
+    if (cache->data()[i + 0] == receiver_cid) {
+      top[0] = cache->data()[i + kCheckedArgs];
+      found = true;
+      break;
+    }
+  }
+
+  if (!found) {
+    InlineCacheMiss(
+        kCheckedArgs, thread, icdata, call_base, top, *pc, *FP, *SP);
+  }
+
+  *argdesc = icdata->ptr()->args_descriptor_;
+  Invoke(thread, call_base, top, pp, pc, FP, SP);
+}
+
+
+DART_FORCE_INLINE void Simulator::InstanceCall2(Thread* thread,
+                                                RawICData* icdata,
+                                                RawObject** call_base,
+                                                RawObject** top,
+                                                RawArray** argdesc,
+                                                RawObjectPool** pp,
+                                                uint32_t** pc,
+                                                RawObject*** FP,
+                                                RawObject*** SP) {
+  ASSERT(icdata->GetClassId() == kICDataCid);
+  SimulatorHelpers::IncrementUsageCounter(icdata);
+
+  const intptr_t kCheckedArgs = 2;
+  RawObject** args = call_base;
+  RawArray* cache = icdata->ptr()->ic_data_->ptr();
+
+  RawSmi* receiver_cid = SimulatorHelpers::GetClassIdAsSmi(args[0]);
+  RawSmi* arg0_cid = SimulatorHelpers::GetClassIdAsSmi(args[1]);
+
+  bool found = false;
+  const intptr_t length = Smi::Value(cache->length_);
+  for (intptr_t i = 0;
+       i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) {
+    if ((cache->data()[i + 0] == receiver_cid) &&
+        (cache->data()[i + 1] == arg0_cid)) {
+      top[0] = cache->data()[i + kCheckedArgs];
+      found = true;
+      break;
+    }
+  }
+
+  if (!found) {
+    InlineCacheMiss(
+        kCheckedArgs, thread, icdata, call_base, top, *pc, *FP, *SP);
+  }
+
+  *argdesc = icdata->ptr()->args_descriptor_;
+  Invoke(thread, call_base, top, pp, pc, FP, SP);
+}
+
+
+DART_FORCE_INLINE void Simulator::InstanceCall3(Thread* thread,
+                                                RawICData* icdata,
+                                                RawObject** call_base,
+                                                RawObject** top,
+                                                RawArray** argdesc,
+                                                RawObjectPool** pp,
+                                                uint32_t** pc,
+                                                RawObject*** FP,
+                                                RawObject*** SP) {
+  ASSERT(icdata->GetClassId() == kICDataCid);
+  SimulatorHelpers::IncrementUsageCounter(icdata);
+
+  const intptr_t kCheckedArgs = 3;
+  RawObject** args = call_base;
+  RawArray* cache = icdata->ptr()->ic_data_->ptr();
+
+  RawSmi* receiver_cid = SimulatorHelpers::GetClassIdAsSmi(args[0]);
+  RawSmi* arg0_cid = SimulatorHelpers::GetClassIdAsSmi(args[1]);
+  RawSmi* arg1_cid = SimulatorHelpers::GetClassIdAsSmi(args[2]);
+
+  bool found = false;
+  const intptr_t length = Smi::Value(cache->length_);
+  for (intptr_t i = 0;
+       i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) {
+    if ((cache->data()[i + 0] == receiver_cid) &&
+        (cache->data()[i + 1] == arg0_cid) &&
+        (cache->data()[i + 2] == arg1_cid)) {
+      top[0] = cache->data()[i + kCheckedArgs];
+      found = true;
+      break;
+    }
+  }
+
+  if (!found) {
+    InlineCacheMiss(
+        kCheckedArgs, thread, icdata, call_base, top, *pc, *FP, *SP);
+  }
+
+  *argdesc = icdata->ptr()->args_descriptor_;
+  Invoke(thread, call_base, top, pp, pc, FP, SP);
+}
+
+
+// Note: functions below are marked DART_NOINLINE to recover performance on
+// ARM where inlining these functions into the interpreter loop seemed to cause
+// some code quality issues.
+static DART_NOINLINE bool InvokeRuntime(
+    Thread* thread,
+    Simulator* sim,
+    RuntimeFunction drt,
+    const NativeArguments& args) {
+  SimulatorSetjmpBuffer buffer(sim);
+  if (!setjmp(buffer.buffer_)) {
+    thread->set_vm_tag(reinterpret_cast<uword>(drt));
+    drt(args);
+    thread->set_vm_tag(VMTag::kDartTagId);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+
+static DART_NOINLINE bool InvokeNative(
+    Thread* thread,
+    Simulator* sim,
+    SimulatorBootstrapNativeCall f,
+    NativeArguments* args) {
+  SimulatorSetjmpBuffer buffer(sim);
+  if (!setjmp(buffer.buffer_)) {
+    thread->set_vm_tag(reinterpret_cast<uword>(f));
+    f(args);
+    thread->set_vm_tag(VMTag::kDartTagId);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+
+static DART_NOINLINE bool InvokeNativeWrapper(
+    Thread* thread,
+    Simulator* sim,
+    Dart_NativeFunction f,
+    NativeArguments* args) {
+  SimulatorSetjmpBuffer buffer(sim);
+  if (!setjmp(buffer.buffer_)) {
+    thread->set_vm_tag(reinterpret_cast<uword>(f));
+    NativeEntry::NativeCallWrapper(reinterpret_cast<Dart_NativeArguments>(args),
+                                   f);
+    thread->set_vm_tag(VMTag::kDartTagId);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+// Note: all macro helpers are intended to be used only inside Simulator::Call.
+
+// Decode opcode and A part of the given value and dispatch to the
+// corresponding bytecode handler.
+#define DISPATCH_OP(val)         \
+  do {                           \
+    op = (val);                \
+    rA = ((op >> 8) & 0xFF);   \
+    goto* dispatch[op & 0xFF]; \
+  } while (0)
+
+// Fetch next operation from PC, increment program counter and dispatch.
+#define DISPATCH() DISPATCH_OP(*pc++)
+
+// Define entry point that handles bytecode Name with the given operand format.
+#define BYTECODE(Name, Operands) \
+  BYTECODE_HEADER(Name, DECLARE_##Operands, DECODE_##Operands)
+
+#define BYTECODE_HEADER(Name, Declare, Decode) \
+  Declare;                                     \
+  bc##Name : Decode                            \
+
+// Helpers to decode common instruction formats. Used in conjunction with
+// BYTECODE() macro.
+#define DECLARE_A_B_C uint16_t rB, rC; USE(rB); USE(rC)
+#define DECODE_A_B_C \
+  rB = ((op >> Bytecode::kBShift) & Bytecode::kBMask);    \
+  rC = ((op >> Bytecode::kCShift) & Bytecode::kCMask);
+
+#define DECLARE_0
+#define DECODE_0
+
+#define DECLARE_A
+#define DECODE_A
+
+#define DECLARE___D uint32_t rD; USE(rD)
+#define DECODE___D rD = (op >> Bytecode::kDShift);
+
+#define DECLARE_A_D DECLARE___D
+#define DECODE_A_D DECODE___D
+
+#define DECLARE_A_X int32_t rD; USE(rD)
+#define DECODE_A_X rD = (static_cast<int32_t>(op) >> Bytecode::kDShift);
+
+// Declare bytecode handler for a smi operation (e.g. AddTOS) with the
+// given result type and the given behavior specified as a function
+// that takes left and right operands and result slot and returns
+// true if fast-path succeeds.
+#define SMI_FASTPATH_TOS(ResultT, Func)                                        \
+  {                                                                            \
+    const intptr_t lhs = reinterpret_cast<intptr_t>(SP[-1]);                   \
+    const intptr_t rhs = reinterpret_cast<intptr_t>(SP[-0]);                   \
+    ResultT* slot = reinterpret_cast<ResultT*>(SP - 1);                        \
+    if (LIKELY(AreBothSmis(lhs, rhs) && !Func(lhs, rhs, slot))) {              \
+      /* Fast path succeeded. Skip the generic call that follows. */           \
+      pc++;                                                                    \
+      /* We dropped 2 arguments and push result                   */           \
+      SP--;                                                                    \
+    }                                                                          \
+  }
+
+// Exception handling helper. Gets handler FP and PC from the Simulator where
+// they were stored by Simulator::Longjmp and proceeds to execute the handler.
+// Corner case: handler PC can be a fake marker that marks entry frame, which
+// means exception was not handled in the Dart code. In this case we return
+// caught exception from Simulator::Call.
+#define HANDLE_EXCEPTION                                                       \
+  do {                                                                         \
+    FP = reinterpret_cast<RawObject**>(fp_);                                   \
+    pc = reinterpret_cast<uint32_t*>(pc_);                                     \
+    if ((reinterpret_cast<uword>(pc) & 2) != 0) {  /* Entry frame? */          \
+      fp_ = sp_ = reinterpret_cast<RawObject**>(fp_[0]);                       \
+      thread->set_top_exit_frame_info(reinterpret_cast<uword>(sp_));           \
+      thread->set_top_resource(top_resource);                                  \
+      thread->set_vm_tag(vm_tag);                                              \
+      return special_[kExceptionSpecialIndex];                                 \
+    }                                                                          \
+    pp = FrameCode(FP)->ptr()->object_pool_->ptr();                            \
+    goto DispatchAfterException;                                               \
+  } while (0)                                                                  \
+
+// Runtime call helpers: handle invocation and potential exception after return.
+#define INVOKE_RUNTIME(Func, Args)                \
+  if (!InvokeRuntime(thread, this, Func, Args)) { \
+    HANDLE_EXCEPTION;                             \
+  }                                               \
+
+#define INVOKE_NATIVE(Func, Args)                 \
+  if (!InvokeNative(thread, this, Func, &Args)) { \
+    HANDLE_EXCEPTION;                             \
+  }                                               \
+
+#define INVOKE_NATIVE_WRAPPER(Func, Args)                \
+  if (!InvokeNativeWrapper(thread, this, Func, &Args)) { \
+    HANDLE_EXCEPTION;                                    \
+  }                                                      \
+
+#define LOAD_CONSTANT(index) (pp->data()[(index)].raw_obj_)
+
+RawObject* Simulator::Call(const Code& code,
+                           const Array& arguments_descriptor,
+                           const Array& arguments,
+                           Thread* thread) {
+  // Dispatch used to interpret bytecode. Contains addresses of
+  // labels of bytecode handlers. Handlers themselves are defined below.
+  static const void* dispatch[] = {
+#define TARGET(name, fmt, fmta, fmtb, fmtc) &&bc##name,
+      BYTECODES_LIST(TARGET)
+#undef TARGET
+  };
+
+  // Interpreter state (see constants_dbc.h for high-level overview).
+  uint32_t* pc;  // Program Counter: points to the next op to execute.
+  RawObjectPool* pp;  // Pool Pointer.
+  RawObject** FP;  // Frame Pointer.
+  RawObject** SP;  // Stack Pointer.
+
+  RawArray* argdesc;  // Arguments Descriptor: used to pass information between
+                      // call instruction and the function entry.
+
+  uint32_t op;  // Currently executing op.
+  uint16_t rA;  // A component of the currently executing op.
+
+  if (sp_ == NULL) {
+    fp_ = sp_ = reinterpret_cast<RawObject**>(stack_);
+  }
+
+  // Save current VM tag and mark thread as executing Dart code.
+  const uword vm_tag = thread->vm_tag();
+  thread->set_vm_tag(VMTag::kDartTagId);
+
+  // Save current top stack resource and reset the list.
+  StackResource* top_resource = thread->top_resource();
+  thread->set_top_resource(NULL);
+
+  // Setup entry frame:
+  //
+  //                        ^
+  //                        |  previous Dart frames
+  //       ~~~~~~~~~~~~~~~  |
+  //       | ........... | -+
+  // fp_ > |             |     saved top_exit_frame_info
+  //       | arg 0       | -+
+  //       ~~~~~~~~~~~~~~~  |
+  //                         > incoming arguments
+  //       ~~~~~~~~~~~~~~~  |
+  //       | arg 1       | -+
+  //       | function    | -+
+  //       | code        |  |
+  //       | callee PC   | ---> special fake PC marking an entry frame
+  //  SP > | fp_         |  |
+  //  FP > | ........... |   > normal Dart frame (see stack_frame_dbc.h)
+  //                        |
+  //                        v
+  //
+  FP = fp_ + 1 + arguments.Length() + kDartFrameFixedSize;
+  SP = FP - 1;
+
+  // Save outer top_exit_frame_info.
+  fp_[0] = reinterpret_cast<RawObject*>(thread->top_exit_frame_info());
+
+  // Copy arguments and setup the Dart frame.
+  const intptr_t argc = arguments.Length();
+  for (intptr_t i = 0; i < argc; i++) {
+    fp_[1 + i] = arguments.At(i);
+  }
+
+  FP[kFunctionSlotFromFp] = code.function();
+  FP[kPcMarkerSlotFromFp] = code.raw();
+  FP[kSavedCallerPcSlotFromFp] = reinterpret_cast<RawObject*>((argc << 2) | 2);
+  FP[kSavedCallerFpSlotFromFp] = reinterpret_cast<RawObject*>(fp_);
+
+  // Load argument descriptor.
+  argdesc = arguments_descriptor.raw();
+
+  // Ready to start executing bytecode. Load entry point and corresponding
+  // object pool.
+  pc = reinterpret_cast<uint32_t*>(code.raw()->ptr()->entry_point_);
+  pp = code.object_pool()->ptr();
+
+  // Cache some frequently used values in the frame.
+  RawBool* true_value = Bool::True().raw();
+  RawBool* false_value = Bool::False().raw();
+  RawObject* null_value = Object::null();
+  RawObject* empty_context = thread->isolate()->object_store()->empty_context();
+
+#if defined(DEBUG)
+  Function& function_h = Function::Handle();
+#endif
+
+  // Enter the dispatch loop.
+  DISPATCH();
+
+  // Bytecode handlers (see constants_dbc.h for bytecode descriptions).
+  {
+    BYTECODE(Entry, A_B_C);
+    const uint8_t num_fixed_params = rA;
+    const uint16_t num_locals = rB;
+    const uint16_t context_reg = rC;
+
+    // Decode arguments descriptor.
+    const intptr_t pos_count = Smi::Value(*reinterpret_cast<RawSmi**>(
+        reinterpret_cast<uword>(argdesc->ptr()) +
+        Array::element_offset(ArgumentsDescriptor::kPositionalCountIndex)));
+
+    // Check that we got the right number of positional parameters.
+    if (pos_count != num_fixed_params) {
+      // Mismatch can only occur if current function is a closure.
+      goto ClosureNoSuchMethod;
+    }
+
+    // Initialize locals with null and set current context variable to
+    // empty context.
+    {
+      RawObject** L = FP;
+      for (intptr_t i = 0; i < num_locals; i++) {
+        L[i] = null_value;
+      }
+      L[context_reg] = empty_context;
+      SP = FP + num_locals - 1;
+    }
+
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(EntryOpt, A_B_C);
+    const uint16_t num_fixed_params = rA;
+    const uint16_t num_opt_pos_params = rB;
+    const uint16_t num_opt_named_params = rC;
+    const intptr_t min_num_pos_args = num_fixed_params;
+    const intptr_t max_num_pos_args = num_fixed_params + num_opt_pos_params;
+
+    // Decode arguments descriptor.
+    const intptr_t arg_count = Smi::Value(*reinterpret_cast<RawSmi**>(
+        reinterpret_cast<uword>(argdesc->ptr()) +
+        Array::element_offset(ArgumentsDescriptor::kCountIndex)));
+    const intptr_t pos_count = Smi::Value(*reinterpret_cast<RawSmi**>(
+        reinterpret_cast<uword>(argdesc->ptr()) +
+        Array::element_offset(ArgumentsDescriptor::kPositionalCountIndex)));
+    const intptr_t named_count = (arg_count - pos_count);
+
+    // Check that got the right number of positional parameters.
+    if ((min_num_pos_args > pos_count) || (pos_count > max_num_pos_args)) {
+      goto ClosureNoSuchMethod;
+    }
+
+    // Copy all passed position arguments.
+    RawObject** first_arg = FrameArguments(FP, arg_count);
+    memmove(FP, first_arg, pos_count * kWordSize);
+
+    if (num_opt_named_params != 0) {
+      // This is a function with named parameters.
+      // Walk the list of named parameters and their
+      // default values encoded as pairs of LoadConstant instructions that
+      // follows the entry point and find matching values via arguments
+      // descriptor.
+      RawObject** argdesc_data = argdesc->ptr()->data();
+
+      intptr_t i = named_count - 1;  // argument position
+      intptr_t j = num_opt_named_params - 1;  // parameter position
+      while ((j >= 0) && (i >= 0)) {
+        // Fetch formal parameter information: name, default value, target slot.
+        const uint32_t load_name = pc[2 * j];
+        const uint32_t load_value = pc[2 * j + 1];
+        ASSERT(Bytecode::DecodeOpcode(load_name) == Bytecode::kLoadConstant);
+        ASSERT(Bytecode::DecodeOpcode(load_value) == Bytecode::kLoadConstant);
+        const uint8_t reg = Bytecode::DecodeA(load_name);
+        ASSERT(reg == Bytecode::DecodeA(load_value));
+
+        RawString* name = static_cast<RawString*>(
+            LOAD_CONSTANT(Bytecode::DecodeD(load_name)));
+        if (name == argdesc_data[ArgumentsDescriptor::name_index(i)]) {
+          // Parameter was passed. Fetch passed value.
+          const intptr_t arg_index = Smi::Value(static_cast<RawSmi*>(
+              argdesc_data[ArgumentsDescriptor::position_index(i)]));
+          FP[reg] = first_arg[arg_index];
+          i--;  // Consume passed argument.
+        } else {
+          // Parameter was not passed. Fetch default value.
+          FP[reg] = LOAD_CONSTANT(Bytecode::DecodeD(load_value));
+        }
+        j--;  // Next formal parameter.
+      }
+
+      // If we have unprocessed formal parameters then initialize them all
+      // using default values.
+      while (j >= 0) {
+        const uint32_t load_name = pc[2 * j];
+        const uint32_t load_value = pc[2 * j + 1];
+        ASSERT(Bytecode::DecodeOpcode(load_name) == Bytecode::kLoadConstant);
+        ASSERT(Bytecode::DecodeOpcode(load_value) == Bytecode::kLoadConstant);
+        const uint8_t reg = Bytecode::DecodeA(load_name);
+        ASSERT(reg == Bytecode::DecodeA(load_value));
+
+        FP[reg] = LOAD_CONSTANT(Bytecode::DecodeD(load_value));
+        j--;
+      }
+
+      // If we have unprocessed passed arguments that means we have mismatch
+      // between formal parameters and concrete arguments. This can only
+      // occur if the current function is a closure.
+      if (i != -1) {
+        goto ClosureNoSuchMethod;
+      }
+
+      // Skip LoadConstant-s encoding information about named parameters.
+      pc += num_opt_named_params * 2;
+
+      // SP points past copied arguments.
+      SP = FP + num_fixed_params + num_opt_named_params - 1;
+    } else {
+      ASSERT(num_opt_pos_params != 0);
+      if (named_count != 0) {
+        // Function can't have both named and optional positional parameters.
+        // This kind of mismatch can only occur if the current function
+        // is a closure.
+        goto ClosureNoSuchMethod;
+      }
+
+      // Process the list of default values encoded as a sequence of
+      // LoadConstant instructions after EntryOpt bytecode.
+      // Execute only those that correspond to parameters the were not passed.
+      for (intptr_t i = pos_count - num_fixed_params;
+           i < num_opt_pos_params;
+           i++) {
+        const uint32_t load_value = pc[i];
+        ASSERT(Bytecode::DecodeOpcode(load_value) == Bytecode::kLoadConstant);
+#if defined(DEBUG)
+        const uint8_t reg = Bytecode::DecodeA(load_value);
+        ASSERT((num_fixed_params + i) == reg);
+#endif
+        FP[num_fixed_params + i] = LOAD_CONSTANT(Bytecode::DecodeD(load_value));
+      }
+
+      // Skip LoadConstant-s encoding default values for optional positional
+      // parameters.
+      pc += num_opt_pos_params;
+
+      // SP points past the last copied parameter.
+      SP = FP + max_num_pos_args - 1;
+    }
+
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(Frame, A_D);
+    // Initialize locals with null and increment SP.
+    const uint16_t num_locals = rD;
+    for (intptr_t i = 1; i <= num_locals; i++) {
+      SP[i] = null_value;
+    }
+    SP += num_locals;
+
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(SetFrame, A);
+    SP = FP + rA - 1;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(Compile, 0);
+    FP[0] = FrameFunction(FP);
+    FP[1] = 0;
+    Exit(thread, FP, FP + 2, pc);
+    NativeArguments args(thread, 1, FP, FP + 1);
+    INVOKE_RUNTIME(DRT_CompileFunction, args);
+    {
+      // Function should be compiled now, dispatch to its entry point.
+      RawCode* code = FrameFunction(FP)->ptr()->code_;
+      SetFrameCode(FP, code);
+      pp = code->ptr()->object_pool_->ptr();
+      pc = reinterpret_cast<uint32_t*>(code->ptr()->entry_point_);
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(CheckStack, A);
+    {
+      if (reinterpret_cast<uword>(SP) >= thread->stack_limit()) {
+        Exit(thread, FP, SP + 1, pc);
+        NativeArguments args(thread, 0, NULL, NULL);
+        INVOKE_RUNTIME(DRT_StackOverflow, args);
+      }
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DebugStep, A);
+    if (thread->isolate()->single_step()) {
+      Exit(thread, FP, SP + 1, pc);
+      NativeArguments args(thread, 0, NULL, NULL);
+      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DebugBreak, A);
+    {
+      const uint32_t original_bc =
+          static_cast<uint32_t>(reinterpret_cast<uintptr_t>(
+              thread->isolate()->debugger()->GetPatchedStubAddress(
+                  reinterpret_cast<uword>(pc))));
+
+      SP[1] = null_value;
+      Exit(thread, FP, SP + 2, pc);
+      NativeArguments args(thread, 0, NULL, SP + 1);
+      INVOKE_RUNTIME(DRT_BreakpointRuntimeHandler, args)
+      DISPATCH_OP(original_bc);
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(InstantiateType, A_D);
+    RawObject* type = LOAD_CONSTANT(rD);
+    SP[1] = type;
+    SP[2] = SP[0];
+    SP[0] = null_value;
+    Exit(thread, FP, SP + 3, pc);
+    {
+      NativeArguments args(thread, 2, SP + 1, SP);
+      INVOKE_RUNTIME(DRT_InstantiateType, args);
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(InstantiateTypeArgumentsTOS, A_D);
+    RawTypeArguments* type_arguments =
+        static_cast<RawTypeArguments*>(LOAD_CONSTANT(rD));
+
+    RawObject* instantiator = SP[0];
+    // If the instantiator is null and if the type argument vector
+    // instantiated from null becomes a vector of dynamic, then use null as
+    // the type arguments.
+    if (rA == 0 || null_value != instantiator) {
+      // First lookup in the cache.
+      RawArray* instantiations = type_arguments->ptr()->instantiations_;
+      for (intptr_t i = 0;
+           instantiations->ptr()->data()[i] != NULL;  // kNoInstantiator
+           i += 2) {
+        if (instantiations->ptr()->data()[i] == instantiator) {
+          // Found in the cache.
+          SP[0] = instantiations->ptr()->data()[i + 1];
+          goto InstantiateTypeArgumentsTOSDone;
+        }
+      }
+
+      // Cache lookup failed, call runtime.
+      SP[1] = type_arguments;
+      SP[2] = instantiator;
+
+      Exit(thread, FP, SP + 3, pc);
+      NativeArguments args(thread, 2, SP + 1, SP);
+      INVOKE_RUNTIME(DRT_InstantiateTypeArguments, args);
+    }
+
+  InstantiateTypeArgumentsTOSDone:
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(Throw, A);
+    {
+      SP[1] = 0;  // Space for result.
+      Exit(thread, FP, SP + 2, pc);
+      if (rA == 0) {  // Throw
+        NativeArguments args(thread, 1, SP, SP + 1);
+        INVOKE_RUNTIME(DRT_Throw, args);
+      } else {  // ReThrow
+        NativeArguments args(thread, 2, SP - 1, SP + 1);
+        INVOKE_RUNTIME(DRT_ReThrow, args);
+      }
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(Drop1, 0);
+    SP--;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(Drop, 0);
+    SP -= rA;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DropR, 0);
+    RawObject* result = SP[0];
+    SP -= rA;
+    SP[0] = result;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(LoadConstant, A_D);
+    FP[rA] = LOAD_CONSTANT(rD);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(PushConstant, __D);
+    *++SP = LOAD_CONSTANT(rD);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(Push, A_X);
+    *++SP = FP[rD];
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(Move, A_X);
+    FP[rA] = FP[rD];
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(StoreLocal, A_X);
+    FP[rD] = *SP;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(PopLocal, A_X);
+    FP[rD] = *SP--;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(MoveSpecial, A_D);
+    FP[rA] = special_[rD];
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(BooleanNegateTOS, 0);
+    SP[0] = (SP[0] == true_value) ? false_value : true_value;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(StaticCall, A_D);
+
+    // Check if single stepping.
+    if (thread->isolate()->single_step()) {
+      Exit(thread, FP, SP + 1, pc);
+      NativeArguments args(thread, 0, NULL, NULL);
+      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
+    }
+
+    // Invoke target function.
+    {
+      const uint16_t argc = rA;
+      RawObject** call_base = SP - argc;
+      RawObject** call_top = SP;  // *SP contains function
+      argdesc = static_cast<RawArray*>(LOAD_CONSTANT(rD));
+      Invoke(thread, call_base, call_top, &pp, &pc, &FP, &SP);
+    }
+
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(InstanceCall, A_D);
+
+    // Check if single stepping.
+    if (thread->isolate()->single_step()) {
+      Exit(thread, FP, SP + 1, pc);
+      NativeArguments args(thread, 0, NULL, NULL);
+      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
+    }
+
+    {
+      const uint16_t argc = rA;
+      const uint16_t kidx = rD;
+
+      RawObject** call_base = SP - argc + 1;
+      RawObject** call_top = SP + 1;
+      InstanceCall1(thread,
+                    static_cast<RawICData*>(LOAD_CONSTANT(kidx)),
+                    call_base, call_top, &argdesc, &pp, &pc, &FP, &SP);
+    }
+
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(InstanceCall2, A_D);
+    if (thread->isolate()->single_step()) {
+      Exit(thread, FP, SP + 1, pc);
+      NativeArguments args(thread, 0, NULL, NULL);
+      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
+    }
+
+    {
+      const uint16_t argc = rA;
+      const uint16_t kidx = rD;
+
+      RawObject** call_base = SP - argc + 1;
+      RawObject** call_top = SP + 1;
+      InstanceCall2(thread,
+                    static_cast<RawICData*>(LOAD_CONSTANT(kidx)),
+                    call_base, call_top, &argdesc, &pp, &pc, &FP, &SP);
+    }
+
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(InstanceCall3, A_D);
+    if (thread->isolate()->single_step()) {
+      Exit(thread, FP, SP + 1, pc);
+      NativeArguments args(thread, 0, NULL, NULL);
+      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
+    }
+
+    {
+      const uint16_t argc = rA;
+      const uint16_t kidx = rD;
+
+      RawObject** call_base = SP - argc + 1;
+      RawObject** call_top = SP + 1;
+      InstanceCall3(thread,
+                    static_cast<RawICData*>(LOAD_CONSTANT(kidx)),
+                    call_base, call_top, &argdesc, &pp, &pc, &FP, &SP);
+    }
+
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(NativeBootstrapCall, 0);
+    RawFunction* function = FrameFunction(FP);
+    RawObject** incoming_args =
+        (function->ptr()->num_optional_parameters_ == 0)
+            ? FrameArguments(FP, function->ptr()->num_fixed_parameters_)
+            : FP;
+
+    SimulatorBootstrapNativeCall native_target =
+        reinterpret_cast<SimulatorBootstrapNativeCall>(SP[-1]);
+    intptr_t argc_tag = reinterpret_cast<intptr_t>(SP[-0]);
+    SP[-0] = 0;  // Note: argc_tag is not smi-tagged.
+    SP[-1] = null_value;
+    Exit(thread, FP, SP + 1, pc);
+    NativeArguments args(thread, argc_tag, incoming_args, SP - 1);
+    INVOKE_NATIVE(native_target, args);
+    SP -= 1;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(NativeCall, 0);
+    RawFunction* function = FrameFunction(FP);
+    RawObject** incoming_args =
+        (function->ptr()->num_optional_parameters_ == 0)
+            ? FrameArguments(FP, function->ptr()->num_fixed_parameters_)
+            : FP;
+
+    Dart_NativeFunction native_target =
+        reinterpret_cast<Dart_NativeFunction>(SP[-1]);
+    intptr_t argc_tag = reinterpret_cast<intptr_t>(SP[-0]);
+    SP[-0] = 0;  // argc_tag is not smi tagged!
+    SP[-1] = null_value;
+    Exit(thread, FP, SP + 1, pc);
+    NativeArguments args(thread, argc_tag, incoming_args, SP - 1);
+    INVOKE_NATIVE_WRAPPER(native_target, args);
+    SP -= 1;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(AddTOS, A_B_C);
+    SMI_FASTPATH_TOS(intptr_t, SignedAddWithOverflow);
+    DISPATCH();
+  }
+  {
+    BYTECODE(SubTOS, A_B_C);
+    SMI_FASTPATH_TOS(intptr_t, SignedSubWithOverflow);
+    DISPATCH();
+  }
+  {
+    BYTECODE(MulTOS, A_B_C);
+    SMI_FASTPATH_TOS(intptr_t, SMI_MUL);
+    DISPATCH();
+  }
+  {
+    BYTECODE(BitOrTOS, A_B_C);
+    SMI_FASTPATH_TOS(intptr_t, SMI_BITOR);
+    DISPATCH();
+  }
+  {
+    BYTECODE(BitAndTOS, A_B_C);
+    SMI_FASTPATH_TOS(intptr_t, SMI_BITAND);
+    DISPATCH();
+  }
+  {
+    BYTECODE(EqualTOS, A_B_C);
+    SMI_FASTPATH_TOS(RawObject*, SMI_EQ);
+    DISPATCH();
+  }
+  {
+    BYTECODE(LessThanTOS, A_B_C);
+    SMI_FASTPATH_TOS(RawObject*, SMI_LT);
+    DISPATCH();
+  }
+  {
+    BYTECODE(GreaterThanTOS, A_B_C);
+    SMI_FASTPATH_TOS(RawObject*, SMI_GT);
+    DISPATCH();
+  }
+
+  // Return and return like instructions (Instrinsic).
+  {
+    RawObject* result;  // result to return to the caller.
+
+    BYTECODE(Intrinsic, A);
+    // Try invoking intrinsic handler. If it succeeds (returns true)
+    // then just return the value it returned to the caller.
+    result = null_value;
+    if (!intrinsics_[rA](thread, FP, &result)) {
+      DISPATCH();
+    }
+    goto ReturnImpl;
+
+    BYTECODE(Return, A);
+    result = FP[rA];
+    goto ReturnImpl;
+
+    BYTECODE(ReturnTOS, 0);
+    result = *SP;
+    // Fall through to the ReturnImpl.
+
+  ReturnImpl:
+    // Restore caller PC.
+    pc = SavedCallerPC(FP);
+
+    // Check if it is a fake PC marking the entry frame.
+    if ((reinterpret_cast<uword>(pc) & 2) != 0) {
+      const intptr_t argc = reinterpret_cast<uword>(pc) >> 2;
+      fp_ = sp_ =
+          reinterpret_cast<RawObject**>(FrameArguments(FP, argc + 1)[0]);
+      thread->set_top_exit_frame_info(reinterpret_cast<uword>(sp_));
+      thread->set_top_resource(top_resource);
+      thread->set_vm_tag(vm_tag);
+      return result;
+    }
+
+    // Look at the caller to determine how many arguments to pop.
+    const uint8_t argc = Bytecode::DecodeArgc(pc[-1]);
+
+    // Restore SP, FP and PP. Push result and dispatch.
+    SP = FrameArguments(FP, argc);
+    FP = SavedCallerFP(FP);
+    pp = FrameCode(FP)->ptr()->object_pool_->ptr();
+    *SP = result;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(StoreStaticTOS, A_D);
+    RawField* field = reinterpret_cast<RawField*>(LOAD_CONSTANT(rD));
+    RawInstance* value = static_cast<RawInstance*>(*SP--);
+    field->StorePointer(&field->ptr()->value_.static_value_, value);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(PushStatic, A_D);
+    RawField* field = reinterpret_cast<RawField*>(LOAD_CONSTANT(rD));
+    // Note: field is also on the stack, hence no increment.
+    *SP = field->ptr()->value_.static_value_;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(StoreField, A_B_C);
+    const uint16_t offset_in_words = rB;
+    const uint16_t value_reg = rC;
+
+    RawInstance* instance = reinterpret_cast<RawInstance*>(FP[rA]);
+    RawObject* value = reinterpret_cast<RawObject*>(FP[value_reg]);
+
+    instance->StorePointer(
+        reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words,
+        value);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(StoreFieldTOS, A_D);
+    const uint16_t offset_in_words = rD;
+    RawInstance* instance = reinterpret_cast<RawInstance*>(SP[-1]);
+    RawObject* value = reinterpret_cast<RawObject*>(SP[0]);
+    SP -= 2;  // Drop instance and value.
+    instance->StorePointer(
+        reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words,
+        value);
+
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(LoadField, A_B_C);
+    const uint16_t instance_reg = rB;
+    const uint16_t offset_in_words = rC;
+    RawInstance* instance = reinterpret_cast<RawInstance*>(FP[instance_reg]);
+    FP[rA] = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(LoadFieldTOS, A_D);
+    const uint16_t offset_in_words = rD;
+    RawInstance* instance = static_cast<RawInstance*>(SP[0]);
+    SP[0] = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(InitStaticTOS, A);
+    RawField* field = static_cast<RawField*>(*SP--);
+    RawObject* value = field->ptr()->value_.static_value_;
+    if ((value == Object::sentinel().raw()) ||
+        (value == Object::transition_sentinel().raw())) {
+      // Note: SP[1] already contains the field object.
+      SP[2] = 0;
+      Exit(thread, FP, SP + 3, pc);
+      NativeArguments args(thread, 1, SP + 1, SP + 2);
+      INVOKE_RUNTIME(DRT_InitStaticField, args);
+    }
+    DISPATCH();
+  }
+
+  // TODO(vegorov) allocation bytecodes can benefit from the new-space
+  // allocation fast-path that does not transition into the runtime system.
+  {
+    BYTECODE(AllocateContext, A_D);
+    const uint16_t num_context_variables = rD;
+    {
+      *++SP = 0;
+      SP[1] = Smi::New(num_context_variables);
+      Exit(thread, FP, SP + 2, pc);
+      NativeArguments args(thread, 1, SP + 1, SP);
+      INVOKE_RUNTIME(DRT_AllocateContext, args);
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(CloneContext, A);
+    {
+      SP[1] = SP[0];  // Context to clone.
+      Exit(thread, FP, SP + 2, pc);
+      NativeArguments args(thread, 1, SP + 1, SP);
+      INVOKE_RUNTIME(DRT_CloneContext, args);
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(Allocate, A_D);
+    SP[1] = 0;  // Space for the result.
+    SP[2] = LOAD_CONSTANT(rD);  // Class object.
+    SP[3] = null_value;  // Type arguments.
+    Exit(thread, FP, SP + 4, pc);
+    NativeArguments args(thread, 2, SP + 2, SP + 1);
+    INVOKE_RUNTIME(DRT_AllocateObject, args);
+    SP++;  // Result is in SP[1].
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(AllocateT, 0);
+    SP[1] = SP[-0];  // Class object.
+    SP[2] = SP[-1];  // Type arguments
+    Exit(thread, FP, SP + 3, pc);
+    NativeArguments args(thread, 2, SP + 1, SP - 1);
+    INVOKE_RUNTIME(DRT_AllocateObject, args);
+    SP -= 1;  // Result is in SP - 1.
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(CreateArrayTOS, 0);
+    SP[1] = SP[-0];  // Length.
+    SP[2] = SP[-1];  // Type.
+    Exit(thread, FP, SP + 3, pc);
+    NativeArguments args(thread, 2, SP + 1, SP - 1);
+    INVOKE_RUNTIME(DRT_AllocateArray, args);
+    SP -= 1;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(AssertAssignable, A_D);  // Stack: instance, type args, type, name
+    RawObject** args = SP - 3;
+    if (args[0] != null_value) {
+      RawSubtypeTestCache* cache =
+          static_cast<RawSubtypeTestCache*>(LOAD_CONSTANT(rD));
+      if (cache != null_value) {
+        RawInstance* instance = static_cast<RawInstance*>(args[0]);
+        RawTypeArguments* instantiator_type_arguments =
+            static_cast<RawTypeArguments*>(args[1]);
+
+        const intptr_t cid = SimulatorHelpers::GetClassId(instance);
+
+        RawTypeArguments* instance_type_arguments =
+            static_cast<RawTypeArguments*>(null_value);
+        RawObject* instance_cid_or_function;
+        if (cid == kClosureCid) {
+          RawClosure* closure = static_cast<RawClosure*>(instance);
+          instance_type_arguments = closure->ptr()->type_arguments_;
+          instance_cid_or_function = closure->ptr()->function_;
+        } else {
+          instance_cid_or_function = Smi::New(cid);
+
+          RawClass* instance_class =
+              thread->isolate()->class_table()->At(cid);
+          if (instance_class->ptr()->num_type_arguments_ < 0) {
+            goto AssertAssignableCallRuntime;
+          } else if (instance_class->ptr()->num_type_arguments_ > 0) {
+            instance_type_arguments = reinterpret_cast<RawTypeArguments**>(
+                instance
+                    ->ptr())[instance_class->ptr()
+                                 ->type_arguments_field_offset_in_words_];
+          }
+        }
+
+        for (RawObject** entries = cache->ptr()->cache_->ptr()->data();
+             entries[0] != null_value;
+             entries += SubtypeTestCache::kTestEntryLength) {
+          if ((entries[SubtypeTestCache::kInstanceClassIdOrFunction] ==
+                  instance_cid_or_function) &&
+              (entries[SubtypeTestCache::kInstanceTypeArguments] ==
+                  instance_type_arguments) &&
+              (entries[SubtypeTestCache::kInstantiatorTypeArguments] ==
+                  instantiator_type_arguments)) {
+            if (true_value == entries[SubtypeTestCache::kTestResult]) {
+              goto AssertAssignableOk;
+            } else {
+              break;
+            }
+          }
+        }
+      }
+
+    AssertAssignableCallRuntime:
+      SP[1] = args[0];  // instance
+      SP[2] = args[2];  // type
+      SP[3] = args[1];  // type args
+      SP[4] = args[3];  // name
+      SP[5] = cache;
+      Exit(thread, FP, SP + 6, pc);
+      NativeArguments args(thread, 5, SP + 1, SP - 3);
+      INVOKE_RUNTIME(DRT_TypeCheck, args);
+    }
+
+  AssertAssignableOk:
+    SP -= 3;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(AssertBoolean, A);
+    RawObject* value = SP[0];
+    if (rA) {  // Should we perform type check?
+      if ((value == true_value) || (value == false_value)) {
+        goto AssertBooleanOk;
+      }
+    } else if (value != null_value) {
+      goto AssertBooleanOk;
+    }
+
+    // Assertion failed.
+    {
+      SP[1] = SP[0];  // instance
+      Exit(thread, FP, SP + 2, pc);
+      NativeArguments args(thread, 1, SP + 1, SP);
+      INVOKE_RUNTIME(DRT_NonBoolTypeError, args);
+    }
+
+  AssertBooleanOk:
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfEqStrictTOS, A_D);
+    SP -= 2;
+    if (SP[1] != SP[2]) {
+      pc++;
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfNeStrictTOS, A_D);
+    SP -= 2;
+    if (SP[1] == SP[2]) {
+      pc++;
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfEqStrictNumTOS, A_D);
+    if (thread->isolate()->single_step()) {
+      Exit(thread, FP, SP + 1, pc);
+      NativeArguments args(thread, 0, NULL, NULL);
+      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
+    }
+
+    SP -= 2;
+    if (!SimulatorHelpers::IsStrictEqualWithNumberCheck(SP[1], SP[2])) {
+      pc++;
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfNeStrictNumTOS, A_D);
+    if (thread->isolate()->single_step()) {
+      Exit(thread, FP, SP + 1, pc);
+      NativeArguments args(thread, 0, NULL, NULL);
+      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
+    }
+
+    SP -= 2;
+    if (SimulatorHelpers::IsStrictEqualWithNumberCheck(SP[1], SP[2])) {
+      pc++;
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(Jump, 0);
+    const int32_t target = static_cast<int32_t>(op) >> 8;
+    pc += (target - 1);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(StoreIndexedTOS, 0);
+    SP -= 3;
+    RawArray* array = static_cast<RawArray*>(SP[1]);
+    RawSmi* index = static_cast<RawSmi*>(SP[2]);
+    RawObject* value = SP[3];
+    ASSERT(array->GetClassId() == kArrayCid);
+    ASSERT(!index->IsHeapObject());
+    array->StorePointer(array->ptr()->data() + Smi::Value(index), value);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(Trap, 0);
+    UNIMPLEMENTED();
+    DISPATCH();
+  }
+
+  // Helper used to handle noSuchMethod on closures.
+  {
+  ClosureNoSuchMethod:
+#if defined(DEBUG)
+    function_h ^= FrameFunction(FP);
+    ASSERT(function_h.IsClosureFunction());
+#endif
+
+    // Restore caller context as we are going to throw NoSuchMethod.
+    pc = SavedCallerPC(FP);
+
+    const bool has_dart_caller = (reinterpret_cast<uword>(pc) & 2) == 0;
+    const intptr_t argc = has_dart_caller
+                              ? Bytecode::DecodeArgc(pc[-1])
+                              : (reinterpret_cast<uword>(pc) >> 2);
+
+    SP = FrameArguments(FP, 0);
+    RawObject** args = SP - argc;
+    FP = SavedCallerFP(FP);
+    if (has_dart_caller) {
+      pp = FrameCode(FP)->ptr()->object_pool_->ptr();
+    }
+
+    *++SP = null_value;
+    *++SP = args[0];  // Closure object.
+    *++SP = argdesc;
+    *++SP = null_value;  // Array of arguments (will be filled).
+
+    // Allocate array of arguments.
+    {
+      SP[1] = Smi::New(argc);  // length
+      SP[2] = null_value;      // type
+      Exit(thread, FP, SP + 3, pc);
+      NativeArguments native_args(thread, 2, SP + 1, SP);
+      INVOKE_RUNTIME(DRT_AllocateArray, native_args);
+
+      // Copy arguments into the newly allocated array.
+      RawArray* array = static_cast<RawArray*>(SP[0]);
+      ASSERT(array->GetClassId() == kArrayCid);
+      for (intptr_t i = 0; i < argc; i++) {
+        array->ptr()->data()[i] = args[i];
+      }
+    }
+
+    // Invoke noSuchMethod passing down closure, argument descriptor and
+    // array of arguments.
+    {
+      Exit(thread, FP, SP + 1, pc);
+      NativeArguments native_args(thread, 3, SP - 2, SP - 3);
+      INVOKE_RUNTIME(DRT_InvokeClosureNoSuchMethod, native_args);
+      UNREACHABLE();
+    }
+
+    DISPATCH();
+  }
+
+  // Single dispatch point used by exception handling macros.
+  {
+  DispatchAfterException:
+    DISPATCH();
+  }
+
+  UNREACHABLE();
+  return 0;
+}
+
+void Simulator::Longjmp(uword pc,
+                        uword sp,
+                        uword fp,
+                        RawObject* raw_exception,
+                        RawObject* raw_stacktrace,
+                        Thread* thread) {
+  // Walk over all setjmp buffers (simulated --> C++ transitions)
+  // and try to find the setjmp associated with the simulated stack pointer.
+  SimulatorSetjmpBuffer* buf = last_setjmp_buffer();
+  while ((buf->link() != NULL) && (buf->link()->fp() > fp)) {
+    buf = buf->link();
+  }
+  ASSERT(buf != NULL);
+  ASSERT(last_setjmp_buffer() == buf);
+
+  // The C++ caller has not cleaned up the stack memory of C++ frames.
+  // Prepare for unwinding frames by destroying all the stack resources
+  // in the previous C++ frames.
+  StackResource::Unwind(thread);
+
+  // Set the tag.
+  thread->set_vm_tag(VMTag::kDartTagId);
+  // Clear top exit frame.
+  thread->set_top_exit_frame_info(0);
+
+  ASSERT(raw_exception != Object::null());
+  sp_ = reinterpret_cast<RawObject**>(sp);
+  fp_ = reinterpret_cast<RawObject**>(fp);
+  pc_ = pc;
+  special_[kExceptionSpecialIndex] = raw_exception;
+  special_[kStacktraceSpecialIndex] = raw_stacktrace;
+  buf->Longjmp();
+  UNREACHABLE();
+}
+
+}  // namespace dart
+
+
+#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/simulator_dbc.h b/runtime/vm/simulator_dbc.h
new file mode 100644
index 0000000..c1d3ff9a
--- /dev/null
+++ b/runtime/vm/simulator_dbc.h
@@ -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.
+
+#ifndef VM_SIMULATOR_DBC_H_
+#define VM_SIMULATOR_DBC_H_
+
+#ifndef VM_SIMULATOR_H_
+#error Do not include simulator_dbc.h directly; use simulator.h.
+#endif
+
+#include "vm/constants_dbc.h"
+#include "vm/method_recognizer.h"
+
+namespace dart {
+
+class Isolate;
+class RawObject;
+class SimulatorSetjmpBuffer;
+class Thread;
+class Code;
+class Array;
+class RawICData;
+class RawArray;
+class RawObjectPool;
+class RawFunction;
+
+// Simulator intrinsic handler. It is invoked on entry to the intrinsified
+// function via Intrinsic bytecode before the frame is setup.
+// If the handler returns true then Intrinsic bytecode works as a return
+// instruction returning the value in result. Otherwise interpreter proceeds to
+// execute the body of the function.
+typedef bool (*IntrinsicHandler)(Thread* thread,
+                                 RawObject** FP,
+                                 RawObject** result);
+
+
+class Simulator {
+ public:
+  static const uword kSimulatorStackUnderflowSize = 0x80;
+
+  Simulator();
+  ~Simulator();
+
+  // The currently executing Simulator instance, which is associated to the
+  // current isolate
+  static Simulator* Current();
+
+  // Accessors to the internal simulator stack base and top.
+  uword StackBase() const { return reinterpret_cast<uword>(stack_); }
+  uword StackTop() const;
+
+  // The isolate's top_exit_frame_info refers to a Dart frame in the simulator
+  // stack. The simulator's top_exit_frame_info refers to a C++ frame in the
+  // native stack.
+  uword top_exit_frame_info() const { return top_exit_frame_info_; }
+  void set_top_exit_frame_info(uword value) { top_exit_frame_info_ = value; }
+
+  // Call on program start.
+  static void InitOnce();
+
+  RawObject* Call(const Code& code,
+                  const Array& arguments_descriptor,
+                  const Array& arguments,
+                  Thread* thread);
+
+  void Longjmp(uword pc,
+               uword sp,
+               uword fp,
+               RawObject* raw_exception,
+               RawObject* raw_stacktrace,
+               Thread* thread);
+
+  uword get_sp() const {
+    return reinterpret_cast<uword>(sp_);
+  }
+
+  enum IntrinsicId {
+#define V(test_class_name, test_function_name, enum_name, fp) \
+    k##enum_name##Intrinsic,
+  ALL_INTRINSICS_LIST(V)
+  GRAPH_INTRINSICS_LIST(V)
+#undef V
+    kIntrinsicCount,
+  };
+
+  static bool IsSupportedIntrinsic(IntrinsicId id) {
+    return intrinsics_[id] != NULL;
+  }
+
+  enum SpecialIndex {
+    kExceptionSpecialIndex,
+    kStacktraceSpecialIndex,
+    kSpecialIndexCount
+  };
+
+ private:
+  uintptr_t* stack_;
+
+  RawObject** fp_;
+  RawObject** sp_;
+  uword pc_;
+
+  SimulatorSetjmpBuffer* last_setjmp_buffer_;
+  uword top_exit_frame_info_;
+
+  RawObject* special_[kSpecialIndexCount];
+
+  static IntrinsicHandler intrinsics_[kIntrinsicCount];
+
+  void Exit(Thread* thread,
+            RawObject** base,
+            RawObject** exit_frame,
+            uint32_t* pc);
+
+  void CallRuntime(Thread* thread,
+                   RawObject** base,
+                   RawObject** exit_frame,
+                   uint32_t* pc,
+                   intptr_t argc_tag,
+                   RawObject** args,
+                   RawObject** result,
+                   uword target);
+
+  void Invoke(Thread* thread,
+              RawObject** call_base,
+              RawObject** call_top,
+              RawObjectPool** pp,
+              uint32_t** pc,
+              RawObject*** B,
+              RawObject*** SP);
+
+  void InlineCacheMiss(int checked_args,
+                       Thread* thread,
+                       RawICData* icdata,
+                       RawObject** call_base,
+                       RawObject** top,
+                       uint32_t* pc,
+                       RawObject** B, RawObject** SP);
+
+  void InstanceCall1(Thread* thread,
+                     RawICData* icdata,
+                     RawObject** call_base,
+                     RawObject** call_top,
+                     RawArray** argdesc,
+                     RawObjectPool** pp,
+                     uint32_t** pc,
+                     RawObject*** B, RawObject*** SP);
+
+  void InstanceCall2(Thread* thread,
+                     RawICData* icdata,
+                     RawObject** call_base,
+                     RawObject** call_top,
+                     RawArray** argdesc,
+                     RawObjectPool** pp,
+                     uint32_t** pc,
+                     RawObject*** B, RawObject*** SP);
+
+  void InstanceCall3(Thread* thread,
+                     RawICData* icdata,
+                     RawObject** call_base,
+                     RawObject** call_top,
+                     RawArray** argdesc,
+                     RawObjectPool** pp,
+                     uint32_t** pc,
+                     RawObject*** B, RawObject*** SP);
+
+  // Longjmp support for exceptions.
+  SimulatorSetjmpBuffer* last_setjmp_buffer() {
+    return last_setjmp_buffer_;
+  }
+  void set_last_setjmp_buffer(SimulatorSetjmpBuffer* buffer) {
+    last_setjmp_buffer_ = buffer;
+  }
+
+  friend class SimulatorSetjmpBuffer;
+  DISALLOW_COPY_AND_ASSIGN(Simulator);
+};
+
+}  // namespace dart
+
+#endif  // VM_SIMULATOR_DBC_H_
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index 244b331..d23c755 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -43,7 +43,6 @@
 // The runtime then does a Longjmp on that buffer to return to the simulator.
 class SimulatorSetjmpBuffer {
  public:
-  int Setjmp() { return setjmp(buffer_); }
   void Longjmp() {
     // "This" is now the last setjmp buffer.
     simulator_->set_last_setjmp_buffer(this);
@@ -1257,7 +1256,7 @@
         ASSERT(sizeof(NativeArguments) == 4*kWordSize);
         arguments.thread_ = reinterpret_cast<Thread*>(get_register(A0));
         arguments.argc_tag_ = get_register(A1);
-        arguments.argv_ = reinterpret_cast<RawObject*(*)[]>(get_register(A2));
+        arguments.argv_ = reinterpret_cast<RawObject**>(get_register(A2));
         arguments.retval_ = reinterpret_cast<RawObject**>(get_register(A3));
         SimulatorRuntimeCall target =
             reinterpret_cast<SimulatorRuntimeCall>(external);
diff --git a/runtime/vm/simulator_mips.h b/runtime/vm/simulator_mips.h
index 8d10c3f..700b1f5 100644
--- a/runtime/vm/simulator_mips.h
+++ b/runtime/vm/simulator_mips.h
@@ -58,6 +58,10 @@
   int64_t get_dregister_bits(DRegister freg) const;
   double get_dregister(DRegister freg) const;
 
+  int32_t get_sp() const {
+    return get_register(SPREG);
+  }
+
   // Accessor for the pc.
   void set_pc(int32_t value) { pc_ = value; }
   int32_t get_pc() const { return pc_; }
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index c455d30..4729798 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -542,7 +542,7 @@
       if (kind_ == Snapshot::kFull) {
         result->SetCanonical();
       } else {
-        *result = result->CheckAndCanonicalize(NULL);
+        *result = result->CheckAndCanonicalize(thread(), NULL);
         ASSERT(!result->IsNull());
       }
     }
@@ -647,7 +647,6 @@
       }
     }
 
-
     // Validate the class table.
 #if defined(DEBUG)
     isolate->ValidateClassTable();
@@ -655,8 +654,17 @@
 
     // Setup native resolver for bootstrap impl.
     Bootstrap::SetupNativeResolver();
-    return ApiError::null();
   }
+
+  Class& cls = Class::Handle(thread->zone());
+  for (intptr_t i = 0; i < backward_references_->length(); i++) {
+    if ((*backward_references_)[i].reference()->IsClass()) {
+      cls ^= (*backward_references_)[i].reference()->raw();
+      cls.RehashConstants(thread->zone());
+    }
+  }
+
+  return ApiError::null();
 }
 
 
@@ -1188,7 +1196,7 @@
 }
 
 
-void InstructionsWriter::WriteAssembly() {
+void AssemblyInstructionsWriter::Write() {
   Zone* zone = Thread::Current()->zone();
 
   // Handlify collected raw pointers as building the names below
@@ -1204,12 +1212,12 @@
     data.obj_ = &Object::Handle(zone, data.raw_obj_);
   }
 
-  stream_.Print(".text\n");
-  stream_.Print(".globl _kInstructionsSnapshot\n");
+  assembly_stream_.Print(".text\n");
+  assembly_stream_.Print(".globl _kInstructionsSnapshot\n");
   // Start snapshot at page boundary.
   ASSERT(VirtualMemory::PageSize() >= OS::kMaxPreferredCodeAlignment);
-  stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize());
-  stream_.Print("_kInstructionsSnapshot:\n");
+  assembly_stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize());
+  assembly_stream_.Print("_kInstructionsSnapshot:\n");
 
   // This head also provides the gap to make the instructions snapshot
   // look like a HeapPage.
@@ -1233,16 +1241,17 @@
     owner = code.owner();
     if (owner.IsNull()) {
       const char* name = StubCode::NameOfStub(insns.EntryPoint());
-      stream_.Print("Precompiled_Stub_%s:\n", name);
+      assembly_stream_.Print("Precompiled_Stub_%s:\n", name);
     } else if (owner.IsClass()) {
       str = Class::Cast(owner).Name();
       const char* name = str.ToCString();
       EnsureIdentifier(const_cast<char*>(name));
-      stream_.Print("Precompiled_AllocationStub_%s_%" Pd ":\n", name, i);
+      assembly_stream_.Print("Precompiled_AllocationStub_%s_%" Pd ":\n",
+                             name, i);
     } else if (owner.IsFunction()) {
       const char* name = Function::Cast(owner).ToQualifiedCString();
       EnsureIdentifier(const_cast<char*>(name));
-      stream_.Print("Precompiled_%s_%" Pd ":\n", name, i);
+      assembly_stream_.Print("Precompiled_%s_%" Pd ":\n", name, i);
     } else {
       UNREACHABLE();
     }
@@ -1268,24 +1277,25 @@
     }
   }
 #if defined(TARGET_OS_LINUX)
-  stream_.Print(".section .rodata\n");
+  assembly_stream_.Print(".section .rodata\n");
 #elif defined(TARGET_OS_MACOS)
-  stream_.Print(".const\n");
+  assembly_stream_.Print(".const\n");
 #else
   // Unsupported platform.
   UNREACHABLE();
 #endif
-  stream_.Print(".globl _kDataSnapshot\n");
+  assembly_stream_.Print(".globl _kDataSnapshot\n");
   // Start snapshot at page boundary.
-  stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize());
-  stream_.Print("_kDataSnapshot:\n");
+  assembly_stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize());
+  assembly_stream_.Print("_kDataSnapshot:\n");
   WriteWordLiteral(next_object_offset_);  // Data length.
   COMPILE_ASSERT(OS::kMaxPreferredCodeAlignment >= kObjectAlignment);
-  stream_.Print(".balign %" Pd ", 0\n", OS::kMaxPreferredCodeAlignment);
+  assembly_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);
+    assembly_stream_.Print("Precompiled_Obj_%d:\n", i);
 
     NoSafepointScope no_safepoint;
     uword start = reinterpret_cast<uword>(obj.raw()) - kHeapObjectTag;
@@ -1306,6 +1316,84 @@
 }
 
 
+void BlobInstructionsWriter::Write() {
+  Zone* zone = Thread::Current()->zone();
+
+  // Handlify collected raw pointers as building the names below
+  // will allocate on the Dart heap.
+  for (intptr_t i = 0; i < instructions_.length(); i++) {
+    InstructionsData& data = instructions_[i];
+    data.insns_ = &Instructions::Handle(zone, data.raw_insns_);
+    ASSERT(data.raw_code_ != NULL);
+    data.code_ = &Code::Handle(zone, data.raw_code_);
+  }
+  for (intptr_t i = 0; i < objects_.length(); i++) {
+    ObjectData& data = objects_[i];
+    data.obj_ = &Object::Handle(zone, data.raw_obj_);
+  }
+
+  // This head also provides the gap to make the instructions snapshot
+  // look like a HeapPage.
+  intptr_t instructions_length = next_offset_;
+  instructions_blob_stream_.WriteWord(instructions_length);
+  intptr_t header_words = InstructionsSnapshot::kHeaderSize / sizeof(uword);
+  for (intptr_t i = 1; i < header_words; i++) {
+    instructions_blob_stream_.WriteWord(0);
+  }
+
+  for (intptr_t i = 0; i < instructions_.length(); i++) {
+    const Instructions& insns = *instructions_[i].insns_;
+
+    {
+      // 2. Write from the entry point to the end.
+      NoSafepointScope no_safepoint;
+      uword beginning = reinterpret_cast<uword>(insns.raw()) - kHeapObjectTag;
+      uword entry = beginning + Instructions::HeaderSize();
+      uword payload_size = insns.size();
+      payload_size = Utils::RoundUp(payload_size, OS::PreferredCodeAlignment());
+      uword end = entry + payload_size;
+
+      ASSERT(Utils::IsAligned(beginning, sizeof(uint64_t)));
+      ASSERT(Utils::IsAligned(entry, sizeof(uint64_t)));
+      ASSERT(Utils::IsAligned(end, sizeof(uint64_t)));
+
+      for (uword* cursor = reinterpret_cast<uword*>(entry);
+           cursor < reinterpret_cast<uword*>(end);
+           cursor++) {
+        instructions_blob_stream_.WriteWord(*cursor);
+      }
+    }
+  }
+
+  rodata_blob_stream_.WriteWord(next_object_offset_);  // Data length.
+  COMPILE_ASSERT(OS::kMaxPreferredCodeAlignment >= kObjectAlignment);
+  while (!Utils::IsAligned(rodata_blob_stream_.bytes_written(),
+                           OS::kMaxPreferredCodeAlignment)) {
+    rodata_blob_stream_.WriteWord(0);
+  }
+
+  for (intptr_t i = 0; i < objects_.length(); i++) {
+    const Object& obj = *objects_[i].obj_;
+
+    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);
+    rodata_blob_stream_.WriteWord(marked_tags);
+    start += sizeof(uword);
+    for (uword* cursor = reinterpret_cast<uword*>(start);
+         cursor < reinterpret_cast<uword*>(end);
+         cursor++) {
+      rodata_blob_stream_.WriteWord(*cursor);
+    }
+  }
+}
+
+
 uword InstructionsReader::GetInstructionsAt(int32_t offset) {
   ASSERT(Utils::IsAligned(offset, OS::PreferredCodeAlignment()));
   return reinterpret_cast<uword>(instructions_buffer_) + offset;
@@ -1875,20 +1963,18 @@
 
 FullSnapshotWriter::FullSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer,
                                        uint8_t** isolate_snapshot_buffer,
-                                       uint8_t** instructions_snapshot_buffer,
                                        ReAlloc alloc,
+                                       InstructionsWriter* instructions_writer,
                                        bool snapshot_code,
                                        bool vm_isolate_is_symbolic)
     : thread_(Thread::Current()),
       vm_isolate_snapshot_buffer_(vm_isolate_snapshot_buffer),
       isolate_snapshot_buffer_(isolate_snapshot_buffer),
-      instructions_snapshot_buffer_(instructions_snapshot_buffer),
       alloc_(alloc),
       vm_isolate_snapshot_size_(0),
       isolate_snapshot_size_(0),
-      instructions_snapshot_size_(0),
       forward_list_(NULL),
-      instructions_writer_(NULL),
+      instructions_writer_(instructions_writer),
       scripts_(Array::Handle(zone())),
       symbol_table_(Array::Handle(zone())),
       snapshot_code_(snapshot_code),
@@ -1927,12 +2013,6 @@
 
   forward_list_ = new ForwardList(thread(), SnapshotWriter::FirstObjectId());
   ASSERT(forward_list_ != NULL);
-
-  if (instructions_snapshot_buffer != NULL) {
-    instructions_writer_ = new InstructionsWriter(instructions_snapshot_buffer,
-                                                  alloc,
-                                                  kInitialSize);
-  }
 }
 
 
@@ -2051,8 +2131,7 @@
   }
   WriteIsolateFullSnapshot();
   if (snapshot_code_) {
-    instructions_writer_->WriteAssembly();
-    instructions_snapshot_size_ = instructions_writer_->BytesWritten();
+    instructions_writer_->Write();
 
     OS::Print("VMIsolate(CodeSize): %" Pd "\n", VmIsolateSnapshotSize());
     OS::Print("Isolate(CodeSize): %" Pd "\n", IsolateSnapshotSize());
@@ -2069,12 +2148,12 @@
 PrecompiledSnapshotWriter::PrecompiledSnapshotWriter(
     uint8_t** vm_isolate_snapshot_buffer,
     uint8_t** isolate_snapshot_buffer,
-    uint8_t** instructions_snapshot_buffer,
-    ReAlloc alloc)
+    ReAlloc alloc,
+    InstructionsWriter* instructions_writer)
   : FullSnapshotWriter(vm_isolate_snapshot_buffer,
                        isolate_snapshot_buffer,
-                       instructions_snapshot_buffer,
                        alloc,
+                       instructions_writer,
                        true, /* snapshot_code */
                        false /* vm_isolate_is_symbolic */) {
 }
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 25dab12..f9822b8 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -844,31 +844,22 @@
 
 class InstructionsWriter : public ZoneAllocated {
  public:
-  InstructionsWriter(uint8_t** buffer,
-                     ReAlloc alloc,
-                     intptr_t initial_size)
-    : stream_(buffer, alloc, initial_size),
-      next_offset_(InstructionsSnapshot::kHeaderSize),
+  InstructionsWriter()
+    : next_offset_(InstructionsSnapshot::kHeaderSize),
       next_object_offset_(DataSnapshot::kHeaderSize),
-      binary_size_(0),
       instructions_(),
       objects_() {
-    ASSERT(buffer != NULL);
-    ASSERT(alloc != NULL);
   }
-
-  // Size of the snapshot (assembly code).
-  intptr_t BytesWritten() const { return stream_.bytes_written(); }
-
-  intptr_t binary_size() { return binary_size_; }
+  virtual ~InstructionsWriter() { }
 
   int32_t GetOffsetFor(RawInstructions* instructions, RawCode* code);
 
   int32_t GetObjectOffsetFor(RawObject* raw_object);
 
-  void WriteAssembly();
+  virtual void Write() = 0;
+  virtual intptr_t binary_size() = 0;
 
- private:
+ protected:
   struct InstructionsData {
     explicit InstructionsData(RawInstructions* insns,
                               RawCode* code,
@@ -896,24 +887,76 @@
     };
   };
 
+  intptr_t next_offset_;
+  intptr_t next_object_offset_;
+  GrowableArray<InstructionsData> instructions_;
+  GrowableArray<ObjectData> objects_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(InstructionsWriter);
+};
+
+
+class AssemblyInstructionsWriter : public InstructionsWriter {
+ public:
+  AssemblyInstructionsWriter(uint8_t** assembly_buffer,
+                             ReAlloc alloc,
+                             intptr_t initial_size)
+    : InstructionsWriter(),
+      assembly_stream_(assembly_buffer, alloc, initial_size) {
+  }
+
+  virtual void Write();
+  virtual intptr_t binary_size() { return binary_size_; }
+
+  intptr_t AssemblySize() const { return assembly_stream_.bytes_written(); }
+
+ private:
   void WriteWordLiteral(uword value) {
     // Padding is helpful for comparing the .S with --disassemble.
 #if defined(ARCH_IS_64_BIT)
-    stream_.Print(".quad 0x%0.16" Px "\n", value);
+    assembly_stream_.Print(".quad 0x%0.16" Px "\n", value);
 #else
-    stream_.Print(".long 0x%0.8" Px "\n", value);
+    assembly_stream_.Print(".long 0x%0.8" Px "\n", value);
 #endif
     binary_size_ += sizeof(value);
   }
 
-  WriteStream stream_;
-  intptr_t next_offset_;
-  intptr_t next_object_offset_;
+  WriteStream assembly_stream_;
   intptr_t binary_size_;
-  GrowableArray<InstructionsData> instructions_;
-  GrowableArray<ObjectData> objects_;
 
-  DISALLOW_COPY_AND_ASSIGN(InstructionsWriter);
+  DISALLOW_COPY_AND_ASSIGN(AssemblyInstructionsWriter);
+};
+
+
+class BlobInstructionsWriter : public InstructionsWriter {
+ public:
+  BlobInstructionsWriter(uint8_t** instructions_blob_buffer,
+                         uint8_t** rodata_blob_buffer,
+                         ReAlloc alloc,
+                         intptr_t initial_size)
+    : InstructionsWriter(),
+      instructions_blob_stream_(instructions_blob_buffer, alloc, initial_size),
+      rodata_blob_stream_(rodata_blob_buffer, alloc, initial_size) {
+  }
+
+  virtual void Write();
+  virtual intptr_t binary_size() {
+    return InstructionsBlobSize() + RodataBlobSize();
+  }
+
+  intptr_t InstructionsBlobSize() const {
+    return instructions_blob_stream_.bytes_written();
+  }
+  intptr_t RodataBlobSize() const {
+    return rodata_blob_stream_.bytes_written();
+  }
+
+ private:
+  WriteStream instructions_blob_stream_;
+  WriteStream rodata_blob_stream_;
+
+  DISALLOW_COPY_AND_ASSIGN(BlobInstructionsWriter);
 };
 
 
@@ -1070,8 +1113,8 @@
   static const intptr_t kInitialSize = 64 * KB;
   FullSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer,
                      uint8_t** isolate_snapshot_buffer,
-                     uint8_t** instructions_snapshot_buffer,
                      ReAlloc alloc,
+                     InstructionsWriter* instructions_writer,
                      bool snapshot_code,
                      bool vm_isolate_is_symbolic);
   ~FullSnapshotWriter();
@@ -1098,9 +1141,6 @@
   intptr_t IsolateSnapshotSize() const {
     return isolate_snapshot_size_;
   }
-  intptr_t InstructionsSnapshotSize() const {
-    return instructions_snapshot_size_;
-  }
 
  private:
   // Writes a snapshot of the VM Isolate.
@@ -1112,11 +1152,9 @@
   Thread* thread_;
   uint8_t** vm_isolate_snapshot_buffer_;
   uint8_t** isolate_snapshot_buffer_;
-  uint8_t** instructions_snapshot_buffer_;
   ReAlloc alloc_;
   intptr_t vm_isolate_snapshot_size_;
   intptr_t isolate_snapshot_size_;
-  intptr_t instructions_snapshot_size_;
   ForwardList* forward_list_;
   InstructionsWriter* instructions_writer_;
   Array& scripts_;
@@ -1132,8 +1170,8 @@
  public:
   PrecompiledSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer,
                             uint8_t** isolate_snapshot_buffer,
-                            uint8_t** instructions_snapshot_buffer,
-                            ReAlloc alloc);
+                            ReAlloc alloc,
+                            InstructionsWriter* instructions_writer);
   ~PrecompiledSnapshotWriter();
 };
 
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 573addf..bf15a61 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -1186,8 +1186,8 @@
     {
       FullSnapshotWriter writer(NULL,
                                 &isolate_snapshot_buffer,
-                                NULL, /* instructions_snapshot_buffer */
                                 &malloc_allocator,
+                                NULL, /* instructions_writer */
                                 false, /* snapshot_code */
                                 true);
       writer.WriteFullSnapshot();
@@ -1247,8 +1247,8 @@
     {
       FullSnapshotWriter writer(NULL,
                                 &isolate_snapshot_buffer,
-                                NULL, /* instructions_snapshot_buffer */
                                 &malloc_allocator,
+                                NULL, /* instructions_writer */
                                 false, /* snapshot_code */
                                 true /* vm_isolate_is_symbolic */);
       writer.WriteFullSnapshot();
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index ebfe69e..aac196b 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -69,6 +69,7 @@
 
 
 void EntryFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) {
+#if !defined(TARGET_ARCH_DBC)
   ASSERT(thread() == Thread::Current());
   // Visit objects between SP and (FP - callee_save_area).
   ASSERT(visitor != NULL);
@@ -76,10 +77,17 @@
   RawObject** last = reinterpret_cast<RawObject**>(
       fp() + (kExitLinkSlotFromEntryFp - 1) * kWordSize);
   visitor->VisitPointers(first, last);
+#else
+  // On DBC stack is growing upwards which implies fp() <= sp().
+  RawObject** first = reinterpret_cast<RawObject**>(fp());
+  RawObject** last = reinterpret_cast<RawObject**>(sp());
+  visitor->VisitPointers(first, last);
+#endif
 }
 
 
 void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) {
+#if !defined(TARGET_ARCH_DBC)
   // NOTE: This code runs while GC is in progress and runs within
   // a NoHandleScope block. Hence it is not ok to use regular Zone or
   // Scope handles. We use direct stack handles, the raw pointers in
@@ -159,6 +167,13 @@
   RawObject** last = reinterpret_cast<RawObject**>(
       fp() + (kFirstObjectSlotFromFp * kWordSize));
   visitor->VisitPointers(first, last);
+#else
+  // On DBC stack grows upwards: fp() <= sp().
+  RawObject** first = reinterpret_cast<RawObject**>(
+      fp() + (kFirstObjectSlotFromFp * kWordSize));
+  RawObject** last = reinterpret_cast<RawObject**>(sp());
+  visitor->VisitPointers(first, last);
+#endif  // !defined(TARGET_ARCH_DBC)
 }
 
 
@@ -319,6 +334,7 @@
 }
 
 
+#if !defined(TARGET_ARCH_DBC)
 StackFrameIterator::StackFrameIterator(uword fp, uword sp, uword pc,
                                        bool validate, Thread* thread)
     : validate_(validate),
@@ -333,6 +349,7 @@
   frames_.sp_ = sp;
   frames_.pc_ = pc;
 }
+#endif
 
 
 StackFrame* StackFrameIterator::NextFrame() {
@@ -353,6 +370,7 @@
       return NULL;
     }
     UnpoisonStack(frames_.fp_);
+#if !defined(TARGET_ARCH_DBC)
     if (frames_.pc_ == 0) {
       // Iteration starts from an exit frame given by its fp.
       current_frame_ = NextExitFrame();
@@ -364,6 +382,12 @@
       // Iteration starts from a Dart or stub frame given by its fp, sp, and pc.
       current_frame_ = frames_.NextFrame(validate_);
     }
+#else
+    // Iteration starts from an exit frame given by its fp. This is the only
+    // mode supported on DBC.
+    ASSERT(frames_.pc_ == 0);
+    current_frame_ = NextExitFrame();
+#endif  // !defined(TARGET_ARCH_DBC)
     return current_frame_;
   }
   ASSERT((validate_ == kDontValidateFrames) || current_frame_->IsValid());
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index 2d1b12c..dac3e5f 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -19,6 +19,8 @@
 #include "vm/stack_frame_arm64.h"
 #elif defined(TARGET_ARCH_MIPS)
 #include "vm/stack_frame_mips.h"
+#elif defined(TARGET_ARCH_DBC)
+#include "vm/stack_frame_dbc.h"
 #else
 #error Unknown architecture.
 #endif
@@ -101,10 +103,12 @@
   uword GetCallerSp() const {
     return fp() + (kCallerSpSlotFromFp * kWordSize);
   }
+
   uword GetCallerFp() const {
     return *(reinterpret_cast<uword*>(
-        fp() + (kSavedCallerFpSlotFromFp * kWordSize)));
+      fp() + (kSavedCallerFpSlotFromFp * kWordSize)));
   }
+
   uword GetCallerPc() const {
     return *(reinterpret_cast<uword*>(
         fp() + (kSavedCallerPcSlotFromFp * kWordSize)));
@@ -188,10 +192,12 @@
   StackFrameIterator(uword last_fp, bool validate,
                      Thread* thread = Thread::Current());
 
+#if !defined(TARGET_ARCH_DBC)
   // Iterator for iterating over all frames from the current frame (given by its
   // fp, sp, and pc) to the first EntryFrame.
   StackFrameIterator(uword fp, uword sp, uword pc, bool validate,
                      Thread* thread = Thread::Current());
+#endif
 
   // Checks if a next frame exists.
   bool HasNextFrame() const { return frames_.fp_ != 0; }
@@ -272,6 +278,8 @@
   DartFrameIterator(uword last_fp,
                     Thread* thread = Thread::Current())
       : frames_(last_fp, StackFrameIterator::kDontValidateFrames, thread) { }
+
+#if !defined(TARGET_ARCH_DBC)
   DartFrameIterator(uword fp,
                     uword sp,
                     uword pc,
@@ -279,6 +287,8 @@
       : frames_(fp, sp, pc,
                 StackFrameIterator::kDontValidateFrames, thread) {
   }
+#endif
+
   // Get next dart frame.
   StackFrame* NextFrame() {
     StackFrame* frame = frames_.NextFrame();
@@ -336,6 +346,27 @@
   DISALLOW_COPY_AND_ASSIGN(InlinedFunctionsIterator);
 };
 
+#if !defined(TARGET_ARCH_DBC)
+DART_FORCE_INLINE static uword LocalVarAddress(uword fp, intptr_t index) {
+  return fp + (index * kWordSize);
+}
+
+
+DART_FORCE_INLINE static uword ParamAddress(uword fp, intptr_t reverse_index) {
+  return fp + (kParamEndSlotFromFp * kWordSize) + (reverse_index * kWordSize);
+}
+
+
+DART_FORCE_INLINE static bool IsCalleeFrameOf(uword fp, uword other_fp) {
+  return other_fp < fp;
+}
+
+// Value for stack limit that is used to cause an interrupt.
+// Note that on DBC stack is growing upwards so interrupt limit is 0 unlike
+// on all other architectures.
+static const uword kInterruptStackLimit = ~static_cast<uword>(0);
+#endif
+
 }  // namespace dart
 
 #endif  // VM_STACK_FRAME_H_
diff --git a/runtime/vm/stack_frame_dbc.h b/runtime/vm/stack_frame_dbc.h
new file mode 100644
index 0000000..a59a417
--- /dev/null
+++ b/runtime/vm/stack_frame_dbc.h
@@ -0,0 +1,85 @@
+// 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.
+
+#ifndef VM_STACK_FRAME_DBC_H_
+#define VM_STACK_FRAME_DBC_H_
+
+namespace dart {
+
+/* DBC Frame Layout
+
+IMPORTANT: On DBC stack is growing upwards which is different from all other
+architectures. This enables effecient addressing for locals via unsigned index.
+
+               |                    | <- TOS
+Callee frame   | ...                |
+               | saved FP           |    (FP of current frame)
+               | saved PC           |    (PC of current frame)
+               | code object        |
+               | function object    |
+               +--------------------+
+Current frame  | ...               T| <- SP of current frame
+               | ...               T|
+               | first local       T| <- FP of current frame
+               | caller's FP       *|
+               | caller's PC       *|
+               | code object       T|    (current frame's code object)
+               | function object   T|    (current frame's function object)
+               +--------------------+
+Caller frame   | last parameter     | <- SP of caller frame
+               |  ...               |
+
+               T against a slot indicates it needs to be traversed during GC.
+               * against a slot indicates that it can be traversed during GC
+                 because it will look like a smi to the visitor.
+*/
+
+static const int kDartFrameFixedSize = 4;  // Function, Code, PC, FP
+static const int kSavedPcSlotFromSp = 3;
+
+static const int kFirstObjectSlotFromFp = -4;  // Used by GC to traverse stack.
+
+static const int kSavedCallerFpSlotFromFp = -1;
+static const int kSavedCallerPpSlotFromFp = kSavedCallerFpSlotFromFp;
+static const int kSavedCallerPcSlotFromFp = -2;
+static const int kCallerSpSlotFromFp = -kDartFrameFixedSize-1;
+static const int kPcMarkerSlotFromFp = -3;
+static const int kFunctionSlotFromFp = -4;
+
+// Note: These constants don't match actual DBC behavior. This is done because
+// setting kFirstLocalSlotFromFp to 0 breaks assumptions spread across the code.
+// Instead for the purposes of local variable allocation we pretend that DBC
+// behaves as other architectures (stack growing downwards) and later fix
+// these indices during code generation in the backend.
+static const int kParamEndSlotFromFp = 4;  // One slot past last parameter.
+static const int kFirstLocalSlotFromFp = -1;
+
+
+DART_FORCE_INLINE static uword LocalVarAddress(uword fp, intptr_t index) {
+  ASSERT(index != 0);
+  if (index > 0) {
+     return fp - index * kWordSize;
+  } else {
+     return fp - (index + 1) * kWordSize;
+  }
+}
+
+DART_FORCE_INLINE static uword ParamAddress(uword fp, intptr_t reverse_index) {
+  return fp - (kDartFrameFixedSize + reverse_index) * kWordSize;
+}
+
+DART_FORCE_INLINE static bool IsCalleeFrameOf(uword fp, uword other_fp) {
+  return other_fp > fp;
+}
+
+static const int kExitLinkSlotFromEntryFp = 0;
+
+// Value for stack limit that is used to cause an interrupt.
+// Note that on DBC stack is growing upwards so interrupt limit is 0 unlike
+// on all other architectures.
+static const uword kInterruptStackLimit = 0;
+
+}  // namespace dart
+
+#endif  // VM_STACK_FRAME_DBC_H_
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index 6738a25..04ca4f4 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -85,30 +85,47 @@
 
 
 bool StubCode::HasBeenInitialized() {
+#if !defined(TARGET_ARCH_DBC)
   // Use JumpToExceptionHandler and InvokeDart as canaries.
   const StubEntry* entry_1 = StubCode::JumpToExceptionHandler_entry();
   const StubEntry* entry_2 = StubCode::InvokeDartCode_entry();
   return (entry_1 != NULL) && (entry_2 != NULL);
+#else
+  return true;
+#endif
 }
 
 
 bool StubCode::InInvocationStub(uword pc) {
+#if !defined(TARGET_ARCH_DBC)
   ASSERT(HasBeenInitialized());
   uword entry = StubCode::InvokeDartCode_entry()->EntryPoint();
   uword size = StubCode::InvokeDartCodeSize();
   return (pc >= entry) && (pc < (entry + size));
+#else
+  // On DBC we use a special marker PC to signify entry frame because there is
+  // no such thing as invocation stub.
+  return (pc & 2) != 0;
+#endif
 }
 
 
 bool StubCode::InJumpToExceptionHandlerStub(uword pc) {
+#if !defined(TARGET_ARCH_DBC)
   ASSERT(HasBeenInitialized());
   uword entry = StubCode::JumpToExceptionHandler_entry()->EntryPoint();
   uword size = StubCode::JumpToExceptionHandlerSize();
   return (pc >= entry) && (pc < (entry + size));
+#else
+  // This stub does not exist on DBC.
+  return false;
+#endif
 }
 
 
 RawCode* StubCode::GetAllocationStubForClass(const Class& cls) {
+  // These stubs are not used by DBC.
+#if !defined(TARGET_ARCH_DBC)
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   const Error& error = Error::Handle(zone, cls.EnsureIsFinalized(thread));
@@ -169,11 +186,16 @@
     }
   }
   return stub.raw();
+#endif
+  UNIMPLEMENTED();
+  return Code::null();
 }
 
 
 const StubEntry* StubCode::UnoptimizedStaticCallEntry(
     intptr_t num_args_tested) {
+  // These stubs are not used by DBC.
+#if !defined(TARGET_ARCH_DBC)
   switch (num_args_tested) {
     case 0:
       return ZeroArgsUnoptimizedStaticCall_entry();
@@ -185,6 +207,9 @@
       UNIMPLEMENTED();
       return NULL;
   }
+#else
+  return NULL;
+#endif
 }
 
 
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index fed306b..aa20321 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -18,9 +18,9 @@
 class SnapshotReader;
 class SnapshotWriter;
 
-
 // List of stubs created in the VM isolate, these stubs are shared by different
 // isolates running in this dart process.
+#if !defined(TARGET_ARCH_DBC)
 #define VM_STUB_CODE_LIST(V)                                                   \
   V(GetStackPointer)                                                           \
   V(JumpToExceptionHandler)                                                    \
@@ -65,6 +65,13 @@
   V(CallClosureNoSuchMethod)                                                   \
   V(FrameAwaitingMaterialization)                                              \
 
+#else
+#define VM_STUB_CODE_LIST(V)                                                   \
+  V(LazyCompile)                                                               \
+  V(FixCallersTarget)                                                          \
+
+#endif  // !defined(TARGET_ARCH_DBC)
+
 // Is it permitted for the stubs above to refer to Object::null(), which is
 // allocated in the VM isolate and shared across all isolates.
 // However, in cases where a simple GC-safe placeholder is needed on the stack,
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index e5a03c7..8e85852 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -625,8 +625,7 @@
   __ b(&slow_case, GT);
 
   const intptr_t cid = kArrayCid;
-  __ MaybeTraceAllocation(cid, R4, &slow_case,
-                          /* inline_isolate = */ false);
+  __ MaybeTraceAllocation(cid, R4, &slow_case);
 
   const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
   __ LoadImmediate(R9, fixed_size);
@@ -653,7 +652,7 @@
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ LoadAllocationStatsAddress(R3, cid, /* inline_isolate = */ false);
+  __ LoadAllocationStatsAddress(R3, cid);
   __ str(NOTFP, Address(R8, Heap::TopOffset(space)));
   __ add(R0, R0, Operand(kHeapObjectTag));
 
@@ -859,8 +858,7 @@
     ASSERT(kSmiTagShift == 1);
     __ bic(R2, R2, Operand(kObjectAlignment - 1));
 
-    __ MaybeTraceAllocation(kContextCid, R8, &slow_case,
-                            /* inline_isolate = */ false);
+    __ MaybeTraceAllocation(kContextCid, R8, &slow_case);
     // Now allocate the object.
     // R1: number of context variables.
     // R2: object size.
@@ -891,7 +889,7 @@
     // R2: object size.
     // R3: next object start.
     // R9: heap.
-    __ LoadAllocationStatsAddress(R4, cid, /* inline_isolate = */ false);
+    __ LoadAllocationStatsAddress(R4, cid);
     __ str(R3, Address(R9, Heap::TopOffset(space)));
     __ add(R0, R0, Operand(kHeapObjectTag));
 
@@ -1083,7 +1081,7 @@
 
     // Load the address of the allocation stats table. We split up the load
     // and the increment so that the dependent load is not too nearby.
-    __ LoadAllocationStatsAddress(R9, cls.id(), /* inline_isolate = */ false);
+    __ LoadAllocationStatsAddress(R9, cls.id());
 
     // R0: new object start.
     // R1: next object start.
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index bddf296..cb31d8e 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -652,8 +652,7 @@
   __ b(&slow_case, GT);
 
   const intptr_t cid = kArrayCid;
-  __ MaybeTraceAllocation(kArrayCid, R4, &slow_case,
-                          /* inline_isolate = */ false);
+  __ MaybeTraceAllocation(kArrayCid, R4, &slow_case);
 
   Heap::Space space = Heap::SpaceForAllocation(cid);
   __ LoadIsolate(R8);
@@ -694,8 +693,7 @@
   // R8: heap.
   __ StoreToOffset(R7, R8, Heap::TopOffset(space));
   __ add(R0, R0, Operand(kHeapObjectTag));
-  __ UpdateAllocationStatsWithSize(cid, R3, space,
-                                   /* inline_isolate = */ false);
+  __ UpdateAllocationStatsWithSize(cid, R3, space);
 
   // R0: new object start as a tagged pointer.
   // R1: array element type.
@@ -919,8 +917,7 @@
     ASSERT(kSmiTagShift == 1);
     __ andi(R2, R2, Immediate(~(kObjectAlignment - 1)));
 
-    __ MaybeTraceAllocation(kContextCid, R4, &slow_case,
-                            /* inline_isolate = */ false);
+    __ MaybeTraceAllocation(kContextCid, R4, &slow_case);
     // Now allocate the object.
     // R1: number of context variables.
     // R2: object size.
@@ -953,8 +950,7 @@
     // R5: heap.
     __ str(R3, Address(R5, Heap::TopOffset(space)));
     __ add(R0, R0, Operand(kHeapObjectTag));
-    __ UpdateAllocationStatsWithSize(cid, R2, space,
-                                     /* inline_isolate = */ false);
+    __ UpdateAllocationStatsWithSize(cid, R2, space);
 
     // Calculate the size tag.
     // R0: new object.
@@ -1128,7 +1124,7 @@
       __ b(&slow_case, CS);  // Unsigned higher or equal.
     }
     __ str(R3, Address(R5, Heap::TopOffset(space)));
-    __ UpdateAllocationStats(cls.id(), space, /* inline_isolate = */ false);
+    __ UpdateAllocationStats(cls.id(), space);
 
     // R2: new object start.
     // R3: next object start.
diff --git a/runtime/vm/stub_code_dbc.cc b/runtime/vm/stub_code_dbc.cc
new file mode 100644
index 0000000..0042f2d
--- /dev/null
+++ b/runtime/vm/stub_code_dbc.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h"
+#if defined(TARGET_ARCH_DBC)
+
+#include "vm/assembler.h"
+#include "vm/code_generator.h"
+#include "vm/cpu.h"
+#include "vm/compiler.h"
+#include "vm/dart_entry.h"
+#include "vm/flow_graph_compiler.h"
+#include "vm/heap.h"
+#include "vm/instructions.h"
+#include "vm/object_store.h"
+#include "vm/stack_frame.h"
+#include "vm/stub_code.h"
+#include "vm/tags.h"
+
+#define __ assembler->
+
+namespace dart {
+
+DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects.");
+DEFINE_FLAG(bool, use_slow_path, false,
+    "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);
+
+void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
+  __ Compile();
+}
+
+
+// TODO(vegorov) Don't generate this stub.
+void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
+  __ Trap();
+}
+
+
+// TODO(vegorov) Don't generate these stubs.
+void StubCode::GenerateAllocationStubForClass(Assembler* assembler,
+                                              const Class& cls) {
+  __ Trap();
+}
+
+
+// TODO(vegorov) Don't generate this stub.
+void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
+  __ Trap();
+}
+
+
+// Print the stop message.
+DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, 1, const char* message) {
+  OS::Print("Stop message: %s\n", message);
+}
+END_LEAF_RUNTIME_ENTRY
+
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 2a4ed9b..772e39b 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -564,8 +564,7 @@
   __ MaybeTraceAllocation(kArrayCid,
                           EAX,
                           &slow_case,
-                          Assembler::kFarJump,
-                          /* inline_isolate = */ false);
+                          Assembler::kFarJump);
 
   const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
   __ leal(EBX, Address(EDX, TIMES_2, fixed_size));  // EDX is Smi.
@@ -597,8 +596,7 @@
   __ movl(Address(EDI, Heap::TopOffset(space)), EBX);
   __ subl(EBX, EAX);
   __ addl(EAX, Immediate(kHeapObjectTag));
-  __ UpdateAllocationStatsWithSize(cid, EBX, EDI, space,
-                                   /* inline_isolate = */ false);
+  __ UpdateAllocationStatsWithSize(cid, EBX, EDI, space);
 
   // Initialize the tags.
   // EAX: new object start as a tagged pointer.
@@ -803,8 +801,7 @@
     __ MaybeTraceAllocation(kContextCid,
                             EAX,
                             &slow_case,
-                            Assembler::kFarJump,
-                            /* inline_isolate = */ false);
+                            Assembler::kFarJump);
 
     // Now allocate the object.
     // EDX: number of context variables.
@@ -839,8 +836,7 @@
     __ subl(EBX, EAX);
     __ addl(EAX, Immediate(kHeapObjectTag));
     // Generate isolate-independent code to allow sharing between isolates.
-    __ UpdateAllocationStatsWithSize(cid, EBX, EDI, space,
-                                     /* inline_isolate = */ false);
+    __ UpdateAllocationStatsWithSize(cid, EBX, EDI, space);
 
     // Calculate the size tag.
     // EAX: new object.
@@ -1037,8 +1033,7 @@
       __ j(ABOVE_EQUAL, &slow_case);
     }
     __ movl(Address(EDI, Heap::TopOffset(space)), EBX);
-    __ UpdateAllocationStats(cls.id(), ECX, space,
-                             /* inline_isolate = */ false);
+    __ UpdateAllocationStats(cls.id(), ECX, space);
 
     // EAX: new object start (untagged).
     // EBX: next object start.
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index 7ae26bb..ce5db80 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -656,8 +656,7 @@
   __ BranchUnsignedGreater(T3, Immediate(max_len), &slow_case);
 
   const intptr_t cid = kArrayCid;
-  __ MaybeTraceAllocation(kArrayCid, T4, &slow_case,
-                          /* inline_isolate = */ false);
+  __ MaybeTraceAllocation(kArrayCid, T4, &slow_case);
 
   const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
   __ LoadImmediate(T2, fixed_size);
@@ -691,8 +690,7 @@
   // T3: heap.
   __ sw(T1, Address(T3, Heap::TopOffset(space)));
   __ addiu(T0, T0, Immediate(kHeapObjectTag));
-  __ UpdateAllocationStatsWithSize(cid, T2, T4, space,
-                                   /* inline_isolate = */ false);
+  __ UpdateAllocationStatsWithSize(cid, T2, T4, space);
 
   // Initialize the tags.
   // T0: new object start as a tagged pointer.
@@ -937,8 +935,7 @@
     __ LoadImmediate(T0, ~((kObjectAlignment) - 1));
     __ and_(T2, T2, T0);
 
-    __ MaybeTraceAllocation(kContextCid, T4, &slow_case,
-                            /* inline_isolate = */ false);
+    __ MaybeTraceAllocation(kContextCid, T4, &slow_case);
     // Now allocate the object.
     // T1: number of context variables.
     // T2: object size.
@@ -971,8 +968,7 @@
     // T5: heap.
     __ sw(T3, Address(T5, Heap::TopOffset(space)));
     __ addiu(V0, V0, Immediate(kHeapObjectTag));
-    __ UpdateAllocationStatsWithSize(cid, T2, T5, space,
-                                     /* inline_isolate = */ false);
+    __ UpdateAllocationStatsWithSize(cid, T2, T5, space);
 
     // Calculate the size tag.
     // V0: new object.
@@ -1157,7 +1153,7 @@
     // Successfully allocated the object(s), now update top to point to
     // next object start and initialize the object.
     __ sw(T3, Address(T5, Heap::TopOffset(space)));
-    __ UpdateAllocationStats(cls.id(), T5, space, /* inline_isolate = */ false);
+    __ UpdateAllocationStats(cls.id(), T5, space);
 
     // T2: new object start.
     // T3: next object start.
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index db210a1..4e8f0e0 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -590,8 +590,7 @@
   // Check for allocation tracing.
   __ MaybeTraceAllocation(kArrayCid,
                           &slow_case,
-                          Assembler::kFarJump,
-                          /* inline_isolate = */ false);
+                          Assembler::kFarJump);
 
   const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
   __ leaq(RDI, Address(RDI, TIMES_4, fixed_size));  // RDI is a Smi.
@@ -620,8 +619,7 @@
   // next object start and initialize the object.
   __ movq(Address(R13, Heap::TopOffset(space)), RCX);
   __ addq(RAX, Immediate(kHeapObjectTag));
-  __ UpdateAllocationStatsWithSize(cid, RDI, space,
-                                   /* inline_isolate = */ false);
+  __ UpdateAllocationStatsWithSize(cid, RDI, space);
   // Initialize the tags.
   // RAX: new object start as a tagged pointer.
   // RDI: allocation size.
@@ -847,8 +845,7 @@
     // Check for allocation tracing.
     __ MaybeTraceAllocation(kContextCid,
                             &slow_case,
-                            Assembler::kFarJump,
-                            /* inline_isolate = */ false);
+                            Assembler::kFarJump);
 
     // Now allocate the object.
     // R10: number of context variables.
@@ -880,8 +877,7 @@
     __ subq(R13, RAX);
     __ addq(RAX, Immediate(kHeapObjectTag));
     // Generate isolate-independent code to allow sharing between isolates.
-    __ UpdateAllocationStatsWithSize(cid, R13, space,
-                                     /* inline_isolate */ false);
+    __ UpdateAllocationStatsWithSize(cid, R13, space);
 
     // Calculate the size tag.
     // RAX: new object.
@@ -1072,7 +1068,7 @@
       __ j(ABOVE_EQUAL, &slow_case);
     }
     __ movq(Address(RCX, Heap::TopOffset(space)), RBX);
-    __ UpdateAllocationStats(cls.id(), space, /* inline_isolate = */ false);
+    __ UpdateAllocationStats(cls.id(), space);
 
     // RAX: new object start (untagged).
     // RBX: next object start.
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index 5fb54bc..04d6088 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -148,6 +148,7 @@
 class SymbolTraits {
  public:
   static const char* Name() { return "SymbolTraits"; }
+  static bool ReportStats() { return false; }
 
   static bool IsMatch(const Object& a, const Object& b) {
     const String& a_str = String::Cast(a);
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index f20aa44..83c7458 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -352,7 +352,6 @@
   V(_LocalTypeVariableMirror, "_LocalTypeVariableMirror")                      \
   V(_SourceLocation, "_SourceLocation")                                        \
   V(hashCode, "get:hashCode")                                                  \
-  V(_leftShiftWithMask32, "_leftShiftWithMask32")                              \
   V(OptimizedOut, "<optimized out>")                                           \
   V(NotInitialized, "<not initialized>")                                       \
   V(AllocationStubFor, "[Stub] Allocate ")                                     \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 5775145..3c7efee 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -318,6 +318,7 @@
 
 void Thread::SetStackLimitFromStackBase(uword stack_base) {
   // Set stack limit.
+#if !defined(TARGET_ARCH_DBC)
 #if defined(USING_SIMULATOR)
   // Ignore passed-in native stack top and use Simulator stack top.
   Simulator* sim = Simulator::Current();  // May allocate a simulator.
@@ -326,6 +327,9 @@
   // The overflow area is accounted for by the simulator.
 #endif
   SetStackLimit(stack_base - OSThread::GetSpecifiedStackSize());
+#else
+  SetStackLimit(Simulator::Current()->StackTop());
+#endif  // !defined(TARGET_ARCH_DBC)
 }
 
 
@@ -348,11 +352,15 @@
 
 /* static */
 uword Thread::GetCurrentStackPointer() {
+#if !defined(TARGET_ARCH_DBC)
   // Since AddressSanitizer's detect_stack_use_after_return instruments the
   // C++ code to give out fake stack addresses, we call a stub in that case.
   ASSERT(StubCode::GetStackPointer_entry() != NULL);
   uword (*func)() = reinterpret_cast<uword (*)()>(
       StubCode::GetStackPointer_entry()->EntryPoint());
+#else
+  uword (*func)() = NULL;
+#endif
   // But for performance (and to support simulators), we normally use a local.
 #if defined(__has_feature)
 #if __has_feature(address_sanitizer)
@@ -390,7 +398,7 @@
   }
 
   if (stack_limit_ == saved_stack_limit_) {
-    stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask;
+    stack_limit_ = kInterruptStackLimit & ~kInterruptsMask;
   }
   stack_limit_ |= interrupt_bits;
 }
@@ -437,7 +445,7 @@
   deferred_interrupts_mask_ = 0;
   if (deferred_interrupts_ != 0) {
     if (stack_limit_ == saved_stack_limit_) {
-      stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask;
+      stack_limit_ = kInterruptStackLimit & ~kInterruptsMask;
     }
     stack_limit_ |= deferred_interrupts_;
     deferred_interrupts_ = 0;
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 8e126f5..4a21cc5 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -70,11 +70,10 @@
   V(TypeParameter)                                                             \
 
 
-// List of VM-global objects/addresses cached in each Thread object.
-#define CACHED_VM_OBJECTS_LIST(V)                                              \
-  V(RawObject*, object_null_, Object::null(), NULL)                            \
-  V(RawBool*, bool_true_, Object::bool_true().raw(), NULL)                     \
-  V(RawBool*, bool_false_, Object::bool_false().raw(), NULL)                   \
+#if defined(TARGET_ARCH_DBC)
+#define CACHED_VM_STUBS_LIST(V)
+#else
+#define CACHED_VM_STUBS_LIST(V)                                                \
   V(RawCode*, update_store_buffer_code_,                                       \
     StubCode::UpdateStoreBuffer_entry()->code(), NULL)                         \
   V(RawCode*, fix_callers_target_code_,                                        \
@@ -86,11 +85,28 @@
   V(RawCode*, call_to_runtime_stub_,                                           \
     StubCode::CallToRuntime_entry()->code(), NULL)                             \
 
-#define CACHED_ADDRESSES_LIST(V)                                               \
+#endif
+
+// List of VM-global objects/addresses cached in each Thread object.
+#define CACHED_VM_OBJECTS_LIST(V)                                              \
+  V(RawObject*, object_null_, Object::null(), NULL)                            \
+  V(RawBool*, bool_true_, Object::bool_true().raw(), NULL)                     \
+  V(RawBool*, bool_false_, Object::bool_false().raw(), NULL)                   \
+  CACHED_VM_STUBS_LIST(V)                                                      \
+
+#if defined(TARGET_ARCH_DBC)
+#define CACHED_VM_STUBS_ADDRESSES_LIST(V)
+#else
+#define CACHED_VM_STUBS_ADDRESSES_LIST(V)                                      \
   V(uword, update_store_buffer_entry_point_,                                   \
     StubCode::UpdateStoreBuffer_entry()->EntryPoint(), 0)                      \
   V(uword, call_to_runtime_entry_point_,                                       \
     StubCode::CallToRuntime_entry()->EntryPoint(), 0)                          \
+
+#endif
+
+#define CACHED_ADDRESSES_LIST(V)                                               \
+  CACHED_VM_STUBS_ADDRESSES_LIST(V)                                            \
   V(uword, native_call_wrapper_entry_point_,                                   \
     NativeEntry::NativeCallWrapperEntry(), 0)                                  \
   V(RawString**, predefined_symbols_address_,                                  \
@@ -175,6 +191,13 @@
   // The true stack limit for this isolate.
   uword saved_stack_limit() const { return saved_stack_limit_; }
 
+#if defined(TARGET_ARCH_DBC)
+  // Access to the current stack limit for DBC interpreter.
+  uword stack_limit() const {
+    return stack_limit_;
+  }
+#endif
+
   // Stack overflow flags
   enum {
     kOsrRequest = 0x1,  // Current stack overflow caused by OSR request.
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index 68e0784..0adf841 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -33,6 +33,9 @@
             "Comma separated list of timeline streams to record. "
             "Valid values: all, API, Compiler, Dart, Debugger, Embedder, "
             "GC, Isolate, and VM.");
+DEFINE_FLAG(charp, timeline_recorder, "ring",
+            "Select the timeline recorder used. "
+            "Valid values: ring, endless, and startup.")
 
 // Implementation notes:
 //
@@ -77,6 +80,42 @@
 //
 
 
+static TimelineEventRecorder* CreateTimelineRecorder() {
+  // Some flags require that we use the endless recorder.
+  const bool use_endless_recorder =
+      (FLAG_timeline_dir != NULL) || FLAG_timing || FLAG_complete_timeline;
+
+  const bool use_startup_recorder = FLAG_startup_timeline;
+
+  const char* flag = FLAG_timeline_recorder;
+
+  if (use_endless_recorder || (flag != NULL)) {
+    if (use_endless_recorder || (strcmp("endless", flag) == 0)) {
+      if (FLAG_trace_timeline) {
+        THR_Print("Using the endless timeline recorder.\n");
+      }
+      return new TimelineEventEndlessRecorder();
+    }
+  }
+
+  if (use_startup_recorder || (flag != NULL)) {
+    if (use_startup_recorder || (strcmp("startup", flag) == 0)) {
+      if (FLAG_trace_timeline) {
+        THR_Print("Using the startup recorder.\n");
+      }
+      return new TimelineEventStartupRecorder();
+    }
+  }
+
+  if (FLAG_trace_timeline) {
+    THR_Print("Using the ring timeline recorder.\n");
+  }
+
+  // Always fall back to the ring recorder.
+  return new TimelineEventRingRecorder();
+}
+
+
 // Returns a caller freed array of stream names in FLAG_timeline_streams.
 static MallocGrowableArray<char*>* GetEnabledByDefaultTimelineStreams() {
   MallocGrowableArray<char*>* result = new MallocGrowableArray<char*>();
@@ -129,18 +168,8 @@
 
 void Timeline::InitOnce() {
   ASSERT(recorder_ == NULL);
-  // Default to ring recorder being enabled.
-  const bool use_ring_recorder = true;
-  // Some flags require that we use the endless recorder.
-  const bool use_endless_recorder =
-      (FLAG_timeline_dir != NULL) || FLAG_timing || FLAG_complete_timeline;
-  if (use_endless_recorder) {
-    recorder_ = new TimelineEventEndlessRecorder();
-  } else if (FLAG_startup_timeline) {
-    recorder_ = new TimelineEventStartupRecorder();
-  } else if (use_ring_recorder) {
-    recorder_ = new TimelineEventRingRecorder();
-  }
+  recorder_ = CreateTimelineRecorder();
+  ASSERT(recorder_ != NULL);
   enabled_streams_ = GetEnabledByDefaultTimelineStreams();
   // Global overrides.
 #define TIMELINE_STREAM_FLAG_DEFAULT(name, not_used)                           \
@@ -295,6 +324,9 @@
 
 
 void TimelineEvent::Reset() {
+  if (owns_label() && label_ != NULL) {
+    free(const_cast<char*>(label_));
+  }
   state_ = 0;
   thread_ = OSThread::kInvalidThreadId;
   isolate_id_ = ILLEGAL_PORT;
@@ -303,6 +335,7 @@
   FreeArguments();
   set_pre_serialized_json(false);
   set_event_type(kNone);
+  set_owns_label(false);
 }
 
 
@@ -502,6 +535,7 @@
   FreeArguments();
   set_pre_serialized_json(false);
   set_event_type(event_type);
+  set_owns_label(false);
 }
 
 
@@ -1035,8 +1069,6 @@
   if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) {
     return;
   }
-  Thread* T = Thread::Current();
-  StackZone zone(T);
 
   Timeline::ReclaimCachedBlocksFromThreads();
 
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
index 9196ee0..f78b516 100644
--- a/runtime/vm/timeline.h
+++ b/runtime/vm/timeline.h
@@ -286,6 +286,10 @@
 
   const char* GetSerializedJSON() const;
 
+  void set_owns_label(bool owns_label) {
+    state_ = OwnsLabelBit::update(owns_label, state_);
+  }
+
  private:
   void FreeArguments();
 
@@ -315,15 +319,21 @@
     state_ = PreSerializedJSON::update(pre_serialized_json, state_);
   }
 
+  bool owns_label() const {
+    return OwnsLabelBit::decode(state_);
+  }
+
   enum StateBits {
     kEventTypeBit = 0,  // reserve 4 bits for type.
     kPreSerializedJSON = 4,
-    kNextBit = 5,
+    kOwnsLabelBit = 5,
+    kNextBit = 6,
   };
 
   class EventTypeField : public BitField<uword, EventType, kEventTypeBit, 4> {};
   class PreSerializedJSON :
       public BitField<uword, bool, kPreSerializedJSON, 1> {};
+  class OwnsLabelBit : public BitField<uword, bool, kOwnsLabelBit, 1> {};
 
   int64_t timestamp0_;
   int64_t timestamp1_;
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index defaea6..f170ffc 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -374,7 +374,7 @@
   // using the ABI calling convention.
   // ResultType is the return type of the assembler test function.
   // ArgNType is the type of the Nth argument.
-#if defined(USING_SIMULATOR)
+#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
 
 #if defined(ARCH_IS_64_BIT)
   // TODO(fschneider): Make InvokeWithCodeAndThread<> more general and work on
@@ -454,7 +454,7 @@
     typedef ResultType (*FunctionType) (Arg1Type, Arg2Type, Arg3Type);
     return reinterpret_cast<FunctionType>(entry())(arg1, arg2, arg3);
   }
-#endif  // USING_SIMULATOR
+#endif  // defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
 
   // Assemble test and set code_.
   void Assemble();
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index f73d16d..fa053a3 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -19,6 +19,8 @@
     'assembler_arm64.cc',
     'assembler_arm64.h',
     'assembler_arm64_test.cc',
+    'assembler_dbc.cc',
+    'assembler_dbc.h',
     'assembler_ia32.cc',
     'assembler_ia32.h',
     'assembler_ia32_test.cc',
@@ -89,6 +91,7 @@
     'code_patcher_arm_test.cc',
     'code_patcher_arm64.cc',
     'code_patcher_arm64_test.cc',
+    'code_patcher_dbc.cc',
     'code_patcher_ia32.cc',
     'code_patcher_ia32_test.cc',
     'code_patcher_mips.cc',
@@ -110,6 +113,7 @@
     'cpu.h',
     'cpu_arm.cc',
     'cpu_arm64.cc',
+    'cpu_dbc.cc',
     'cpu_ia32.cc',
     'cpu_mips.cc',
     'cpu_test.cc',
@@ -140,6 +144,7 @@
     'debugger_api_impl_test.cc',
     'debugger_arm.cc',
     'debugger_arm64.cc',
+    'debugger_dbc.cc',
     'debugger_ia32.cc',
     'debugger_mips.cc',
     'debugger_x64.cc',
@@ -151,6 +156,7 @@
     'disassembler.h',
     'disassembler_arm.cc',
     'disassembler_arm64.cc',
+    'disassembler_dbc.cc',
     'disassembler_ia32.cc',
     'disassembler_mips.cc',
     'disassembler_test.cc',
@@ -177,6 +183,7 @@
     'flow_graph_compiler.h',
     'flow_graph_compiler_arm.cc',
     'flow_graph_compiler_arm64.cc',
+    'flow_graph_compiler_dbc.cc',
     'flow_graph_compiler_ia32.cc',
     'flow_graph_compiler_mips.cc',
     'flow_graph_compiler_x64.cc',
@@ -218,6 +225,8 @@
     'instructions_arm64.cc',
     'instructions_arm64.h',
     'instructions_arm64_test.cc',
+    'instructions_dbc.cc',
+    'instructions_dbc.h',
     'instructions_ia32.cc',
     'instructions_ia32.h',
     'instructions_ia32_test.cc',
@@ -231,6 +240,7 @@
     'intermediate_language.h',
     'intermediate_language_arm.cc',
     'intermediate_language_arm64.cc',
+    'intermediate_language_dbc.cc',
     'intermediate_language_ia32.cc',
     'intermediate_language_mips.cc',
     'intermediate_language_test.cc',
@@ -239,6 +249,7 @@
     'intrinsifier.h',
     'intrinsifier_arm.cc',
     'intrinsifier_arm64.cc',
+    'intrinsifier_dbc.cc',
     'intrinsifier_ia32.cc',
     'intrinsifier_mips.cc',
     'intrinsifier_x64.cc',
@@ -377,6 +388,7 @@
     'runtime_entry_list.h',
     'runtime_entry_arm.cc',
     'runtime_entry_arm64.cc',
+    'runtime_entry_dbc.cc',
     'runtime_entry_ia32.cc',
     'runtime_entry_mips.cc',
     'runtime_entry.cc',
@@ -410,6 +422,8 @@
     'simulator_arm.h',
     'simulator_arm64.cc',
     'simulator_arm64.h',
+    'simulator_dbc.cc',
+    'simulator_dbc.h',
     'simulator_mips.cc',
     'simulator_mips.h',
     'snapshot.cc',
@@ -436,6 +450,7 @@
     'stub_code_arm_test.cc',
     'stub_code_arm64.cc',
     'stub_code_arm64_test.cc',
+    'stub_code_dbc.cc',
     'stub_code_ia32.cc',
     'stub_code_ia32_test.cc',
     'stub_code_mips.cc',
diff --git a/sdk/lib/_blink/dartium/_blink_dartium.dart b/sdk/lib/_blink/dartium/_blink_dartium.dart
index c0674f6..bb80827 100644
--- a/sdk/lib/_blink/dartium/_blink_dartium.dart
+++ b/sdk/lib/_blink/dartium/_blink_dartium.dart
@@ -347,7 +347,6 @@
   if (s == "MimeTypeArray") return BlinkMimeTypeArray.instance;
   if (s == "MouseEvent") return BlinkMouseEvent.instance;
   if (s == "MutationCallback") return BlinkMutationCallback.instance;
-  if (s == "MutationEvent") return BlinkMutationEvent.instance;
   if (s == "MutationObserver") return BlinkMutationObserver.instance;
   if (s == "MutationRecord") return BlinkMutationRecord.instance;
   if (s == "NamedNodeMap") return BlinkNamedNodeMap.instance;
@@ -10946,27 +10945,6 @@
 
 }
 
-class BlinkMutationEvent extends BlinkEvent {
-  static final instance = new BlinkMutationEvent();
-
-  attrChange_Getter_(mthis) => Blink_JsNative_DomException.getProperty(mthis /* MutationEvent */, "attrChange");
-
-  attrName_Getter_(mthis) => Blink_JsNative_DomException.getProperty(mthis /* MutationEvent */, "attrName");
-
-  newValue_Getter_(mthis) => Blink_JsNative_DomException.getProperty(mthis /* MutationEvent */, "newValue");
-
-  prevValue_Getter_(mthis) => Blink_JsNative_DomException.getProperty(mthis /* MutationEvent */, "prevValue");
-
-  relatedNode_Getter_(mthis) => Blink_JsNative_DomException.getProperty(mthis /* MutationEvent */, "relatedNode");
-
-  initMutationEvent_Callback_6_(mthis, __arg_0, __arg_1, __arg_2, __arg_3, __arg_4, __arg_5) => Blink_JsNative_DomException.callMethod(mthis /* MutationEvent */, "initMutationEvent", [__arg_0, __arg_1, __arg_2, __arg_3, __arg_4, __arg_5]);
-
-  initMutationEvent_Callback_7_(mthis, __arg_0, __arg_1, __arg_2, __arg_3, __arg_4, __arg_5, __arg_6) => Blink_JsNative_DomException.callMethod(mthis /* MutationEvent */, "initMutationEvent", [__arg_0, __arg_1, __arg_2, __arg_3, __arg_4, __arg_5, __arg_6]);
-
-  initMutationEvent_Callback_8_(mthis, __arg_0, __arg_1, __arg_2, __arg_3, __arg_4, __arg_5, __arg_6, __arg_7) => Blink_JsNative_DomException.callMethod(mthis /* MutationEvent */, "initMutationEvent", [__arg_0, __arg_1, __arg_2, __arg_3, __arg_4, __arg_5, __arg_6, __arg_7]);
-
-}
-
 class BlinkMutationObserver {
   static final instance = new BlinkMutationObserver();
 
diff --git a/sdk/lib/_internal/js_runtime/lib/async_patch.dart b/sdk/lib/_internal/js_runtime/lib/async_patch.dart
index 20cd748..db2a4e1 100644
--- a/sdk/lib/_internal/js_runtime/lib/async_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/async_patch.dart
@@ -417,14 +417,14 @@
   final value;
   final int state;
 
-  _IterationMarker._(this.state, this.value);
+  const _IterationMarker._(this.state, this.value);
 
   static yieldStar(dynamic /* Iterable or Stream */ values) {
     return new _IterationMarker._(YIELD_STAR, values);
   }
 
   static endOfIteration() {
-    return new _IterationMarker._(ITERATION_ENDED, null);
+    return const _IterationMarker._(ITERATION_ENDED, null);
   }
 
   static yieldSingle(dynamic value) {
@@ -439,17 +439,33 @@
 }
 
 class _SyncStarIterator implements Iterator {
-  final dynamic _body;
+  // _SyncStarIterator handles stepping a sync* generator body state machine.
+  //
+  // It also handles the stepping over 'nested' iterators to flatten yield*
+  // statements. For non-sync* iterators, [_nestedIterator] contains the
+  // iterator. We delegate to [_nestedIterator] when it is not `null`.
+  //
+  // For nested sync* iterators, [this] iterator acts on behalf of the innermost
+  // nested sync* iterator. The current state machine is suspended on a stack
+  // until the inner state machine ends.
 
-  // If [runningNested] this is the nested iterator, otherwise it is the
-  // current value.
+  // The state machine for the innermost _SyncStarIterator.
+  dynamic _body;
+
+  // The current value, unless iterating a non-sync* nested iterator.
   dynamic _current = null;
-  bool _runningNested = false;
 
-  get current => _runningNested ? _current.current : _current;
+  // This is the nested iterator when iterating a yield* of a non-sync iterator.
+  Iterator _nestedIterator = null;
+
+  // Stack of suspended state machines when iterating a yield* of a sync*
+  // iterator.
+  List _suspendedBodies = null;
 
   _SyncStarIterator(this._body);
 
+  get current => _nestedIterator == null ? _current : _nestedIterator.current;
+
   _runBody() {
     // TODO(sra): Find a way to hard-wire SUCCESS and ERROR codes.
     return JS('',
@@ -472,33 +488,56 @@
         _body, async_error_codes.SUCCESS, async_error_codes.ERROR);
   }
 
-
   bool moveNext() {
-    if (_runningNested) {
-      if (_current.moveNext()) {
+    while (true) {
+      if (_nestedIterator != null) {
+        if (_nestedIterator.moveNext()) {
+          return true;
+        } else {
+          _nestedIterator = null;
+        }
+      }
+      var value = _runBody();
+      if (value is _IterationMarker) {
+        int state = value.state;
+        if (state == _IterationMarker.ITERATION_ENDED) {
+          if (_suspendedBodies == null || _suspendedBodies.isEmpty) {
+            _current = null;
+            // Rely on [_body] to repeatedly return `ITERATION_ENDED`.
+            return false;
+          }
+          // Resume the innermost suspended iterator.
+          _body = _suspendedBodies.removeLast();
+          continue;
+        } else if (state == _IterationMarker.UNCAUGHT_ERROR) {
+          // Rely on [_body] to repeatedly return `UNCAUGHT_ERROR`.
+          // This is a wrapped exception, so we use JavaScript throw to throw
+          // it.
+          JS('', 'throw #', value.value);
+        } else {
+          assert(state == _IterationMarker.YIELD_STAR);
+          Iterator inner = value.value.iterator;
+          if (inner is _SyncStarIterator) {
+            // Suspend the current state machine and start acting on behalf of
+            // the nested state machine.
+            //
+            // TODO(sra): Recognize "tail yield*" statements and avoid
+            // suspending the current body when all it will do is step without
+            // effect to ITERATION_ENDED.
+            (_suspendedBodies ??= []).add(_body);
+            _body = inner._body;
+            continue;
+          } else {
+            _nestedIterator = inner;
+            continue;
+          }
+        }
+      } else {
+        _current = value;
         return true;
-      } else {
-        _runningNested = false;
       }
     }
-    _current = _runBody();
-    if (_current is _IterationMarker) {
-      if (_current.state == _IterationMarker.ITERATION_ENDED) {
-        _current = null;
-        // Rely on [_body] to repeatedly return `ITERATION_ENDED`.
-        return false;
-      } else if (_current.state == _IterationMarker.UNCAUGHT_ERROR) {
-        // Rely on [_body] to repeatedly return `UNCAUGHT_ERROR`.
-        // This is a wrapped exception, so we use JavaScript throw to throw it.
-        JS('', 'throw #', _current.value);
-      } else {
-        assert(_current.state == _IterationMarker.YIELD_STAR);
-        _current = _current.value.iterator;
-        _runningNested = true;
-        return moveNext();
-      }
-    }
-    return true;
+    return false;  // TODO(sra): Fix type inference so that this is not needed.
   }
 }
 
diff --git a/sdk/lib/_internal/js_runtime/lib/io_patch.dart b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
index e403844..4487e15 100644
--- a/sdk/lib/_internal/js_runtime/lib/io_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
@@ -45,6 +45,14 @@
 }
 
 @patch
+class _AsyncDirectoryListerOps {
+  @patch
+  factory _AsyncDirectoryListerOps(int pointer) {
+    throw new UnsupportedError("Directory._list");
+  }
+}
+
+@patch
 class _EventHandler {
   @patch
   static void _sendData(Object sender,
@@ -135,58 +143,10 @@
 }
 
 @patch
-class _RandomAccessFile {
+class _RandomAccessFileOps {
   @patch
-  static int _close(int id) {
-    throw new UnsupportedError("RandomAccessFile._close");
-  }
-  @patch
-  static int _getFD(int id) {
-    throw new UnsupportedError("RandomAccessFile._getFD");
-  }
-  @patch
-  static _readByte(int id) {
-    throw new UnsupportedError("RandomAccessFile._readByte");
-  }
-  @patch
-  static _read(int id, int bytes) {
-    throw new UnsupportedError("RandomAccessFile._read");
-  }
-  @patch
-  static _readInto(int id, List<int> buffer, int start, int end) {
-    throw new UnsupportedError("RandomAccessFile._readInto");
-  }
-  @patch
-  static _writeByte(int id, int value) {
-    throw new UnsupportedError("RandomAccessFile._writeByte");
-  }
-  @patch
-  static _writeFrom(int id, List<int> buffer, int start, int end) {
-    throw new UnsupportedError("RandomAccessFile._writeFrom");
-  }
-  @patch
-  static _position(int id) {
-    throw new UnsupportedError("RandomAccessFile._position");
-  }
-  @patch
-  static _setPosition(int id, int position) {
-    throw new UnsupportedError("RandomAccessFile._setPosition");
-  }
-  @patch
-  static _truncate(int id, int length) {
-    throw new UnsupportedError("RandomAccessFile._truncate");
-  }
-  @patch
-  static _length(int id) {
-    throw new UnsupportedError("RandomAccessFile._length");
-  }
-  @patch
-  static _flush(int id) {
-    throw new UnsupportedError("RandomAccessFile._flush");
-  }
-  @patch
-  static _lock(int id, int lock, int start, int end) {
-    throw new UnsupportedError("RandomAccessFile._lock");
+  factory _RandomAccessFileOps(int pointer) {
+    throw new UnsupportedError("RandomAccessFile");
   }
 }
 
@@ -353,6 +313,10 @@
 @patch
 class NetworkInterface {
   @patch
+  static bool get listSupported {
+    throw new UnsupportedError("NetworkInterface.listSupported");
+  }
+  @patch
   static Future<List<NetworkInterface>> list({
       bool includeLoopback: false,
       bool includeLinkLocal: false,
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 87fc341..97b1244 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -259,8 +259,8 @@
    *         _outputSink.add(data);
    *       }
    *
-   *       void addError(e, [st]) => _outputSink.addError(e, st);
-   *       void close() => _outputSink.close();
+   *       void addError(e, [st]) { _outputSink.addError(e, st); }
+   *       void close() { _outputSink.close(); }
    *     }
    *
    *     class DuplicationTransformer implements StreamTransformer<String, String> {
diff --git a/sdk/lib/async/stream_transformers.dart b/sdk/lib/async/stream_transformers.dart
index ea4aaf7..979ce3a 100644
--- a/sdk/lib/async/stream_transformers.dart
+++ b/sdk/lib/async/stream_transformers.dart
@@ -213,10 +213,11 @@
   _HandlerEventSink(this._handleData, this._handleError, this._handleDone,
                     this._sink);
 
-  void add(S data) => _handleData(data, _sink);
-  void addError(Object error, [StackTrace stackTrace])
-      => _handleError(error, stackTrace, _sink);
-  void close() => _handleDone(_sink);
+  void add(S data) { _handleData(data, _sink); }
+  void addError(Object error, [StackTrace stackTrace]) {
+    _handleError(error, stackTrace, _sink);
+  }
+  void close() { _handleDone(_sink); }
 }
 
 /**
diff --git a/sdk/lib/collection/hash_map.dart b/sdk/lib/collection/hash_map.dart
index 5a22dc0..a5f31b6 100644
--- a/sdk/lib/collection/hash_map.dart
+++ b/sdk/lib/collection/hash_map.dart
@@ -93,7 +93,7 @@
    * Effectively a shorthand for:
    *
    *     new HashMap(equals: identical,
-   *                 hashCode: identityHashCodeOf)
+   *                 hashCode: identityHashCode)
    */
   external factory HashMap.identity();
 
diff --git a/sdk/lib/collection/hash_set.dart b/sdk/lib/collection/hash_set.dart
index bb76082..3ecb82c 100644
--- a/sdk/lib/collection/hash_set.dart
+++ b/sdk/lib/collection/hash_set.dart
@@ -101,7 +101,7 @@
    * Effectively a shorthand for:
    *
    *     new HashSet<E>(equals: identical,
-   *                    hashCode: identityHashCodeOf)
+   *                    hashCode: identityHashCode)
    */
   external factory HashSet.identity();
 
diff --git a/sdk/lib/collection/linked_hash_map.dart b/sdk/lib/collection/linked_hash_map.dart
index e06f9e6..0f76652 100644
--- a/sdk/lib/collection/linked_hash_map.dart
+++ b/sdk/lib/collection/linked_hash_map.dart
@@ -80,7 +80,7 @@
    * Effectively a shorthand for:
    *
    *     new LinkedHashMap(equals: identical,
-   *                       hashCode: identityHashCodeOf)
+   *                       hashCode: identityHashCode)
    */
   external factory LinkedHashMap.identity();
 
diff --git a/sdk/lib/collection/linked_hash_set.dart b/sdk/lib/collection/linked_hash_set.dart
index a4848f4..a149692 100644
--- a/sdk/lib/collection/linked_hash_set.dart
+++ b/sdk/lib/collection/linked_hash_set.dart
@@ -84,7 +84,7 @@
    * Effectively a shorthand for:
    *
    *     new LinkedHashSet(equals: identical,
-   *                       hashCode: identityHashCodeOf)
+   *                       hashCode: identityHashCode)
    */
   external factory LinkedHashSet.identity();
 
diff --git a/sdk/lib/convert/byte_conversion.dart b/sdk/lib/convert/byte_conversion.dart
index d27b40f..4c1ede4 100644
--- a/sdk/lib/convert/byte_conversion.dart
+++ b/sdk/lib/convert/byte_conversion.dart
@@ -64,8 +64,8 @@
 
   _ByteAdapterSink(this._sink);
 
-  void add(List<int> chunk) => _sink.add(chunk);
-  void close() => _sink.close();
+  void add(List<int> chunk) { _sink.add(chunk); }
+  void close() { _sink.close(); }
 }
 
 /**
diff --git a/sdk/lib/convert/chunked_conversion.dart b/sdk/lib/convert/chunked_conversion.dart
index d450c75..a36c505 100644
--- a/sdk/lib/convert/chunked_conversion.dart
+++ b/sdk/lib/convert/chunked_conversion.dart
@@ -130,11 +130,11 @@
       : this._eventSink = sink,
         _chunkedSink = converter.startChunkedConversion(sink);
 
-  void add(S o) => _chunkedSink.add(o);
+  void add(S o) { _chunkedSink.add(o); }
   void addError(Object error, [StackTrace stackTrace]) {
     _eventSink.addError(error, stackTrace);
   }
-  void close() => _chunkedSink.close();
+  void close() { _chunkedSink.close(); }
 }
 
 /**
diff --git a/sdk/lib/convert/html_escape.dart b/sdk/lib/convert/html_escape.dart
index 2a0af75..7efe317 100644
--- a/sdk/lib/convert/html_escape.dart
+++ b/sdk/lib/convert/html_escape.dart
@@ -227,5 +227,5 @@
     }
   }
 
-  void close() => _sink.close();
+  void close() { _sink.close(); }
 }
diff --git a/sdk/lib/convert/string_conversion.dart b/sdk/lib/convert/string_conversion.dart
index 9c32673..bdfd39b 100644
--- a/sdk/lib/convert/string_conversion.dart
+++ b/sdk/lib/convert/string_conversion.dart
@@ -93,13 +93,14 @@
 
   _ClosableStringSink(this._sink, this._callback);
 
-  void close() => _callback();
+  void close() { _callback(); }
 
-  void writeCharCode(int charCode) => _sink.writeCharCode(charCode);
-  void write(Object o) => _sink.write(o);
-  void writeln([Object o = ""]) => _sink.writeln(o);
-  void writeAll(Iterable objects, [String separator = ""])
-      => _sink.writeAll(objects, separator);
+  void writeCharCode(int charCode) { _sink.writeCharCode(charCode); }
+  void write(Object o) { _sink.write(o); }
+  void writeln([Object o = ""]) { _sink.writeln(o); }
+  void writeAll(Iterable objects, [String separator = ""]) {
+    _sink.writeAll(objects, separator);
+  }
 }
 
 /**
@@ -177,7 +178,7 @@
   void addSlice(String str, int start, int end, bool isLast);
   void close();
 
-  void add(String str) => addSlice(str, 0, str.length, false);
+  void add(String str) { addSlice(str, 0, str.length, false); }
 
   ByteConversionSink asUtf8Sink(bool allowMalformed) {
     return new _Utf8ConversionSink(this, allowMalformed);
@@ -207,7 +208,7 @@
     if (isLast) close();
   }
 
-  void add(String str) => _stringSink.write(str);
+  void add(String str) { _stringSink.write(str); }
 
   ByteConversionSink asUtf8Sink(bool allowMalformed) {
     return new _Utf8StringSinkAdapter(this, _stringSink, allowMalformed);
@@ -253,7 +254,7 @@
 
   _StringAdapterSink(this._sink);
 
-  void add(String str) => _sink.add(str);
+  void add(String str) { _sink.add(str); }
 
   void addSlice(String str, int start, int end, bool isLast) {
     if (start == 0 && end == str.length) {
@@ -264,7 +265,7 @@
     if (isLast) close();
   }
 
-  void close() => _sink.close();
+  void close() { _sink.close(); }
 }
 
 
diff --git a/sdk/lib/core/iterable.dart b/sdk/lib/core/iterable.dart
index dd19502..4f45744 100644
--- a/sdk/lib/core/iterable.dart
+++ b/sdk/lib/core/iterable.dart
@@ -447,11 +447,11 @@
    * Returns the first element.
    *
    * Throws a [StateError] if `this` is empty.
-   * Otherwise returs the first element in the iteration order,
-   * equivalent to `(iterator..moveNext())..current`.
+   * Otherwise returns the first element in the iteration order,
+   * equivalent to `this.elementAt(0)`.
    */
   E get first {
-    Iterator it = iterator;
+    Iterator<E> it = iterator;
     if (!it.moveNext()) {
       throw IterableElementError.noElement();
     }
@@ -469,7 +469,7 @@
    * without iterating through the previous ones).
    */
   E get last {
-    Iterator it = iterator;
+    Iterator<E> it = iterator;
     if (!it.moveNext()) {
       throw IterableElementError.noElement();
     }
@@ -486,7 +486,7 @@
    * Throws a [StateError] if `this` is empty or has more than one element.
    */
   E get single {
-    Iterator it = iterator;
+    Iterator<E> it = iterator;
     if (!it.moveNext()) throw IterableElementError.noElement();
     E result = it.current;
     if (it.moveNext()) throw IterableElementError.tooMany();
@@ -610,9 +610,19 @@
   final int _start;
   final int _end;
   final _Generator<E> _generator;
+
+  /// Creates an iterable that builds the elements from a generator function.
+  ///
+  /// The [generator] may be null, in which case the default generator
+  /// enumerating the integer positions is used. This means that [int] must
+  /// be assignable to [E] when no generator is provided. In practice this means
+  /// that the generator can only be emitted when [E] is equal to `dynamic`,
+  /// `int`, or `num`. The constructor will check that the types match.
   _GeneratorIterable(this._end, E generator(int n))
       : _start = 0,
-        _generator = (generator != null) ? generator : _id;
+        // The `as` below is used as check to make sure that `int` is assignable
+        // to [E].
+        _generator = (generator != null) ? generator : _id as _Generator<E>;
 
   _GeneratorIterable.slice(this._start, this._end, this._generator);
 
diff --git a/sdk/lib/core/num.dart b/sdk/lib/core/num.dart
index 38587b1..21f23ee 100644
--- a/sdk/lib/core/num.dart
+++ b/sdk/lib/core/num.dart
@@ -439,14 +439,15 @@
   static num parse(String input, [num onError(String input)]) {
     String source = input.trim();
     // TODO(lrn): Optimize to detect format and result type in one check.
-    num result = int.parse(source, onError: _returnNull);
+    num result = int.parse(source, onError: _returnIntNull);
     if (result != null) return result;
-    result = double.parse(source, _returnNull);
+    result = double.parse(source, _returnDoubleNull);
     if (result != null) return result;
     if (onError == null) throw new FormatException(input);
     return onError(input);
   }
 
-  /** Helper function for [parse]. */
-  static _returnNull(_) => null;
+  /** Helper functions for [parse]. */
+  static int _returnIntNull(String _) => null;
+  static double _returnDoubleNull(String _) => null;
 }
diff --git a/sdk/lib/core/symbol.dart b/sdk/lib/core/symbol.dart
index f60cdd1..44e9787 100644
--- a/sdk/lib/core/symbol.dart
+++ b/sdk/lib/core/symbol.dart
@@ -49,5 +49,5 @@
    * Qualified member names, like `#foo.bar` are equal only if they have the
    * same identifiers before the same final member name.
    */
-  bool operator ==(Object other);
+  bool operator ==(other);
 }
diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart
index a1a5b5d..0cfeceb 100644
--- a/sdk/lib/core/uri.dart
+++ b/sdk/lib/core/uri.dart
@@ -148,7 +148,7 @@
    * except for the unreserved characters, and replaces spaces with `+`.
    * If `query` is the empty string, it is equivalent to omitting it.
    * To have an actual empty query part,
-   * use an empty list for `queryParameters`.
+   * use an empty map for `queryParameters`.
    *
    * If both `query` and `queryParameters` are omitted or `null`,
    * the URI has no query part.
@@ -165,7 +165,7 @@
                String path,
                Iterable<String> pathSegments,
                String query,
-               Map<String, dynamic> queryParameters,
+               Map<String, dynamic/*String|Iterable<String>*/> queryParameters,
                String fragment}) {
     scheme = _makeScheme(scheme, 0, _stringOrNullLength(scheme));
     userInfo = _makeUserInfo(userInfo, 0, _stringOrNullLength(userInfo));
@@ -1010,7 +1010,7 @@
                String path,
                Iterable<String> pathSegments,
                String query,
-               Map<String, String> queryParameters,
+               Map<String, dynamic/*String|Iterable<String>*/> queryParameters,
                String fragment}) {
     // Set to true if the scheme has (potentially) changed.
     // In that case, the default port may also have changed and we need
@@ -1373,8 +1373,9 @@
     return _removeDotSegments(path);
   }
 
-  static String _makeQuery(String query, int start, int end,
-                           Map<String, String> queryParameters) {
+  static String _makeQuery(
+      String query, int start, int end,
+      Map<String, dynamic/*String|Iterable<String>*/> queryParameters) {
     if (query == null && queryParameters == null) return null;
     if (query != null && queryParameters != null) {
       throw new ArgumentError('Both query and queryParameters specified');
@@ -1469,7 +1470,7 @@
 
   static String _escapeChar(int char) {
     assert(char <= 0x10ffff);  // It's a valid unicode code point.
-    List codeUnits;
+    List<int> codeUnits;
     if (char < 0x80) {
       // ASCII, a single percent encoded sequence.
       codeUnits = new List(3);
@@ -2365,8 +2366,7 @@
     } else if (parts.length != 8) {
       error('an address without a wildcard must contain exactly 8 parts');
     }
-    // TODO(ajohnsen): Consider using Uint8List.
-    List bytes = new List<int>(16);
+    List<int> bytes = new Uint8List(16);
     for (int i = 0, index = 0; i < parts.length; i++) {
       int value = parts[i];
       if (value == -1) {
@@ -2830,7 +2830,7 @@
                               Map<String, String> parameters,
                               bool base64: false}) {
     StringBuffer buffer = new StringBuffer();
-    List indices = [_noScheme];
+    List<int> indices = [_noScheme];
     String charsetName;
     String encodingName;
     if (parameters != null) charsetName = parameters["charset"];
@@ -2867,7 +2867,7 @@
                              Map<String, String> parameters,
                              percentEncoded: false}) {
     StringBuffer buffer = new StringBuffer();
-    List indices = [_noScheme];
+    List<int> indices = [_noScheme];
     _writeUri(mimeType, null, parameters, buffer, indices);
     indices.add(buffer.length);
     if (percentEncoded) {
@@ -3231,7 +3231,7 @@
     const int slash     = 0x2f;
     const int semicolon = 0x3b;
     const int equals    = 0x3d;
-    List indices = [start - 1];
+    List<int> indices = [start - 1];
     int slashIndex = -1;
     var char;
     int i = start;
diff --git a/sdk/lib/developer/timeline.dart b/sdk/lib/developer/timeline.dart
index c463d8b..362832d 100644
--- a/sdk/lib/developer/timeline.dart
+++ b/sdk/lib/developer/timeline.dart
@@ -20,7 +20,7 @@
     }
     var block = new _SyncBlock._(name, _getTraceClock());
     if (arguments is Map) {
-      block.arguments.addAll(arguments);
+      block._appendArguments(arguments);
     }
     _stack.add(block);
   }
@@ -108,7 +108,7 @@
     }
     var block = new _AsyncBlock._(name, _taskId);
     if (arguments is Map) {
-      block.arguments.addAll(arguments);
+      block._appendArguments(arguments);
     }
     _stack.add(block);
     block._start();
@@ -171,7 +171,7 @@
   final int _taskId;
   /// An (optional) set of arguments which will be serialized to JSON and
   /// associated with this block.
-  final Map arguments = {};
+  Map _arguments;
 
   _AsyncBlock._(this.name, this._taskId);
 
@@ -182,7 +182,7 @@
                      'b',
                      category,
                      name,
-                     _argumentsAsJson(arguments));
+                     _argumentsAsJson(_arguments));
   }
 
   // Emit the finish event.
@@ -194,6 +194,13 @@
                      name,
                      _argumentsAsJson(null));
   }
+
+  void _appendArguments(Map arguments) {
+    if (_arguments == null) {
+      _arguments = {};
+    }
+    _arguments.addAll(arguments);
+  }
 }
 
 /// A synchronous block of time on the timeline. This block should not be
@@ -205,7 +212,7 @@
   final String name;
   /// An (optional) set of arguments which will be serialized to JSON and
   /// associated with this block.
-  final Map arguments = {};
+  Map _arguments;
   // The start time stamp.
   final int _start;
 
@@ -220,7 +227,17 @@
                          _getTraceClock(),
                          category,
                          name,
-                         _argumentsAsJson(arguments));
+                         _argumentsAsJson(_arguments));
+  }
+
+  void _appendArguments(Map arguments) {
+    if (arguments == null) {
+      return;
+    }
+    if (_arguments == null) {
+      _arguments = {};
+    }
+    _arguments.addAll(arguments);
   }
 }
 
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 50e16be..4ca1158 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -143,12 +143,12 @@
    */
   @DomName('AbstractWorker.errorEvent')
   @DocsEditable()
-  static const EventStreamProvider<ErrorEvent> errorEvent = const EventStreamProvider<ErrorEvent>('error');
+  static const EventStreamProvider<Event> errorEvent = const EventStreamProvider<Event>('error');
 
   /// Stream of `error` events handled by this [AbstractWorker].
   @DomName('AbstractWorker.onerror')
   @DocsEditable()
-  Stream<ErrorEvent> get onError => errorEvent.forTarget(this);
+  Stream<Event> get onError => errorEvent.forTarget(this);
 }
 // 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
@@ -165,7 +165,7 @@
   @DomName('HTMLAnchorElement.HTMLAnchorElement')
   @DocsEditable()
   factory AnchorElement({String href}) {
-    var e = document.createElement("a");
+    AnchorElement e = document.createElement("a");
     if (href != null) e.href = href;
     return e;
   }
@@ -1868,7 +1868,7 @@
   @DomName('HTMLCanvasElement.HTMLCanvasElement')
   @DocsEditable()
   factory CanvasElement({int width, int height}) {
-    var e = document.createElement("canvas");
+    CanvasElement e = document.createElement("canvas");
     if (width != null) e.width = width;
     if (height != null) e.height = height;
     return e;
@@ -3099,7 +3099,7 @@
     if (view == null) {
       view = window;
     }
-    var e = document._createEvent("CompositionEvent");
+    CompositionEvent e = document._createEvent("CompositionEvent");
 
     if (Device.isFirefox) {
       // Firefox requires the locale parameter that isn't supported elsewhere.
@@ -9429,7 +9429,7 @@
   factory DeviceOrientationEvent(String type,
       {bool canBubble: true, bool cancelable: true, num alpha: 0, num beta: 0,
       num gamma: 0, bool absolute: false}) {
-    var e = document._createEvent("DeviceOrientationEvent");
+    DeviceOrientationEvent e = document._createEvent("DeviceOrientationEvent");
     e._initDeviceOrientationEvent(type, canBubble, cancelable, alpha, beta,
         gamma, absolute);
     return e;
@@ -9969,10 +9969,11 @@
   @DocsEditable()
   String _title;
 
+  @JSName('visibilityState')
   @DomName('Document.visibilityState')
   @DocsEditable()
   @Experimental() // untriaged
-  final String visibilityState;
+  final String _visibilityState;
 
   @JSName('webkitFullscreenElement')
   @DomName('Document.webkitFullscreenElement')
@@ -10605,9 +10606,8 @@
    * For details about CSS selector syntax, see the
    * [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
    */
-  ElementList<Element> querySelectorAll(String selectors) {
-    return new _FrozenElementList._wrap(_querySelectorAll(selectors));
-  }
+  ElementList<Element /*=T*/> querySelectorAll/*<T extends Element>*/(String selectors) =>
+    new _FrozenElementList/*<T>*/._wrap(_querySelectorAll(selectors));
 
   /**
    * Alias for [querySelector]. Note this function is deprecated because its
@@ -10625,7 +10625,7 @@
   @deprecated
   @Experimental()
   @DomName('Document.querySelectorAll')
-  ElementList<Element> queryAll(String relativeSelectors) =>
+  ElementList<Element /*=T*/> queryAll/*<T extends Element>*/(String relativeSelectors) =>
       querySelectorAll(relativeSelectors);
 
   /// Checks if [registerElement] is supported on the current platform.
@@ -10675,6 +10675,15 @@
       [int whatToShow, NodeFilter filter])
       => JS('TreeWalker', '#.createTreeWalker(#, #, #, false)',
           this, root, whatToShow, filter);
+
+  @DomName('Document.visibilityState')
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.FIREFOX)
+  @SupportedBrowser(SupportedBrowser.IE, '10')
+  @Experimental()
+  String get visibilityState => JS('String',
+    '(#.visibilityState || #.mozVisibilityState || #.msVisibilityState ||'
+      '#.webkitVisibilityState)', this, this, this, this);
 }
 // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -10717,7 +10726,7 @@
 
   set children(List<Element> value) {
     // Copy list first since we don't want liveness during iteration.
-    List copy = new List.from(value);
+    var copy = value.toList();
     var children = this.children;
     children.clear();
     children.addAll(copy);
@@ -10734,8 +10743,9 @@
    * For details about CSS selector syntax, see the
    * [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
    */
-  ElementList<Element> querySelectorAll(String selectors) =>
-    new _FrozenElementList._wrap(_querySelectorAll(selectors));
+  ElementList<Element /*=T*/> querySelectorAll/*<T extends Element>*/(String selectors) =>
+    new _FrozenElementList/*<T>*/._wrap(_querySelectorAll(selectors));
+
 
   String get innerHtml {
     final e = new Element.tag("div");
@@ -10792,9 +10802,8 @@
   @deprecated
   @Experimental()
   @DomName('DocumentFragment.querySelectorAll')
-  ElementList<Element> queryAll(String relativeSelectors) {
-    return querySelectorAll(relativeSelectors);
-  }
+  ElementList<Element /*=T*/> queryAll/*<T extends Element>*/(String relativeSelectors) =>
+    querySelectorAll(relativeSelectors);
   // To suppress missing implicit constructor warnings.
   factory DocumentFragment._() { throw new UnsupportedError("Not supported"); }
 
@@ -11202,125 +11211,53 @@
   // To suppress missing implicit constructor warnings.
   factory DomMatrixReadOnly._() { throw new UnsupportedError("Not supported"); }
 
-  @DomName('DOMMatrixReadOnly.a')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double a;
+  num get a => JS("num", "#.a", this);
 
-  @DomName('DOMMatrixReadOnly.b')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double b;
+  num get b => JS("num", "#.b", this);
 
-  @DomName('DOMMatrixReadOnly.c')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double c;
+  num get c => JS("num", "#.c", this);
 
-  @DomName('DOMMatrixReadOnly.d')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double d;
+  num get d => JS("num", "#.d", this);
 
-  @DomName('DOMMatrixReadOnly.e')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double e;
+  num get e => JS("num", "#.e", this);
 
-  @DomName('DOMMatrixReadOnly.f')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double f;
+  num get f => JS("num", "#.f", this);
 
-  @DomName('DOMMatrixReadOnly.is2D')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final bool is2D;
+  bool get is2D => JS("bool", "#.is2D", this);
 
-  @DomName('DOMMatrixReadOnly.isIdentity')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final bool isIdentity;
+  bool get isIdentity => JS("bool", "#.isIdentity", this);
 
-  @DomName('DOMMatrixReadOnly.m11')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double m11;
+  num get m11 => JS("num", "#.m11", this);
 
-  @DomName('DOMMatrixReadOnly.m12')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double m12;
+  num get m12 => JS("num", "#.m12", this);
 
-  @DomName('DOMMatrixReadOnly.m13')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double m13;
+  num get m13 => JS("num", "#.m13", this);
 
-  @DomName('DOMMatrixReadOnly.m14')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double m14;
+  num get m14 => JS("num", "#.m14", this);
 
-  @DomName('DOMMatrixReadOnly.m21')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double m21;
+  num get m21 => JS("num", "#.m21", this);
 
-  @DomName('DOMMatrixReadOnly.m22')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double m22;
+  num get m22 => JS("num", "#.m22", this);
 
-  @DomName('DOMMatrixReadOnly.m23')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double m23;
+  num get m23 => JS("num", "#.m23", this);
 
-  @DomName('DOMMatrixReadOnly.m24')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double m24;
+  num get m24 => JS("num", "#.m24", this);
 
-  @DomName('DOMMatrixReadOnly.m31')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double m31;
+  num get m31 => JS("num", "#.m31", this);
 
-  @DomName('DOMMatrixReadOnly.m32')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double m32;
+  num get m32 => JS("num", "#.m32", this);
 
-  @DomName('DOMMatrixReadOnly.m33')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double m33;
+  num get m33 => JS("num", "#.m33", this);
 
-  @DomName('DOMMatrixReadOnly.m34')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double m34;
+  num get m34 => JS("num", "#.m34", this);
 
-  @DomName('DOMMatrixReadOnly.m41')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double m41;
+  num get m41 => JS("num", "#.m41", this);
 
-  @DomName('DOMMatrixReadOnly.m42')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double m42;
+  num get m42 => JS("num", "#.m42", this);
 
-  @DomName('DOMMatrixReadOnly.m43')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double m43;
+  num get m43 => JS("num", "#.m43", this);
 
-  @DomName('DOMMatrixReadOnly.m44')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double m44;
+  num get m44 => JS("num", "#.m44", this);
 
   @DomName('DOMMatrixReadOnly.multiply')
   @DocsEditable()
@@ -11475,25 +11412,13 @@
   }
   static DomPointReadOnly _create_1(x, y, z, w) => JS('DomPointReadOnly', 'new DOMPointReadOnly(#,#,#,#)', x, y, z, w);
 
-  @DomName('DOMPointReadOnly.w')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double w;
+  num get w => JS("num", "#.w", this);
 
-  @DomName('DOMPointReadOnly.x')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double x;
+  num get x => JS("num", "#.x", this);
 
-  @DomName('DOMPointReadOnly.y')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double y;
+  num get y => JS("num", "#.y", this);
 
-  @DomName('DOMPointReadOnly.z')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double z;
+  num get z => JS("num", "#.z", this);
 }
 // 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
@@ -11605,45 +11530,21 @@
   }
   static DomRectReadOnly _create_1(x, y, width, height) => JS('DomRectReadOnly', 'new DOMRectReadOnly(#,#,#,#)', x, y, width, height);
 
-  @DomName('DOMRectReadOnly.bottom')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double bottom;
+  num get bottom => JS("num", "#.bottom", this);
 
-  @DomName('DOMRectReadOnly.height')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double height;
+  num get height => JS("num", "#.height", this);
 
-  @DomName('DOMRectReadOnly.left')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double left;
+  num get left => JS("num", "#.left", this);
 
-  @DomName('DOMRectReadOnly.right')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double right;
+  num get right => JS("num", "#.right", this);
 
-  @DomName('DOMRectReadOnly.top')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double top;
+  num get top => JS("num", "#.top", this);
 
-  @DomName('DOMRectReadOnly.width')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double width;
+  num get width => JS("num", "#.width", this);
 
-  @DomName('DOMRectReadOnly.x')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double x;
+  num get x => JS("num", "#.x", this);
 
-  @DomName('DOMRectReadOnly.y')
-  @DocsEditable()
-  @Experimental() // untriaged
-  final double y;
+  num get y => JS("num", "#.y", this);
 }
 
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -11727,10 +11628,6 @@
   @Experimental() // untriaged
   String __getter__(int index) native;
 
-  @DomName('DOMStringList.contains')
-  @DocsEditable()
-  bool contains(String string) native;
-
   @DomName('DOMStringList.item')
   @DocsEditable()
   String item(int index) native;
@@ -11877,7 +11774,7 @@
     _filter(test, true);
   }
 
-  void _filter(bool test(var element), bool retainMatching) {
+  void _filter(bool test(Element element), bool retainMatching) {
     var removed;
     if (retainMatching) {
       removed = _element.children.where((e) => !test(e));
@@ -12531,17 +12428,17 @@
 // declared to return `ElementList`.  This provides all the static analysis
 // benefit so there is no need for this class have a constrained type parameter.
 //
-class _FrozenElementList extends ListBase
-    implements ElementList, NodeListWrapper {
+class _FrozenElementList<E extends Element> extends ListBase<E>
+    implements ElementList<E>, NodeListWrapper {
   final List<Node> _nodeList;
 
   _FrozenElementList._wrap(this._nodeList);
 
   int get length => _nodeList.length;
 
-  Element operator [](int index) => _nodeList[index];
+  E operator [](int index) => _downcast/*<Node, E>*/(_nodeList[index]);
 
-  void operator []=(int index, Element value) {
+  void operator []=(int index, E value) {
     throw new UnsupportedError('Cannot modify list');
   }
 
@@ -12549,7 +12446,7 @@
     throw new UnsupportedError('Cannot modify list');
   }
 
-  void sort([Comparator<Element> compare]) {
+  void sort([Comparator<E> compare]) {
     throw new UnsupportedError('Cannot sort list');
   }
 
@@ -12557,11 +12454,11 @@
     throw new UnsupportedError('Cannot shuffle list');
   }
 
-  Element get first => _nodeList.first;
+  E get first => _downcast/*<Node, E>*/(_nodeList.first);
 
-  Element get last => _nodeList.last;
+  E get last => _downcast/*<Node, E>*/(_nodeList.last);
 
-  Element get single => _nodeList.single;
+  E get single => _downcast/*<Node, E>*/(_nodeList.single);
 
   CssClassSet get classes => new _MultiElementCssClassSet(this);
 
@@ -12575,7 +12472,7 @@
     //
     // as the code below converts the Iterable[value] to a string multiple
     // times.  Maybe compute the string and set className here.
-    _nodeList.forEach((e) => e.classes = value);
+    forEach((e) => e.classes = value);
   }
 
   CssRect get contentEdge => new _ContentCssListRect(this);
@@ -13315,7 +13212,7 @@
 
   set children(List<Element> value) {
     // Copy list first since we don't want liveness during iteration.
-    List copy = new List.from(value);
+    var copy = value.toList();
     var children = this.children;
     children.clear();
     children.addAll(copy);
@@ -13333,8 +13230,8 @@
    * [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
    */
   @DomName('Element.querySelectorAll')
-  ElementList<Element> querySelectorAll(String selectors) =>
-    new _FrozenElementList._wrap(_querySelectorAll(selectors));
+  ElementList<Element /*=T*/> querySelectorAll/*<T extends Element>*/(String selectors) =>
+    new _FrozenElementList/*<T>*/._wrap(_querySelectorAll(selectors));
 
   /**
    * Alias for [querySelector]. Note this function is deprecated because its
@@ -13352,7 +13249,7 @@
   @deprecated
   @DomName('Element.querySelectorAll')
   @Experimental()
-  ElementList<Element> queryAll(String relativeSelectors) =>
+  ElementList<Element /*=T*/> queryAll/*<T extends Element>*/(String relativeSelectors) =>
       querySelectorAll(relativeSelectors);
 
   /**
@@ -13550,14 +13447,13 @@
       throw new ArgumentError("The frames parameter should be a List of Maps "
           "with frame information");
     }
-    var convertedFrames = frames;
-    if (convertedFrames is Iterable) {
+    var convertedFrames;
+    if (frames is Iterable) {
       convertedFrames = frames.map(convertDartToNative_Dictionary).toList();
+    } else {
+      convertedFrames = frames;
     }
-    var convertedTiming = timing;
-    if (convertedTiming is Map) {
-      convertedTiming = convertDartToNative_Dictionary(convertedTiming);
-    }
+    var convertedTiming = timing is Map ? convertDartToNative_Dictionary(timing) : timing;
     return convertedTiming == null
       ? _animate(convertedFrames)
       : _animate(convertedFrames, convertedTiming);
@@ -14025,7 +13921,7 @@
 
       // Workaround for Safari bug. Was also previously Chrome bug 229142
       // - URIs are not resolved in new doc.
-      var base = _parseDocument.createElement('base');
+      BaseElement base = _parseDocument.createElement('base');
       base.href = document.baseUri;
       _parseDocument.head.append(base);
     }
@@ -14940,9 +14836,8 @@
   @DocsEditable()
   bool hidden;
 
-  @DomName('Element.isContentEditable')
-  @DocsEditable()
-  final bool isContentEditable;
+  // Using property as subclass shadows.
+  bool get isContentEditable => JS("bool", "#.isContentEditable", this);
 
   @DomName('Element.lang')
   @DocsEditable()
@@ -15067,10 +14962,8 @@
   // Use implementation from Node.
   // final String _namespaceUri;
 
-  @JSName('outerHTML')
-  @DomName('Element.outerHTML')
-  @DocsEditable()
-  final String outerHtml;
+  // Using property as subclass shadows.
+  String get outerHtml => JS("String", "#.outerHTML", this);
 
   @JSName('scrollHeight')
   @DomName('Element.scrollHeight')
@@ -16215,7 +16108,7 @@
     e._initEvent(name, canBubble, cancelable);
     return e;
   }
-  
+
   /** The CSS selector involved with event delegation. */
   String _selector;
 
@@ -16229,8 +16122,8 @@
       throw new UnsupportedError('Cannot call matchingTarget if this Event did'
           ' not arise as a result of event delegation.');
     }
-    var currentTarget = this.currentTarget;
-    var target = this.target;
+    Element currentTarget = this.currentTarget;
+    Element target = this.target;
     var matchedTarget;
     do {
       if (target.matches(_selector)) return target;
@@ -16523,26 +16416,24 @@
 }
 
 class ElementEvents extends Events {
-  /* Raw event target. */
-  final Element _ptr;
   static final webkitEvents = {
-    'animationend' : 'webkitAnimationEnd', 
-    'animationiteration' : 'webkitAnimationIteration', 
-    'animationstart' : 'webkitAnimationStart', 
-    'fullscreenchange' : 'webkitfullscreenchange', 
+    'animationend' : 'webkitAnimationEnd',
+    'animationiteration' : 'webkitAnimationIteration',
+    'animationstart' : 'webkitAnimationStart',
+    'fullscreenchange' : 'webkitfullscreenchange',
     'fullscreenerror' : 'webkitfullscreenerror',
-    'keyadded' : 'webkitkeyadded', 
-    'keyerror' : 'webkitkeyerror', 
-    'keymessage' : 'webkitkeymessage', 
-    'needkey' : 'webkitneedkey', 
-    'pointerlockchange' : 'webkitpointerlockchange', 
-    'pointerlockerror' : 'webkitpointerlockerror', 
-    'resourcetimingbufferfull' : 'webkitresourcetimingbufferfull', 
+    'keyadded' : 'webkitkeyadded',
+    'keyerror' : 'webkitkeyerror',
+    'keymessage' : 'webkitkeymessage',
+    'needkey' : 'webkitneedkey',
+    'pointerlockchange' : 'webkitpointerlockchange',
+    'pointerlockerror' : 'webkitpointerlockerror',
+    'resourcetimingbufferfull' : 'webkitresourcetimingbufferfull',
     'transitionend': 'webkitTransitionEnd',
     'speechchange' : 'webkitSpeechChange'
   };
 
-  ElementEvents(Element ptr) : this._ptr = ptr, super(ptr);
+  ElementEvents(Element ptr) : super(ptr);
 
   Stream operator [](String type) {
     if (webkitEvents.keys.contains(type.toLowerCase())) {
@@ -17980,7 +17871,10 @@
     }
 
     int watchId;
-    var controller;
+    // TODO(jacobr): it seems like a bug that we have to specifiy the static
+    // type here for controller.stream to have the right type.
+    // dartbug.com/26278
+    StreamController<Geoposition> controller;
     controller = new StreamController<Geoposition>(sync: true,
       onListen: () {
         assert(watchId == null);
@@ -19047,11 +18941,11 @@
 
   @DomName('HTMLCollection.item')
   @DocsEditable()
-  Element item(int index) native;
+  Node item(int index) native;
 
   @DomName('HTMLCollection.namedItem')
   @DocsEditable()
-  Element namedItem(String name) native;
+  Object namedItem(String name) native;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -19171,61 +19065,6 @@
     _webkitExitFullscreen();
   }
 
-  /**
-   * Returns the element, if any, that is currently displayed in fullscreen.
-   *
-   * Returns null if there is currently no fullscreen element. You can use
-   * this to determine if the page is in fullscreen mode.
-   *
-   *     myVideo = new VideoElement();
-   *     if (document.fullscreenElement == null) {
-   *       myVideo.requestFullscreen();
-   *       print(document.fullscreenElement == myVideo); // true
-   *     }
-   *
-   * ## Other resources
-   *
-   * * [Using the fullscreen
-   *   API](http://docs.webplatform.org/wiki/tutorials/using_the_full-screen_api)
-   *   from WebPlatform.org.
-   * * [Fullscreen specification](http://www.w3.org/TR/fullscreen/) from W3C.
-   */
-  @DomName('Document.webkitFullscreenElement')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  Element get fullscreenElement => _webkitFullscreenElement;
-
-  /**
-   * Returns true if this document can display elements in fullscreen mode.
-   *
-   * ## Other resources
-   *
-   * * [Using the fullscreen
-   *   API](http://docs.webplatform.org/wiki/tutorials/using_the_full-screen_api)
-   *   from WebPlatform.org.
-   * * [Fullscreen specification](http://www.w3.org/TR/fullscreen/) from W3C.
-   */
-  @DomName('Document.webkitFullscreenEnabled')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  bool get fullscreenEnabled => _webkitFullscreenEnabled;
-
-  @DomName('Document.webkitHidden')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  bool get hidden => _webkitHidden;
-
-  @DomName('Document.visibilityState')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.FIREFOX)
-  @SupportedBrowser(SupportedBrowser.IE, '10')
-  @Experimental()
-  String get visibilityState => JS('String',
-    '(#.visibilityState || #.mozVisibilityState || #.msVisibilityState ||'
-      '#.webkitVisibilityState)', this, this, this, this);
 
   @Experimental()
   /**
@@ -20394,7 +20233,7 @@
   @DomName('HTMLImageElement.HTMLImageElement')
   @DocsEditable()
   factory ImageElement({String src, int width, int height}) {
-    var e = document.createElement("img");
+    ImageElement e = document.createElement("img");
     if (src != null) e.src = src;
     if (width != null) e.width = width;
     if (height != null) e.height = height;
@@ -20542,7 +20381,7 @@
     ButtonInputElement {
 
   factory InputElement({String type}) {
-    var e = document.createElement("input");
+    InputElement e = document.createElement("input");
     if (type != null) {
       try {
         // IE throws an exception for unknown types.
@@ -21402,15 +21241,15 @@
 @Native("KeyboardEvent")
 class KeyboardEvent extends UIEvent {
 
-  /** 
-   * Programmatically create a KeyboardEvent. 
+  /**
+   * Programmatically create a KeyboardEvent.
    *
    * Due to browser differences, keyCode, charCode, or keyIdentifier values
    * cannot be specified in this base level constructor. This constructor
    * enables the user to programmatically create and dispatch a [KeyboardEvent],
    * but it will not contain any particular key content. For programmatically
    * creating keyboard events with specific key value contents, see the custom
-   * Event [KeyEvent]. 
+   * Event [KeyEvent].
    */
   factory KeyboardEvent(String type,
       {Window view, bool canBubble: true, bool cancelable: true,
@@ -21419,7 +21258,7 @@
     if (view == null) {
       view = window;
     }
-    final e = document._createEvent("KeyboardEvent");
+    KeyboardEvent e = document._createEvent("KeyboardEvent");
     e._initKeyboardEvent(type, canBubble, cancelable, view, "",
         keyLocation, ctrlKey, altKey, shiftKey, metaKey);
     return e;
@@ -23438,7 +23277,7 @@
   factory MessageEvent(String type,
       {bool canBubble: false, bool cancelable: false, Object data,
       String origin, String lastEventId,
-      Window source, List messagePorts}) {
+      Window source, List<MessagePort> messagePorts}) {
     if (source == null) {
       source = window;
     }
@@ -23448,7 +23287,7 @@
           type, canBubble, cancelable, data, origin, lastEventId, source,
           messagePorts);
     }
-    var event = document._createEvent("MessageEvent");
+    MessageEvent event = document._createEvent("MessageEvent");
     event._initMessageEvent(type, canBubble, cancelable, data, origin,
         lastEventId, source, messagePorts);
     return event;
@@ -24066,7 +23905,7 @@
     if (view == null) {
       view = window;
     }
-    var event = document._createEvent('MouseEvent');
+    MouseEvent event = document._createEvent('MouseEvent');
     event._initMouseEvent(type, canBubble, cancelable, view, detail,
         screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey,
         button, relatedTarget);
@@ -24210,22 +24049,6 @@
   @deprecated
   final Node toElement;
 
-  @JSName('webkitMovementX')
-  @DomName('MouseEvent.webkitMovementX')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  final int _webkitMovementX;
-
-  @JSName('webkitMovementY')
-  @DomName('MouseEvent.webkitMovementY')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  final int _webkitMovementY;
-
   // Use implementation from UIEvent.
   // final int _which;
 
@@ -24249,9 +24072,9 @@
   @DomName('MouseEvent.movementX')
   @DomName('MouseEvent.movementY')
   @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @SupportedBrowser(SupportedBrowser.FIREFOX)
   @Experimental()
-  Point get movement => new Point(_webkitMovementX, _webkitMovementY);
+  Point get movement => new Point(_movementX, _movementY);
 
   /**
    * The coordinates of the mouse pointer in target node coordinates.
@@ -25110,7 +24933,7 @@
   set nodes(Iterable<Node> value) {
     // Copy list first since we don't want liveness during iteration.
     // TODO(jacobr): there is a better way to do this.
-    List copy = new List.from(value);
+    var copy = value.toList();
     text = '';
     for (Node node in copy) {
       append(node);
@@ -29444,8 +29267,7 @@
   // Override default options, since IE returns SelectElement itself and it
   // does not operate as a List.
   List<OptionElement> get options {
-    var options = this.querySelectorAll('option').where(
-        (e) => e is OptionElement).toList();
+    var options = new List<OptionElement>.from(this.querySelectorAll('option'));
     return new UnmodifiableListView(options);
   }
 
@@ -31333,11 +31155,11 @@
   }
 
   // TODO(nweiz): update this when maps support lazy iteration
-  bool containsValue(String value) => values.any((e) => e == value);
+  bool containsValue(Object value) => values.any((e) => e == value);
 
-  bool containsKey(String key) => _getItem(key) != null;
+  bool containsKey(Object key) => _getItem(key) != null;
 
-  String operator [](String key) => _getItem(key);
+  String operator [](Object key) => _getItem(key);
 
   void operator []=(String key, String value) { _setItem(key, value); }
 
@@ -31346,7 +31168,7 @@
     return this[key];
   }
 
-  String remove(String key) {
+  String remove(Object key) {
     final value = this[key];
     _removeItem(key);
     return value;
@@ -31364,13 +31186,13 @@
   }
 
   Iterable<String> get keys {
-    final keys = [];
+    final keys = <String>[];
     forEach((k, v) => keys.add(k));
     return keys;
   }
 
   Iterable<String> get values {
-    final values = [];
+    final values = <String>[];
     forEach((k, v) => values.add(v));
     return values;
   }
@@ -31452,7 +31274,7 @@
     {bool canBubble: false, bool cancelable: false, String key, String oldValue,
     String newValue, String url, Storage storageArea}) {
 
-    var e = document._createEvent("StorageEvent");
+    StorageEvent e = document._createEvent("StorageEvent");
     e._initStorageEvent(type, canBubble, cancelable, key, oldValue,
         newValue, url, storageArea);
     return e;
@@ -32386,7 +32208,7 @@
     if (view == null) {
       view = window;
     }
-    var e = document._createEvent("TextEvent");
+    TextEvent e = document._createEvent("TextEvent");
     e._initTextEvent(type, canBubble, cancelable, view, data);
     return e;
   }
@@ -32980,7 +32802,7 @@
     if (view == null) {
       view = window;
     }
-    var e = document._createEvent("TouchEvent");
+    TouchEvent e = document._createEvent("TouchEvent");
     e._initTouchEvent(touches, targetTouches, changedTouches, type, view,
         screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey);
     return e;
@@ -33414,7 +33236,7 @@
     if (view == null) {
       view = window;
     }
-    final e = document._createEvent("UIEvent");
+    UIEvent e = document._createEvent("UIEvent");
     e._initUIEvent(type, canBubble, cancelable, view, detail);
     return e;
   }
@@ -34817,7 +34639,7 @@
   @DomName('Window.requestAnimationFrame')
   int requestAnimationFrame(FrameRequestCallback callback) {
     _ensureRequestAnimationFrame();
-    return _requestAnimationFrame(_wrapZone(callback));
+    return _requestAnimationFrame(_wrapZone/*<num, dynamic>*/(callback));
   }
 
   /**
@@ -36732,12 +36554,11 @@
 
   Stream<BeforeUnloadEvent> forTarget(EventTarget e, {bool useCapture: false}) {
     var stream = new _EventStream(e, _eventType, useCapture);
-    var controller = new StreamController(sync: true);
+    var controller = new StreamController<BeforeUnloadEvent>(sync: true);
 
     stream.listen((event) {
       var wrapped = new _BeforeUnloadEvent(event);
       controller.add(wrapped);
-      return wrapped.returnValue;
     });
 
     return controller.stream;
@@ -37552,13 +37373,6 @@
   // Use implementation from Node.
   // final String nodeValue;
 
-  // Shadowing definition.
-  String get text => JS("String", "#.textContent", this);
-
-  set text(String value) {
-    JS("void", "#.textContent = #", this, value);
-  }
-
   @DomName('Attr.value')
   @DocsEditable()
   String value;
@@ -38284,29 +38098,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
-@DomName('MutationEvent')
-// http://www.w3.org/TR/DOM-Level-3-Events/#events-mutationevents
-@deprecated
-@Native("MutationEvent")
-abstract class _MutationEvent extends Event {
-  factory _MutationEvent(String type,
-      {bool canBubble: false, bool cancelable: false, Node relatedNode,
-      String prevValue, String newValue, String attrName, int attrChange: 0}) {
-
-    var event = document._createEvent('MutationEvent');
-    event._initMutationEvent(type, canBubble, cancelable, relatedNode,
-        prevValue, newValue, attrName, attrChange);
-    return event;
-  }
-  // To suppress missing implicit constructor warnings.
-  factory _MutationEvent._() { throw new UnsupportedError("Not supported"); }
-
-}
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-
 @DocsEditable()
 @DomName('NamedNodeMap')
 // http://dom.spec.whatwg.org/#namednodemap
@@ -38784,7 +38575,7 @@
     other.forEach((k, v) { this[k] = v; });
   }
 
-  bool containsValue(String value) {
+  bool containsValue(Object value) {
     for (var v in this.values) {
       if (value == v) {
         return true;
@@ -38816,10 +38607,11 @@
   Iterable<String> get keys {
     // TODO: generate a lazy collection instead.
     var attributes = _element._attributes;
-    var keys = new List<String>();
+    var keys = <String>[];
     for (int i = 0, len = attributes.length; i < len; i++) {
-      if (_matches(attributes[i])) {
-        keys.add(attributes[i].name);
+      _Attr attr = attributes[i];
+      if (_matches(attr)) {
+        keys.add(attr.name);
       }
     }
     return keys;
@@ -38828,10 +38620,11 @@
   Iterable<String> get values {
     // TODO: generate a lazy collection instead.
     var attributes = _element._attributes;
-    var values = new List<String>();
+    var values = <String>[];
     for (int i = 0, len = attributes.length; i < len; i++) {
-      if (_matches(attributes[i])) {
-        values.add(attributes[i].value);
+      _Attr attr = attributes[i];
+      if (_matches(attr)) {
+        values.add(attr.value);
       }
     }
     return values;
@@ -38862,11 +38655,11 @@
 
   _ElementAttributeMap(Element element): super(element);
 
-  bool containsKey(String key) {
+  bool containsKey(Object key) {
     return _element._hasAttribute(key);
   }
 
-  String operator [](String key) {
+  String operator [](Object key) {
     return _element.getAttribute(key);
   }
 
@@ -38874,7 +38667,7 @@
     _element.setAttribute(key, value);
   }
 
-  String remove(String key) {
+  String remove(Object key) {
     String value = _element.getAttribute(key);
     _element._removeAttribute(key);
     return value;
@@ -38899,11 +38692,11 @@
 
   _NamespacedAttributeMap(Element element, this._namespace): super(element);
 
-  bool containsKey(String key) {
+  bool containsKey(Object key) {
     return _element._hasAttributeNS(_namespace, key);
   }
 
-  String operator [](String key) {
+  String operator [](Object key) {
     return _element.getAttributeNS(_namespace, key);
   }
 
@@ -38911,7 +38704,7 @@
     _element.setAttributeNS(_namespace, key, value);
   }
 
-  String remove(String key) {
+  String remove(Object key) {
     String value = this[key];
     _element._removeAttributeNS(_namespace, key);
     return value;
@@ -38945,11 +38738,11 @@
   }
 
   // TODO: Use lazy iterator when it is available on Map.
-  bool containsValue(String value) => values.any((v) => v == value);
+  bool containsValue(Object value) => values.any((v) => v == value);
 
-  bool containsKey(String key) => _attributes.containsKey(_attr(key));
+  bool containsKey(Object key) => _attributes.containsKey(_attr(key));
 
-  String operator [](String key) => _attributes[_attr(key)];
+  String operator [](Object key) => _attributes[_attr(key)];
 
   void operator []=(String key, String value) {
     _attributes[_attr(key)] = value;
@@ -38958,7 +38751,7 @@
   String putIfAbsent(String key, String ifAbsent()) =>
     _attributes.putIfAbsent(_attr(key), ifAbsent);
 
-  String remove(String key) => _attributes.remove(_attr(key));
+  String remove(Object key) => _attributes.remove(_attr(key));
 
   void clear() {
     // Needs to operate on a snapshot since we are mutating the collection.
@@ -38976,7 +38769,7 @@
   }
 
   Iterable<String> get keys {
-    final keys = new List<String>();
+    final keys = <String>[];
     _attributes.forEach((String key, String value) {
       if (_matches(key)) {
         keys.add(_strip(key));
@@ -38986,7 +38779,7 @@
   }
 
   Iterable<String> get values {
-    final values = new List<String>();
+    final values = <String>[];
     _attributes.forEach((String key, String value) {
       if (_matches(key)) {
         values.add(value);
@@ -39217,7 +39010,7 @@
    * * [Cross-document messaging](https://html.spec.whatwg.org/multipage/comms.html#web-messaging)
    *   from WHATWG.
    */
-  void postMessage(var message, String targetOrigin, [List messagePorts]);
+  void postMessage(var message, String targetOrigin, [List<MessagePort> messagePorts]);
 }
 
 abstract class LocationBase {
@@ -39271,7 +39064,7 @@
    * [value] must be a valid 'token' representing a single class, i.e. a
    * non-empty string containing no whitespace.
    */
-  bool contains(String value);
+  bool contains(Object value);
 
   /**
    * Add the class [value] to element.
@@ -39323,7 +39116,7 @@
    * Each element of [iterable] must be a valid 'token' representing a single
    * class, i.e. a non-empty string containing no whitespace.
    */
-  void removeAll(Iterable<String> iterable);
+  void removeAll(Iterable<Object> iterable);
 
   /**
    * Toggles all classes specified in [iterable] on element.
@@ -39351,7 +39144,7 @@
  */
 class _ContentCssRect extends CssRect {
 
-  _ContentCssRect(element) : super(element);
+  _ContentCssRect(Element element) : super(element);
 
   num get height => _element.offsetHeight +
       _addOrSubtractToBoxModel(_HEIGHT, _CONTENT);
@@ -39372,9 +39165,11 @@
     if (newHeight is Dimension) {
       if (newHeight.value < 0) newHeight = new Dimension.px(0);
       _element.style.height = newHeight.toString();
-    } else {
+    } else if (newHeight is num) {
       if (newHeight < 0) newHeight = 0;
       _element.style.height = '${newHeight}px';
+    } else {
+      throw new ArgumentError("newHeight is not a Dimension or num");
     }
   }
 
@@ -39390,9 +39185,11 @@
     if (newWidth is Dimension) {
       if (newWidth.value < 0) newWidth = new Dimension.px(0);
       _element.style.width = newWidth.toString();
-    } else {
+    } else if (newWidth is num) {
       if (newWidth < 0) newWidth = 0;
       _element.style.width = '${newWidth}px';
+    } else {
+      throw new ArgumentError("newWidth is not a Dimension or num");
     }
   }
 
@@ -39409,7 +39206,7 @@
 class _ContentCssListRect extends _ContentCssRect {
   List<Element> _elementList;
 
-  _ContentCssListRect(elementList) : super(elementList.first) {
+  _ContentCssListRect(List<Element> elementList) : super(elementList.first) {
     _elementList = elementList;
   }
 
@@ -39498,10 +39295,10 @@
  * animation frame is discouraged. See also:
  * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
  */
-abstract class CssRect extends MutableRectangle<num> {
+abstract class CssRect implements Rectangle<num> {
   Element _element;
 
-  CssRect(this._element) : super(0, 0, 0, 0);
+  CssRect(this._element);
 
   num get left;
 
@@ -39594,6 +39391,102 @@
     }
     return val;
   }
+
+  // TODO(jacobr): these methods are duplicated from _RectangleBase in dart:math
+  // Ideally we would provide a RectangleMixin class that provides this implementation.
+  // In an ideal world we would exp
+  /** The x-coordinate of the right edge. */
+  num get right => left + width;
+  /** The y-coordinate of the bottom edge. */
+  num get bottom => top + height;
+
+  String toString() {
+    return 'Rectangle ($left, $top) $width x $height';
+  }
+
+  bool operator ==(other) {
+    if (other is !Rectangle) return false;
+    return left == other.left && top == other.top && right == other.right &&
+        bottom == other.bottom;
+  }
+
+  int get hashCode => _JenkinsSmiHash.hash4(left.hashCode, top.hashCode,
+      right.hashCode, bottom.hashCode);
+
+  /**
+   * Computes the intersection of `this` and [other].
+   *
+   * The intersection of two axis-aligned rectangles, if any, is always another
+   * axis-aligned rectangle.
+   *
+   * Returns the intersection of this and `other`, or `null` if they don't
+   * intersect.
+   */
+  Rectangle<num> intersection(Rectangle<num> other) {
+    var x0 = max(left, other.left);
+    var x1 = min(left + width, other.left + other.width);
+
+    if (x0 <= x1) {
+      var y0 = max(top, other.top);
+      var y1 = min(top + height, other.top + other.height);
+
+      if (y0 <= y1) {
+        return new Rectangle<num>(x0, y0, x1 - x0, y1 - y0);
+      }
+    }
+    return null;
+  }
+
+
+  /**
+   * Returns true if `this` intersects [other].
+   */
+  bool intersects(Rectangle<num> other) {
+    return (left <= other.left + other.width &&
+        other.left <= left + width &&
+        top <= other.top + other.height &&
+        other.top <= top + height);
+  }
+
+  /**
+   * Returns a new rectangle which completely contains `this` and [other].
+   */
+  Rectangle<num> boundingBox(Rectangle<num> other) {
+    var right = max(this.left + this.width, other.left + other.width);
+    var bottom = max(this.top + this.height, other.top + other.height);
+
+    var left = min(this.left, other.left);
+    var top = min(this.top, other.top);
+
+    return new Rectangle<num>(left, top, right - left, bottom - top);
+  }
+
+  /**
+   * Tests whether `this` entirely contains [another].
+   */
+  bool containsRectangle(Rectangle<num> another) {
+    return left <= another.left &&
+           left + width >= another.left + another.width &&
+           top <= another.top &&
+           top + height >= another.top + another.height;
+  }
+
+  /**
+   * Tests whether [another] is inside or along the edges of `this`.
+   */
+  bool containsPoint(Point<num> another) {
+    return another.x >= left &&
+           another.x <= left + width &&
+           another.y >= top &&
+           another.y <= top + height;
+  }
+
+  Point<num> get topLeft => new Point<num>(this.left, this.top);
+  Point<num> get topRight => new Point<num>(this.left + this.width, this.top);
+  Point<num> get bottomRight => new Point<num>(this.left + this.width,
+      this.top + this.height);
+  Point<num> get bottomLeft => new Point<num>(this.left,
+      this.top + this.height);
 }
 
 final _HEIGHT = ['top', 'bottom'];
@@ -39722,11 +39615,11 @@
     _addAll(_element, iterable);
   }
 
-  void removeAll(Iterable<String> iterable) {
+  void removeAll(Iterable<Object> iterable) {
     _removeAll(_element, iterable);
   }
 
-  void retainAll(Iterable<String> iterable) {
+  void retainAll(Iterable<Object> iterable) {
     _removeWhere(_element, iterable.toSet().contains, false);
   }
 
@@ -39981,7 +39874,7 @@
    * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
    */
   Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
-    new _EventStream(e, _eventType, useCapture);
+    new _EventStream<T>(e, _eventType, useCapture);
 
   /**
    * Gets an [ElementEventStream] for this event type, on the specified element.
@@ -40005,7 +39898,7 @@
    * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
    */
   ElementStream<T> forElement(Element e, {bool useCapture: false}) {
-    return new _ElementEventStreamImpl(e, _eventType, useCapture);
+    return new _ElementEventStreamImpl<T>(e, _eventType, useCapture);
   }
 
   /**
@@ -40076,8 +39969,8 @@
   _EventStream(this._target, this._eventType, this._useCapture);
 
   // DOM events are inherently multi-subscribers.
-  Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription),
-                               void onCancel(StreamSubscription subscription)})
+  Stream<T> asBroadcastStream({void onListen(StreamSubscription<T> subscription),
+                               void onCancel(StreamSubscription<T> subscription)})
       => this;
   bool get isBroadcast => true;
 
@@ -40091,6 +39984,11 @@
   }
 }
 
+bool _matchesWithAncestors(Event event, String selector) {
+  var target = event.target;
+  return target is Element ? target.matchesWithAncestors(selector) : false;
+}
+
 /**
  * Adapter for exposing DOM Element events as streams, while also allowing
  * event delegation.
@@ -40101,7 +39999,7 @@
       super(target, eventType, useCapture);
 
   Stream<T> matches(String selector) => this.where(
-      (event) => event.target.matchesWithAncestors(selector)).map((e) {
+      (event) => _matchesWithAncestors(event, selector)).map((e) {
         e._selector = selector;
         return e;
       });
@@ -40125,7 +40023,7 @@
       this._targetList, this._eventType, this._useCapture);
 
   Stream<T> matches(String selector) => this.where(
-      (event) => event.target.matchesWithAncestors(selector)).map((e) {
+      (event) => _matchesWithAncestors(event, selector)).map((e) {
         e._selector = selector;
         return e;
       });
@@ -40135,37 +40033,46 @@
       { Function onError,
         void onDone(),
         bool cancelOnError}) {
-    var pool = new _StreamPool.broadcast();
+    var pool = new _StreamPool<T>.broadcast();
     for (var target in _targetList) {
-      pool.add(new _EventStream(target, _eventType, _useCapture));
+      pool.add(new _EventStream<T>(target, _eventType, _useCapture));
     }
     return pool.stream.listen(onData, onError: onError, onDone: onDone,
           cancelOnError: cancelOnError);
   }
 
   StreamSubscription<T> capture(void onData(T event)) {
-    var pool = new _StreamPool.broadcast();
+    var pool = new _StreamPool<T>.broadcast();
     for (var target in _targetList) {
-      pool.add(new _EventStream(target, _eventType, true));
+      pool.add(new _EventStream<T>(target, _eventType, true));
     }
     return pool.stream.listen(onData);
   }
 
-  Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription),
-                               void onCancel(StreamSubscription subscription)})
+  Stream<T> asBroadcastStream({void onListen(StreamSubscription<T> subscription),
+                               void onCancel(StreamSubscription<T> subscription)})
       => this;
   bool get isBroadcast => true;
 }
 
+// We would like this to just be EventListener<T> but that typdef cannot
+// use generics until dartbug/26276 is fixed.
+typedef _EventListener<T extends Event>(T event);
+
 class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
   int _pauseCount = 0;
   EventTarget _target;
   final String _eventType;
-  var _onData;
+  EventListener _onData;
   final bool _useCapture;
 
-  _EventStreamSubscription(this._target, this._eventType, onData,
-      this._useCapture) : _onData = _wrapZone(onData) {
+  // TODO(jacobr): for full strong mode correctness we should write
+  // _onData = onData == null ? null : _wrapZone/*<Event, dynamic>*/((e) => onData(e as T))
+  // but that breaks 114 co19 tests as well as multiple html tests as it is reasonable
+  // to pass the wrong type of event object to an event listener as part of a
+  // test.
+  _EventStreamSubscription(this._target, this._eventType, void onData(T event),
+      this._useCapture) : _onData = _wrapZone/*<Event, dynamic>*/(onData) {
     _tryResume();
   }
 
@@ -40187,8 +40094,7 @@
     }
     // Remove current event listener.
     _unlisten();
-
-    _onData = _wrapZone(handleData);
+    _onData = _wrapZone/*<Event, dynamic>*/(handleData);
     _tryResume();
   }
 
@@ -40267,8 +40173,8 @@
         onDone: onDone, cancelOnError: cancelOnError);
   }
 
-  Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription),
-                               void onCancel(StreamSubscription subscription)})
+  Stream<T> asBroadcastStream({void onListen(StreamSubscription<T> subscription),
+                               void onCancel(StreamSubscription<T> subscription)})
       => _streamController.stream;
 
   bool get isBroadcast => true;
@@ -40359,16 +40265,16 @@
   const _CustomEventStreamProvider(this._eventTypeGetter);
 
   Stream<T> forTarget(EventTarget e, {bool useCapture: false}) {
-    return new _EventStream(e, _eventTypeGetter(e), useCapture);
+    return new _EventStream<T>(e, _eventTypeGetter(e), useCapture);
   }
 
   ElementStream<T> forElement(Element e, {bool useCapture: false}) {
-    return new _ElementEventStreamImpl(e, _eventTypeGetter(e), useCapture);
+    return new _ElementEventStreamImpl<T>(e, _eventTypeGetter(e), useCapture);
   }
 
   ElementStream<T> _forElementList(ElementList e,
       {bool useCapture: false}) {
-    return new _ElementListEventStreamImpl(e, _eventTypeGetter(e), useCapture);
+    return new _ElementListEventStreamImpl<T>(e, _eventTypeGetter(e), useCapture);
   }
 
   String getEventType(EventTarget target) {
@@ -41747,7 +41653,7 @@
    * The set of keys that have been pressed down without seeing their
    * corresponding keyup event.
    */
-  final List<KeyboardEvent> _keyDownList = <KeyboardEvent>[];
+  final List<KeyEvent> _keyDownList = <KeyEvent>[];
 
   /** The type of KeyEvent we are tracking (keyup, keydown, keypress). */
   final String _type;
@@ -41806,8 +41712,9 @@
    * General constructor, performs basic initialization for our improved
    * KeyboardEvent controller.
    */
-  _KeyboardEventHandler(this._type): super(_EVENT_TYPE),
-      _stream = new _CustomKeyEventStreamImpl('event'), _target = null;
+  _KeyboardEventHandler(this._type):
+      _stream = new _CustomKeyEventStreamImpl('event'), _target = null,
+      super(_EVENT_TYPE);
 
   /**
    * Hook up all event listeners under the covers so we can estimate keycodes
@@ -42115,7 +42022,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
-
 /**
  * Class which helps construct standard node validation policies.
  *
@@ -42133,11 +42039,9 @@
  * appropriate.
  */
 class NodeValidatorBuilder implements NodeValidator {
-
   final List<NodeValidator> _validators = <NodeValidator>[];
 
-  NodeValidatorBuilder() {
-  }
+  NodeValidatorBuilder() {}
 
   /**
    * Creates a new NodeValidatorBuilder which accepts common constructs.
@@ -42266,29 +42170,17 @@
       {UriPolicy uriPolicy,
       Iterable<String> attributes,
       Iterable<String> uriAttributes}) {
-
     var tagNameUpper = tagName.toUpperCase();
-    var attrs;
-    if (attributes != null) {
-      attrs =
-          attributes.map((name) => '$tagNameUpper::${name.toLowerCase()}');
-    }
-    var uriAttrs;
-    if (uriAttributes != null) {
-      uriAttrs =
-          uriAttributes.map((name) => '$tagNameUpper::${name.toLowerCase()}');
-    }
+    var attrs = attributes
+        ?.map /*<String>*/ ((name) => '$tagNameUpper::${name.toLowerCase()}');
+    var uriAttrs = uriAttributes
+        ?.map /*<String>*/ ((name) => '$tagNameUpper::${name.toLowerCase()}');
     if (uriPolicy == null) {
       uriPolicy = new UriPolicy();
     }
 
     add(new _CustomElementNodeValidator(
-        uriPolicy,
-        [tagNameUpper],
-        attrs,
-        uriAttrs,
-        false,
-        true));
+        uriPolicy, [tagNameUpper], attrs, uriAttrs, false, true));
   }
 
   /**
@@ -42303,37 +42195,26 @@
       {UriPolicy uriPolicy,
       Iterable<String> attributes,
       Iterable<String> uriAttributes}) {
-
     var baseNameUpper = baseName.toUpperCase();
     var tagNameUpper = tagName.toUpperCase();
-    var attrs;
-    if (attributes != null) {
-      attrs =
-          attributes.map((name) => '$baseNameUpper::${name.toLowerCase()}');
-    }
-    var uriAttrs;
-    if (uriAttributes != null) {
-      uriAttrs =
-          uriAttributes.map((name) => '$baseNameUpper::${name.toLowerCase()}');
-    }
+    var attrs = attributes
+        ?.map /*<String>*/ ((name) => '$baseNameUpper::${name.toLowerCase()}');
+    var uriAttrs = uriAttributes
+        ?.map /*<String>*/ ((name) => '$baseNameUpper::${name.toLowerCase()}');
     if (uriPolicy == null) {
       uriPolicy = new UriPolicy();
     }
 
-    add(new _CustomElementNodeValidator(
-        uriPolicy,
-        [tagNameUpper, baseNameUpper],
-        attrs,
-        uriAttrs,
-        true,
-        false));
+    add(new _CustomElementNodeValidator(uriPolicy,
+        [tagNameUpper, baseNameUpper], attrs, uriAttrs, true, false));
   }
 
-  void allowElement(String tagName, {UriPolicy uriPolicy,
-    Iterable<String> attributes,
-    Iterable<String> uriAttributes}) {
-
-    allowCustomElement(tagName, uriPolicy: uriPolicy,
+  void allowElement(String tagName,
+      {UriPolicy uriPolicy,
+      Iterable<String> attributes,
+      Iterable<String> uriAttributes}) {
+    allowCustomElement(tagName,
+        uriPolicy: uriPolicy,
         attributes: attributes,
         uriAttributes: uriAttributes);
   }
@@ -42364,8 +42245,8 @@
   }
 
   bool allowsAttribute(Element element, String attributeName, String value) {
-    return _validators.any(
-        (v) => v.allowsAttribute(element, attributeName, value));
+    return _validators
+        .any((v) => v.allowsAttribute(element, attributeName, value));
   }
 }
 
@@ -42376,76 +42257,70 @@
   final UriPolicy uriPolicy;
 
   factory _SimpleNodeValidator.allowNavigation(UriPolicy uriPolicy) {
-    return new _SimpleNodeValidator(uriPolicy,
-      allowedElements: const [
-        'A',
-        'FORM'],
-      allowedAttributes: const [
-        'A::accesskey',
-        'A::coords',
-        'A::hreflang',
-        'A::name',
-        'A::shape',
-        'A::tabindex',
-        'A::target',
-        'A::type',
-        'FORM::accept',
-        'FORM::autocomplete',
-        'FORM::enctype',
-        'FORM::method',
-        'FORM::name',
-        'FORM::novalidate',
-        'FORM::target',
-      ],
-      allowedUriAttributes: const [
-        'A::href',
-        'FORM::action',
-      ]);
+    return new _SimpleNodeValidator(uriPolicy, allowedElements: const [
+      'A',
+      'FORM'
+    ], allowedAttributes: const [
+      'A::accesskey',
+      'A::coords',
+      'A::hreflang',
+      'A::name',
+      'A::shape',
+      'A::tabindex',
+      'A::target',
+      'A::type',
+      'FORM::accept',
+      'FORM::autocomplete',
+      'FORM::enctype',
+      'FORM::method',
+      'FORM::name',
+      'FORM::novalidate',
+      'FORM::target',
+    ], allowedUriAttributes: const [
+      'A::href',
+      'FORM::action',
+    ]);
   }
 
   factory _SimpleNodeValidator.allowImages(UriPolicy uriPolicy) {
-    return new _SimpleNodeValidator(uriPolicy,
-      allowedElements: const [
-        'IMG'
-      ],
-      allowedAttributes: const [
-        'IMG::align',
-        'IMG::alt',
-        'IMG::border',
-        'IMG::height',
-        'IMG::hspace',
-        'IMG::ismap',
-        'IMG::name',
-        'IMG::usemap',
-        'IMG::vspace',
-        'IMG::width',
-      ],
-      allowedUriAttributes: const [
-        'IMG::src',
-      ]);
+    return new _SimpleNodeValidator(uriPolicy, allowedElements: const [
+      'IMG'
+    ], allowedAttributes: const [
+      'IMG::align',
+      'IMG::alt',
+      'IMG::border',
+      'IMG::height',
+      'IMG::hspace',
+      'IMG::ismap',
+      'IMG::name',
+      'IMG::usemap',
+      'IMG::vspace',
+      'IMG::width',
+    ], allowedUriAttributes: const [
+      'IMG::src',
+    ]);
   }
 
   factory _SimpleNodeValidator.allowTextElements() {
-    return new _SimpleNodeValidator(null,
-      allowedElements: const [
-        'B',
-        'BLOCKQUOTE',
-        'BR',
-        'EM',
-        'H1',
-        'H2',
-        'H3',
-        'H4',
-        'H5',
-        'H6',
-        'HR',
-        'I',
-        'LI',
-        'OL',
-        'P',
-        'SPAN',
-        'UL',
-      ]);
+    return new _SimpleNodeValidator(null, allowedElements: const [
+      'B',
+      'BLOCKQUOTE',
+      'BR',
+      'EM',
+      'H1',
+      'H2',
+      'H3',
+      'H4',
+      'H5',
+      'H6',
+      'HR',
+      'I',
+      'LI',
+      'OL',
+      'P',
+      'SPAN',
+      'UL',
+    ]);
   }
 
   /**
@@ -42454,15 +42329,16 @@
    * lowercase attribute name. For example `'IMG:src'`.
    */
   _SimpleNodeValidator(this.uriPolicy,
-      {Iterable<String> allowedElements, Iterable<String> allowedAttributes,
-        Iterable<String> allowedUriAttributes}) {
+      {Iterable<String> allowedElements,
+      Iterable<String> allowedAttributes,
+      Iterable<String> allowedUriAttributes}) {
     this.allowedElements.addAll(allowedElements ?? const []);
     allowedAttributes = allowedAttributes ?? const [];
     allowedUriAttributes = allowedUriAttributes ?? const [];
-    var legalAttributes = allowedAttributes.where(
-        (x) => !_Html5NodeValidator._uriAttributes.contains(x));
-    var extraUriAttributes = allowedAttributes.where(
-        (x) => _Html5NodeValidator._uriAttributes.contains(x));
+    var legalAttributes = allowedAttributes
+        .where((x) => !_Html5NodeValidator._uriAttributes.contains(x));
+    var extraUriAttributes = allowedAttributes
+        .where((x) => _Html5NodeValidator._uriAttributes.contains(x));
     this.allowedAttributes.addAll(legalAttributes);
     this.allowedUriAttributes.addAll(allowedUriAttributes);
     this.allowedUriAttributes.addAll(extraUriAttributes);
@@ -42495,19 +42371,19 @@
   final bool allowTypeExtension;
   final bool allowCustomTag;
 
-  _CustomElementNodeValidator(UriPolicy uriPolicy,
+  _CustomElementNodeValidator(
+      UriPolicy uriPolicy,
       Iterable<String> allowedElements,
       Iterable<String> allowedAttributes,
       Iterable<String> allowedUriAttributes,
       bool allowTypeExtension,
-      bool allowCustomTag):
-
-      super(uriPolicy,
-          allowedElements: allowedElements,
-          allowedAttributes: allowedAttributes,
-          allowedUriAttributes: allowedUriAttributes),
-      this.allowTypeExtension = allowTypeExtension == true,
-      this.allowCustomTag = allowCustomTag == true;
+      bool allowCustomTag)
+      : this.allowTypeExtension = allowTypeExtension == true,
+        this.allowCustomTag = allowCustomTag == true,
+        super(uriPolicy,
+            allowedElements: allowedElements,
+            allowedAttributes: allowedAttributes,
+            allowedUriAttributes: allowedUriAttributes);
 
   bool allowsElement(Element element) {
     if (allowTypeExtension) {
@@ -42517,12 +42393,14 @@
             allowedElements.contains(Element._safeTagName(element));
       }
     }
-    return allowCustomTag && allowedElements.contains(Element._safeTagName(element));
+    return allowCustomTag &&
+        allowedElements.contains(Element._safeTagName(element));
   }
 
   bool allowsAttribute(Element element, String attributeName, String value) {
-   if (allowsElement(element)) {
-      if (allowTypeExtension && attributeName == 'is' &&
+    if (allowsElement(element)) {
+      if (allowTypeExtension &&
+          attributeName == 'is' &&
           allowedElements.contains(value.toUpperCase())) {
         return true;
       }
@@ -42533,19 +42411,22 @@
 }
 
 class _TemplatingNodeValidator extends _SimpleNodeValidator {
-  static const _TEMPLATE_ATTRS =
-      const <String>['bind', 'if', 'ref', 'repeat', 'syntax'];
+  static const _TEMPLATE_ATTRS = const <String>[
+    'bind',
+    'if',
+    'ref',
+    'repeat',
+    'syntax'
+  ];
 
   final Set<String> _templateAttrs;
 
-  _TemplatingNodeValidator():
-      super(null,
-          allowedElements: [
-            'TEMPLATE'
-          ],
-          allowedAttributes: _TEMPLATE_ATTRS.map((attr) => 'TEMPLATE::$attr')),
-      _templateAttrs = new Set<String>.from(_TEMPLATE_ATTRS) {
-  }
+  _TemplatingNodeValidator()
+      : _templateAttrs = new Set<String>.from(_TEMPLATE_ATTRS),
+        super(null,
+            allowedElements: ['TEMPLATE'],
+            allowedAttributes:
+                _TEMPLATE_ATTRS.map((attr) => 'TEMPLATE::$attr')) {}
 
   bool allowsAttribute(Element element, String attributeName, String value) {
     if (super.allowsAttribute(element, attributeName, value)) {
@@ -42556,14 +42437,13 @@
       return true;
     }
 
-    if (element.attributes['template'] == "" ) {
+    if (element.attributes['template'] == "") {
       return _templateAttrs.contains(attributeName);
     }
     return false;
   }
 }
 
-
 class _SvgNodeValidator implements NodeValidator {
   bool allowsElement(Element element) {
     if (element is svg.ScriptElement) {
@@ -42573,7 +42453,8 @@
     // foreignobject tag as SvgElement. We don't want foreignobject contents
     // anyway, so just remove the whole tree outright. And we can't rely
     // on IE recognizing the SvgForeignObject type, so go by tagName. Bug 23144
-    if (element is svg.SvgElement && Element._safeTagName(element) == 'foreignObject') {
+    if (element is svg.SvgElement &&
+        Element._safeTagName(element) == 'foreignObject') {
       return false;
     }
     if (element is svg.SvgElement) {
@@ -42625,7 +42506,7 @@
  */
 class _WrappedList<E extends Node> extends ListBase<E>
     implements NodeListWrapper {
-  final List _list;
+  final List<Node> _list;
 
   _WrappedList(this._list);
 
@@ -42645,13 +42526,13 @@
 
   // List APIs
 
-  E operator [](int index) => _list[index];
+  E operator [](int index) => _downcast/*<Node, E>*/(_list[index]);
 
   void operator []=(int index, E value) { _list[index] = value; }
 
   set length(int newLength) { _list.length = newLength; }
 
-  void sort([int compare(E a, E b)]) { _list.sort(compare); }
+  void sort([int compare(E a, E b)]) { _list.sort((Node a, Node b) => compare(_downcast/*<Node, E>*/(a), _downcast/*<Node, E>*/(b))); }
 
   int indexOf(Object element, [int start = 0]) => _list.indexOf(element, start);
 
@@ -42659,7 +42540,7 @@
 
   void insert(int index, E element) => _list.insert(index, element);
 
-  E removeAt(int index) => _list.removeAt(index);
+  E removeAt(int index) => _downcast/*<Node, E>*/(_list.removeAt(index));
 
   void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
     _list.setRange(start, end, iterable, skipCount);
@@ -42681,8 +42562,8 @@
 /**
  * Iterator wrapper for _WrappedList.
  */
-class _WrappedIterator<E> implements Iterator<E> {
-  Iterator _iterator;
+class _WrappedIterator<E extends Node> implements Iterator<E> {
+  Iterator<Node> _iterator;
 
   _WrappedIterator(this._iterator);
 
@@ -42690,8 +42571,11 @@
     return _iterator.moveNext();
   }
 
-  E get current => _iterator.current;
+  E get current => _downcast/*<Node, E>*/(_iterator.current);
 }
+
+// ignore: STRONG_MODE_DOWN_CAST_COMPOSITE
+/*=To*/ _downcast/*<From, To extends From>*/(dynamic /*=From*/ x) => x;
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
@@ -43069,7 +42953,7 @@
   Events get on => throw new UnsupportedError(
     'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
-  void _addEventListener([String type, EventListener listener, bool useCapture])
+  void _addEventListener(String type, EventListener listener, [bool useCapture])
       => throw new UnsupportedError(
     'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
@@ -43080,8 +42964,8 @@
   bool dispatchEvent(Event event) => throw new UnsupportedError(
     'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
-  void _removeEventListener([String type, EventListener listener,
-      bool useCapture]) => throw new UnsupportedError(
+  void _removeEventListener(String type, EventListener listener,
+      [bool useCapture]) => throw new UnsupportedError(
     'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
   void removeEventListener(String type, EventListener listener,
@@ -43448,8 +43332,8 @@
       throw new UnsupportedError('Cannot call matchingTarget if this Event did'
           ' not arise as a result of event delegation.');
     }
-    var currentTarget = this.currentTarget;
-    var target = this.target;
+    Element currentTarget = this.currentTarget;
+    Element target = this.target;
     var matchedTarget;
     do {
       if (target.matches(_selector)) return target;
@@ -43480,17 +43364,25 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
-_wrapZone(callback(arg)) {
+// TODO(jacobr): remove these typedefs when dart:async supports generic types.
+typedef R _wrapZoneCallback<A, R>(A a);
+typedef R _wrapZoneBinaryCallback<A, B, R>(A a, B b);
+
+_wrapZoneCallback/*<A, R>*/ _wrapZone/*<A, R>*/(_wrapZoneCallback/*<A, R>*/ callback) {
   // For performance reasons avoid wrapping if we are in the root zone.
   if (Zone.current == Zone.ROOT) return callback;
   if (callback == null) return null;
-  return Zone.current.bindUnaryCallback(callback, runGuarded: true);
+  // TODO(jacobr): we cast to _wrapZoneCallback/*<A, R>*/ to hack around missing
+  // generic method support in zones.
+  return Zone.current.bindUnaryCallback(callback, runGuarded: true) as _wrapZoneCallback/*<A, R>*/;
 }
 
-_wrapBinaryZone(callback(arg1, arg2)) {
+_wrapZoneBinaryCallback/*<A, B, R>*/ _wrapBinaryZone/*<A, B, R>*/(_wrapZoneBinaryCallback/*<A, B, R>*/ callback) {
   if (Zone.current == Zone.ROOT) return callback;
   if (callback == null) return null;
-  return Zone.current.bindBinaryCallback(callback, runGuarded: true);
+  // We cast to _wrapZoneBinaryCallback/*<A, B, R>*/ to hack around missing
+  // generic method support in zones.
+  return Zone.current.bindBinaryCallback(callback, runGuarded: true) as _wrapZoneBinaryCallback/*<A, B, R>*/;
 }
 
 /**
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 30f39f7..78de601 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -401,7 +401,6 @@
   'MimeType': () => MimeType.instanceRuntimeType,
   'MimeTypeArray': () => MimeTypeArray.instanceRuntimeType,
   'MouseEvent': () => MouseEvent.instanceRuntimeType,
-  'MutationEvent': () => _MutationEvent.instanceRuntimeType,
   'MutationObserver': () => MutationObserver.instanceRuntimeType,
   'MutationRecord': () => MutationRecord.instanceRuntimeType,
   'NamedNodeMap': () => _NamedNodeMap.instanceRuntimeType,
@@ -806,12 +805,12 @@
    */
   @DomName('AbstractWorker.errorEvent')
   @DocsEditable()
-  static const EventStreamProvider<ErrorEvent> errorEvent = const EventStreamProvider<ErrorEvent>('error');
+  static const EventStreamProvider<Event> errorEvent = const EventStreamProvider<Event>('error');
 
   /// Stream of `error` events handled by this [AbstractWorker].
   @DomName('AbstractWorker.onerror')
   @DocsEditable()
-  Stream<ErrorEvent> get onError => errorEvent.forTarget(this);
+  Stream<Event> get onError => errorEvent.forTarget(this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -829,7 +828,7 @@
   @DomName('HTMLAnchorElement.HTMLAnchorElement')
   @DocsEditable()
   factory AnchorElement({String href}) {
-    var e = document.createElement("a");
+    AnchorElement e = document.createElement("a");
     if (href != null) e.href = href;
     return e;
   }
@@ -3058,7 +3057,7 @@
   @DomName('HTMLCanvasElement.HTMLCanvasElement')
   @DocsEditable()
   factory CanvasElement({int width, int height}) {
-    var e = document.createElement("canvas");
+    CanvasElement e = document.createElement("canvas");
     if (width != null) e.width = width;
     if (height != null) e.height = height;
     return e;
@@ -4462,7 +4461,7 @@
     if (view == null) {
       view = window;
     }
-    var e = document._createEvent("CompositionEvent");
+    CompositionEvent e = document._createEvent("CompositionEvent");
 
       e._initCompositionEvent(type, canBubble, cancelable, view, data);
 
@@ -9763,7 +9762,7 @@
   factory DeviceOrientationEvent(String type,
       {bool canBubble: true, bool cancelable: true, num alpha: 0, num beta: 0,
       num gamma: 0, bool absolute: false}) {
-    var e = document._createEvent("DeviceOrientationEvent");
+    DeviceOrientationEvent e = document._createEvent("DeviceOrientationEvent");
     e._initDeviceOrientationEvent(type, canBubble, cancelable, alpha, beta,
         gamma, absolute);
     return e;
@@ -10324,7 +10323,7 @@
   @DomName('Document.visibilityState')
   @DocsEditable()
   @Experimental() // untriaged
-  String get visibilityState => _blink.BlinkDocument.instance.visibilityState_Getter_(this);
+  String get _visibilityState => _blink.BlinkDocument.instance.visibilityState_Getter_(this);
   
   @DomName('Document.webkitFullscreenElement')
   @DocsEditable()
@@ -10939,9 +10938,8 @@
    * For details about CSS selector syntax, see the
    * [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
    */
-  ElementList<Element> querySelectorAll(String selectors) {
-    return new _FrozenElementList._wrap(_querySelectorAll(selectors));
-  }
+  ElementList<Element /*=T*/> querySelectorAll/*<T extends Element>*/(String selectors) =>
+    new _FrozenElementList/*<T>*/._wrap(_querySelectorAll(selectors));
 
   /**
    * Alias for [querySelector]. Note this function is deprecated because its
@@ -10959,7 +10957,7 @@
   @deprecated
   @Experimental()
   @DomName('Document.querySelectorAll')
-  ElementList<Element> queryAll(String relativeSelectors) =>
+  ElementList<Element /*=T*/> queryAll/*<T extends Element>*/(String relativeSelectors) =>
       querySelectorAll(relativeSelectors);
 
   /// Checks if [registerElement] is supported on the current platform.
@@ -10986,6 +10984,13 @@
       _blink.BlinkDocument.instance.createElementNS_Callback_3_(this, namespaceURI, qualifiedName, typeExtension);    
   }
 
+
+  @DomName('Document.visibilityState')
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.FIREFOX)
+  @SupportedBrowser(SupportedBrowser.IE, '10')
+  @Experimental()
+  String get visibilityState => _visibilityState;
 }
 // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -11024,7 +11029,7 @@
 
   set children(List<Element> value) {
     // Copy list first since we don't want liveness during iteration.
-    List copy = new List.from(value);
+    var copy = value.toList();
     var children = this.children;
     children.clear();
     children.addAll(copy);
@@ -11041,8 +11046,9 @@
    * For details about CSS selector syntax, see the
    * [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
    */
-  ElementList<Element> querySelectorAll(String selectors) =>
-    new _FrozenElementList._wrap(_querySelectorAll(selectors));
+  ElementList<Element /*=T*/> querySelectorAll/*<T extends Element>*/(String selectors) =>
+    new _FrozenElementList/*<T>*/._wrap(_querySelectorAll(selectors));
+
 
   String get innerHtml {
     final e = new Element.tag("div");
@@ -11099,9 +11105,8 @@
   @deprecated
   @Experimental()
   @DomName('DocumentFragment.querySelectorAll')
-  ElementList<Element> queryAll(String relativeSelectors) {
-    return querySelectorAll(relativeSelectors);
-  }
+  ElementList<Element /*=T*/> queryAll/*<T extends Element>*/(String relativeSelectors) =>
+    querySelectorAll(relativeSelectors);
   // To suppress missing implicit constructor warnings.
   factory DocumentFragment._() { throw new UnsupportedError("Not supported"); }
 
@@ -12481,7 +12486,7 @@
     _filter(test, true);
   }
 
-  void _filter(bool test(var element), bool retainMatching) {
+  void _filter(bool test(Element element), bool retainMatching) {
     var removed;
     if (retainMatching) {
       removed = _element.children.where((e) => !test(e));
@@ -13136,8 +13141,8 @@
 // declared to return `ElementList`.  This provides all the static analysis
 // benefit so there is no need for this class have a constrained type parameter.
 //
-class _FrozenElementList extends ListBase
-    implements ElementList, NodeListWrapper {
+class _FrozenElementList<E extends Element> extends ListBase<E>
+    implements ElementList<E>, NodeListWrapper {
   final List<Node> _nodeList;
 
   var dartClass_instance;
@@ -13148,9 +13153,9 @@
 
   int get length => _nodeList.length;
 
-  Element operator [](int index) => _nodeList[index];
+  E operator [](int index) => _downcast/*<Node, E>*/(_nodeList[index]);
 
-  void operator []=(int index, Element value) {
+  void operator []=(int index, E value) {
     throw new UnsupportedError('Cannot modify list');
   }
 
@@ -13158,7 +13163,7 @@
     throw new UnsupportedError('Cannot modify list');
   }
 
-  void sort([Comparator<Element> compare]) {
+  void sort([Comparator<E> compare]) {
     throw new UnsupportedError('Cannot sort list');
   }
 
@@ -13166,11 +13171,11 @@
     throw new UnsupportedError('Cannot shuffle list');
   }
 
-  Element get first => _nodeList.first;
+  E get first => _downcast/*<Node, E>*/(_nodeList.first);
 
-  Element get last => _nodeList.last;
+  E get last => _downcast/*<Node, E>*/(_nodeList.last);
 
-  Element get single => _nodeList.single;
+  E get single => _downcast/*<Node, E>*/(_nodeList.single);
 
   CssClassSet get classes => new _MultiElementCssClassSet(this);
 
@@ -13184,7 +13189,7 @@
     //
     // as the code below converts the Iterable[value] to a string multiple
     // times.  Maybe compute the string and set className here.
-    _nodeList.forEach((e) => e.classes = value);
+    forEach((e) => e.classes = value);
   }
 
   CssRect get contentEdge => new _ContentCssListRect(this);
@@ -13927,7 +13932,7 @@
 
   set children(List<Element> value) {
     // Copy list first since we don't want liveness during iteration.
-    List copy = new List.from(value);
+    var copy = value.toList();
     var children = this.children;
     children.clear();
     children.addAll(copy);
@@ -13945,8 +13950,8 @@
    * [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
    */
   @DomName('Element.querySelectorAll')
-  ElementList<Element> querySelectorAll(String selectors) =>
-    new _FrozenElementList._wrap(_querySelectorAll(selectors));
+  ElementList<Element /*=T*/> querySelectorAll/*<T extends Element>*/(String selectors) =>
+    new _FrozenElementList/*<T>*/._wrap(_querySelectorAll(selectors));
 
   /**
    * Alias for [querySelector]. Note this function is deprecated because its
@@ -13964,7 +13969,7 @@
   @deprecated
   @DomName('Element.querySelectorAll')
   @Experimental()
-  ElementList<Element> queryAll(String relativeSelectors) =>
+  ElementList<Element /*=T*/> queryAll/*<T extends Element>*/(String relativeSelectors) =>
       querySelectorAll(relativeSelectors);
 
   /**
@@ -14162,15 +14167,14 @@
       throw new ArgumentError("The frames parameter should be a List of Maps "
           "with frame information");
     }
-    var convertedFrames = frames;
-    if (convertedFrames is Iterable) {
+    var convertedFrames;
+    if (frames is Iterable) {
       convertedFrames = convertDartToNative_List(
           frames.map(convertDartToNative_Dictionary).toList());
+    } else {
+      convertedFrames = frames;
     }
-    var convertedTiming = timing;
-    if (convertedTiming is Map) {
-      convertedTiming = convertDartToNative_Dictionary(convertedTiming);
-    }
+    var convertedTiming = timing is Map ? convertDartToNative_Dictionary(timing) : timing;
     return convertedTiming == null
       ? _animate(convertedFrames)
       : _animate(convertedFrames, convertedTiming);
@@ -14498,7 +14502,7 @@
 
       // Workaround for Safari bug. Was also previously Chrome bug 229142
       // - URIs are not resolved in new doc.
-      var base = _parseDocument.createElement('base');
+      BaseElement base = _parseDocument.createElement('base');
       base.href = document.baseUri;
       _parseDocument.head.append(base);
     }
@@ -16640,7 +16644,7 @@
     e._initEvent(name, canBubble, cancelable);
     return e;
   }
-  
+
   /** The CSS selector involved with event delegation. */
   String _selector;
 
@@ -16654,8 +16658,8 @@
       throw new UnsupportedError('Cannot call matchingTarget if this Event did'
           ' not arise as a result of event delegation.');
     }
-    var currentTarget = this.currentTarget;
-    var target = this.target;
+    Element currentTarget = this.currentTarget;
+    Element target = this.target;
     var matchedTarget;
     do {
       if (target.matches(_selector)) return target;
@@ -16945,26 +16949,24 @@
 }
 
 class ElementEvents extends Events {
-  /* Raw event target. */
-  final Element _ptr;
   static final webkitEvents = {
-    'animationend' : 'webkitAnimationEnd', 
-    'animationiteration' : 'webkitAnimationIteration', 
-    'animationstart' : 'webkitAnimationStart', 
-    'fullscreenchange' : 'webkitfullscreenchange', 
+    'animationend' : 'webkitAnimationEnd',
+    'animationiteration' : 'webkitAnimationIteration',
+    'animationstart' : 'webkitAnimationStart',
+    'fullscreenchange' : 'webkitfullscreenchange',
     'fullscreenerror' : 'webkitfullscreenerror',
-    'keyadded' : 'webkitkeyadded', 
-    'keyerror' : 'webkitkeyerror', 
-    'keymessage' : 'webkitkeymessage', 
-    'needkey' : 'webkitneedkey', 
-    'pointerlockchange' : 'webkitpointerlockchange', 
-    'pointerlockerror' : 'webkitpointerlockerror', 
-    'resourcetimingbufferfull' : 'webkitresourcetimingbufferfull', 
+    'keyadded' : 'webkitkeyadded',
+    'keyerror' : 'webkitkeyerror',
+    'keymessage' : 'webkitkeymessage',
+    'needkey' : 'webkitneedkey',
+    'pointerlockchange' : 'webkitpointerlockchange',
+    'pointerlockerror' : 'webkitpointerlockerror',
+    'resourcetimingbufferfull' : 'webkitresourcetimingbufferfull',
     'transitionend': 'webkitTransitionEnd',
     'speechchange' : 'webkitSpeechChange'
   };
 
-  ElementEvents(Element ptr) : this._ptr = ptr, super(ptr);
+  ElementEvents(Element ptr) : super(ptr);
 
   Stream operator [](String type) {
     if (webkitEvents.keys.contains(type.toLowerCase())) {
@@ -18707,7 +18709,10 @@
     }
 
     int watchId;
-    var controller;
+    // TODO(jacobr): it seems like a bug that we have to specifiy the static
+    // type here for controller.stream to have the right type.
+    // dartbug.com/26278
+    StreamController<Geoposition> controller;
     controller = new StreamController<Geoposition>(sync: true,
       onListen: () {
         assert(watchId == null);
@@ -19758,11 +19763,11 @@
 
   @DomName('HTMLCollection.item')
   @DocsEditable()
-  Element item(int index) => _blink.BlinkHTMLCollection.instance.item_Callback_1_(this, index);
+  Node item(int index) => _blink.BlinkHTMLCollection.instance.item_Callback_1_(this, index);
   
   @DomName('HTMLCollection.namedItem')
   @DocsEditable()
-  Element namedItem(String name) => _blink.BlinkHTMLCollection.instance.namedItem_Callback_1_(this, name);
+  Object namedItem(String name) => (_blink.BlinkHTMLCollection.instance.namedItem_Callback_1_(this, name));
   
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -19894,59 +19899,6 @@
     _webkitExitFullscreen();
   }
 
-  /**
-   * Returns the element, if any, that is currently displayed in fullscreen.
-   *
-   * Returns null if there is currently no fullscreen element. You can use
-   * this to determine if the page is in fullscreen mode.
-   *
-   *     myVideo = new VideoElement();
-   *     if (document.fullscreenElement == null) {
-   *       myVideo.requestFullscreen();
-   *       print(document.fullscreenElement == myVideo); // true
-   *     }
-   *
-   * ## Other resources
-   *
-   * * [Using the fullscreen
-   *   API](http://docs.webplatform.org/wiki/tutorials/using_the_full-screen_api)
-   *   from WebPlatform.org.
-   * * [Fullscreen specification](http://www.w3.org/TR/fullscreen/) from W3C.
-   */
-  @DomName('Document.webkitFullscreenElement')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  Element get fullscreenElement => _webkitFullscreenElement;
-
-  /**
-   * Returns true if this document can display elements in fullscreen mode.
-   *
-   * ## Other resources
-   *
-   * * [Using the fullscreen
-   *   API](http://docs.webplatform.org/wiki/tutorials/using_the_full-screen_api)
-   *   from WebPlatform.org.
-   * * [Fullscreen specification](http://www.w3.org/TR/fullscreen/) from W3C.
-   */
-  @DomName('Document.webkitFullscreenEnabled')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  bool get fullscreenEnabled => _webkitFullscreenEnabled;
-
-  @DomName('Document.webkitHidden')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  bool get hidden => _webkitHidden;
-
-  @DomName('Document.visibilityState')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.FIREFOX)
-  @SupportedBrowser(SupportedBrowser.IE, '10')
-  @Experimental()
-  String get visibilityState => _webkitVisibilityState;
 
   /**
    * Internal routine to find the DOM JS class name being extended for custom
@@ -22126,7 +22078,7 @@
   @DomName('HTMLImageElement.HTMLImageElement')
   @DocsEditable()
   factory ImageElement({String src, int width, int height}) {
-    var e = document.createElement("img");
+    ImageElement e = document.createElement("img");
     if (src != null) e.src = src;
     if (width != null) e.width = width;
     if (height != null) e.height = height;
@@ -22335,7 +22287,7 @@
     ButtonInputElement {
 
   factory InputElement({String type}) {
-    var e = document.createElement("input");
+    InputElement e = document.createElement("input");
     if (type != null) {
       try {
         // IE throws an exception for unknown types.
@@ -25910,11 +25862,11 @@
   factory MessageEvent(String type,
       {bool canBubble: false, bool cancelable: false, Object data,
       String origin, String lastEventId,
-      Window source, List messagePorts}) {
+      Window source, List<MessagePort> messagePorts}) {
     if (source == null) {
       source = window;
     }
-    var event = document._createEvent("MessageEvent");
+    MessageEvent event = document._createEvent("MessageEvent");
     event._initMessageEvent(type, canBubble, cancelable, data, origin,
         lastEventId, source, messagePorts);
     return event;
@@ -26849,20 +26801,6 @@
   @deprecated
   Node get toElement => _blink.BlinkMouseEvent.instance.toElement_Getter_(this);
   
-  @DomName('MouseEvent.webkitMovementX')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  int get _webkitMovementX => _blink.BlinkMouseEvent.instance.webkitMovementX_Getter_(this);
-  
-  @DomName('MouseEvent.webkitMovementY')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  int get _webkitMovementY => _blink.BlinkMouseEvent.instance.webkitMovementY_Getter_(this);
-  
   @DomName('MouseEvent.which')
   @DocsEditable()
   @Experimental() // untriaged
@@ -26897,9 +26835,9 @@
   @DomName('MouseEvent.movementX')
   @DomName('MouseEvent.movementY')
   @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @SupportedBrowser(SupportedBrowser.FIREFOX)
   @Experimental()
-  Point get movement => new Point(_webkitMovementX, _webkitMovementY);
+  Point get movement => new Point(_movementX, _movementY);
 
   /**
    * The coordinates of the mouse pointer in target node coordinates.
@@ -27789,7 +27727,7 @@
   set nodes(Iterable<Node> value) {
     // Copy list first since we don't want liveness during iteration.
     // TODO(jacobr): there is a better way to do this.
-    List copy = new List.from(value);
+    var copy = value.toList();
     text = '';
     for (Node node in copy) {
       append(node);
@@ -32917,8 +32855,7 @@
   // Override default options, since IE returns SelectElement itself and it
   // does not operate as a List.
   List<OptionElement> get options {
-    var options = this.querySelectorAll('option').where(
-        (e) => e is OptionElement).toList();
+    var options = new List<OptionElement>.from(this.querySelectorAll('option'));
     return new UnmodifiableListView(options);
   }
 
@@ -35123,11 +35060,11 @@
   }
 
   // TODO(nweiz): update this when maps support lazy iteration
-  bool containsValue(String value) => values.any((e) => e == value);
+  bool containsValue(Object value) => values.any((e) => e == value);
 
-  bool containsKey(String key) => _getItem(key) != null;
+  bool containsKey(Object key) => _getItem(key) != null;
 
-  String operator [](String key) => _getItem(key);
+  String operator [](Object key) => _getItem(key);
 
   void operator []=(String key, String value) { _setItem(key, value); }
 
@@ -35136,7 +35073,7 @@
     return this[key];
   }
 
-  String remove(String key) {
+  String remove(Object key) {
     final value = this[key];
     _removeItem(key);
     return value;
@@ -35154,13 +35091,13 @@
   }
 
   Iterable<String> get keys {
-    final keys = [];
+    final keys = <String>[];
     forEach((k, v) => keys.add(k));
     return keys;
   }
 
   Iterable<String> get values {
-    final values = [];
+    final values = <String>[];
     forEach((k, v) => values.add(v));
     return values;
   }
@@ -35262,7 +35199,7 @@
     {bool canBubble: false, bool cancelable: false, String key, String oldValue,
     String newValue, String url, Storage storageArea}) {
 
-    var e = document._createEvent("StorageEvent");
+    StorageEvent e = document._createEvent("StorageEvent");
     e._initStorageEvent(type, canBubble, cancelable, key, oldValue,
         newValue, url, storageArea);
     return e;
@@ -36407,7 +36344,7 @@
     if (view == null) {
       view = window;
     }
-    var e = document._createEvent("TextEvent");
+    TextEvent e = document._createEvent("TextEvent");
     e._initTextEvent(type, canBubble, cancelable, view, data);
     return e;
   }
@@ -37090,7 +37027,7 @@
     if (view == null) {
       view = window;
     }
-    var e = document._createEvent("TouchEvent");
+    TouchEvent e = document._createEvent("TouchEvent");
     e._initTouchEvent(touches, targetTouches, changedTouches, type, view,
         screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey);
     return e;
@@ -37606,7 +37543,7 @@
     if (view == null) {
       view = window;
     }
-    final e = document._createEvent("UIEvent");
+    UIEvent e = document._createEvent("UIEvent");
     e._initUIEvent(type, canBubble, cancelable, view, detail);
     return e;
   }
@@ -41741,16 +41678,6 @@
   @Experimental() // untriaged
   String get nodeValue => _blink.BlinkAttr.instance.nodeValue_Getter_(this);
   
-  @DomName('Attr.textContent')
-  @DocsEditable()
-  @Experimental() // untriaged
-  String get text => _blink.BlinkAttr.instance.textContent_Getter_(this);
-  
-  @DomName('Attr.textContent')
-  @DocsEditable()
-  @Experimental() // untriaged
-  set text(String value) => _blink.BlinkAttr.instance.textContent_Setter_(this, value);
-  
   @DomName('Attr.value')
   @DocsEditable()
   String get value => _blink.BlinkAttr.instance.value_Getter_(this);
@@ -42699,36 +42626,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-
-@DomName('MutationEvent')
-// http://www.w3.org/TR/DOM-Level-3-Events/#events-mutationevents
-@deprecated
-class _MutationEvent extends Event {
-  factory _MutationEvent(String type,
-      {bool canBubble: false, bool cancelable: false, Node relatedNode,
-      String prevValue, String newValue, String attrName, int attrChange: 0}) {
-
-    var event = document._createEvent('MutationEvent');
-    event._initMutationEvent(type, canBubble, cancelable, relatedNode,
-        prevValue, newValue, attrName, attrChange);
-    return event;
-  }
-  // To suppress missing implicit constructor warnings.
-  factory _MutationEvent._() { throw new UnsupportedError("Not supported"); }
-
-
-  @Deprecated("Internal Use Only")
-  external static Type get instanceRuntimeType;
-
-  @Deprecated("Internal Use Only")
-  _MutationEvent.internal_() : super.internal_();
-
-
-}
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
 // WARNING: Do not edit - generated code.
 
 
@@ -43378,7 +43275,7 @@
     other.forEach((k, v) { this[k] = v; });
   }
 
-  bool containsValue(String value) {
+  bool containsValue(Object value) {
     for (var v in this.values) {
       if (value == v) {
         return true;
@@ -43410,10 +43307,11 @@
   Iterable<String> get keys {
     // TODO: generate a lazy collection instead.
     var attributes = _element._attributes;
-    var keys = new List<String>();
+    var keys = <String>[];
     for (int i = 0, len = attributes.length; i < len; i++) {
-      if (_matches(attributes[i])) {
-        keys.add(attributes[i].name);
+      _Attr attr = attributes[i];
+      if (_matches(attr)) {
+        keys.add(attr.name);
       }
     }
     return keys;
@@ -43422,10 +43320,11 @@
   Iterable<String> get values {
     // TODO: generate a lazy collection instead.
     var attributes = _element._attributes;
-    var values = new List<String>();
+    var values = <String>[];
     for (int i = 0, len = attributes.length; i < len; i++) {
-      if (_matches(attributes[i])) {
-        values.add(attributes[i].value);
+      _Attr attr = attributes[i];
+      if (_matches(attr)) {
+        values.add(attr.value);
       }
     }
     return values;
@@ -43456,11 +43355,11 @@
 
   _ElementAttributeMap(Element element): super(element);
 
-  bool containsKey(String key) {
+  bool containsKey(Object key) {
     return _element._hasAttribute(key);
   }
 
-  String operator [](String key) {
+  String operator [](Object key) {
     return _element.getAttribute(key);
   }
 
@@ -43468,7 +43367,7 @@
     _element.setAttribute(key, value);
   }
 
-  String remove(String key) {
+  String remove(Object key) {
     String value = _element.getAttribute(key);
     _element._removeAttribute(key);
     return value;
@@ -43493,11 +43392,11 @@
 
   _NamespacedAttributeMap(Element element, this._namespace): super(element);
 
-  bool containsKey(String key) {
+  bool containsKey(Object key) {
     return _element._hasAttributeNS(_namespace, key);
   }
 
-  String operator [](String key) {
+  String operator [](Object key) {
     return _element.getAttributeNS(_namespace, key);
   }
 
@@ -43505,7 +43404,7 @@
     _element.setAttributeNS(_namespace, key, value);
   }
 
-  String remove(String key) {
+  String remove(Object key) {
     String value = this[key];
     _element._removeAttributeNS(_namespace, key);
     return value;
@@ -43539,11 +43438,11 @@
   }
 
   // TODO: Use lazy iterator when it is available on Map.
-  bool containsValue(String value) => values.any((v) => v == value);
+  bool containsValue(Object value) => values.any((v) => v == value);
 
-  bool containsKey(String key) => _attributes.containsKey(_attr(key));
+  bool containsKey(Object key) => _attributes.containsKey(_attr(key));
 
-  String operator [](String key) => _attributes[_attr(key)];
+  String operator [](Object key) => _attributes[_attr(key)];
 
   void operator []=(String key, String value) {
     _attributes[_attr(key)] = value;
@@ -43552,7 +43451,7 @@
   String putIfAbsent(String key, String ifAbsent()) =>
     _attributes.putIfAbsent(_attr(key), ifAbsent);
 
-  String remove(String key) => _attributes.remove(_attr(key));
+  String remove(Object key) => _attributes.remove(_attr(key));
 
   void clear() {
     // Needs to operate on a snapshot since we are mutating the collection.
@@ -43570,7 +43469,7 @@
   }
 
   Iterable<String> get keys {
-    final keys = new List<String>();
+    final keys = <String>[];
     _attributes.forEach((String key, String value) {
       if (_matches(key)) {
         keys.add(_strip(key));
@@ -43580,7 +43479,7 @@
   }
 
   Iterable<String> get values {
-    final values = new List<String>();
+    final values = <String>[];
     _attributes.forEach((String key, String value) {
       if (_matches(key)) {
         values.add(value);
@@ -43811,7 +43710,7 @@
    * * [Cross-document messaging](https://html.spec.whatwg.org/multipage/comms.html#web-messaging)
    *   from WHATWG.
    */
-  void postMessage(var message, String targetOrigin, [List messagePorts]);
+  void postMessage(var message, String targetOrigin, [List<MessagePort> messagePorts]);
 }
 
 abstract class LocationBase {
@@ -43865,7 +43764,7 @@
    * [value] must be a valid 'token' representing a single class, i.e. a
    * non-empty string containing no whitespace.
    */
-  bool contains(String value);
+  bool contains(Object value);
 
   /**
    * Add the class [value] to element.
@@ -43917,7 +43816,7 @@
    * Each element of [iterable] must be a valid 'token' representing a single
    * class, i.e. a non-empty string containing no whitespace.
    */
-  void removeAll(Iterable<String> iterable);
+  void removeAll(Iterable<Object> iterable);
 
   /**
    * Toggles all classes specified in [iterable] on element.
@@ -44033,7 +43932,7 @@
  */
 class _ContentCssRect extends CssRect {
 
-  _ContentCssRect(element) : super(element);
+  _ContentCssRect(Element element) : super(element);
 
   num get height => _element.offsetHeight +
       _addOrSubtractToBoxModel(_HEIGHT, _CONTENT);
@@ -44054,9 +43953,11 @@
     if (newHeight is Dimension) {
       if (newHeight.value < 0) newHeight = new Dimension.px(0);
       _element.style.height = newHeight.toString();
-    } else {
+    } else if (newHeight is num) {
       if (newHeight < 0) newHeight = 0;
       _element.style.height = '${newHeight}px';
+    } else {
+      throw new ArgumentError("newHeight is not a Dimension or num");
     }
   }
 
@@ -44072,9 +43973,11 @@
     if (newWidth is Dimension) {
       if (newWidth.value < 0) newWidth = new Dimension.px(0);
       _element.style.width = newWidth.toString();
-    } else {
+    } else if (newWidth is num) {
       if (newWidth < 0) newWidth = 0;
       _element.style.width = '${newWidth}px';
+    } else {
+      throw new ArgumentError("newWidth is not a Dimension or num");
     }
   }
 
@@ -44091,7 +43994,7 @@
 class _ContentCssListRect extends _ContentCssRect {
   List<Element> _elementList;
 
-  _ContentCssListRect(elementList) : super(elementList.first) {
+  _ContentCssListRect(List<Element> elementList) : super(elementList.first) {
     _elementList = elementList;
   }
 
@@ -44180,10 +44083,10 @@
  * animation frame is discouraged. See also:
  * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
  */
-abstract class CssRect extends MutableRectangle<num> {
+abstract class CssRect implements Rectangle<num> {
   Element _element;
 
-  CssRect(this._element) : super(0, 0, 0, 0);
+  CssRect(this._element);
 
   num get left;
 
@@ -44276,6 +44179,102 @@
     }
     return val;
   }
+
+  // TODO(jacobr): these methods are duplicated from _RectangleBase in dart:math
+  // Ideally we would provide a RectangleMixin class that provides this implementation.
+  // In an ideal world we would exp
+  /** The x-coordinate of the right edge. */
+  num get right => left + width;
+  /** The y-coordinate of the bottom edge. */
+  num get bottom => top + height;
+
+  String toString() {
+    return 'Rectangle ($left, $top) $width x $height';
+  }
+
+  bool operator ==(other) {
+    if (other is !Rectangle) return false;
+    return left == other.left && top == other.top && right == other.right &&
+        bottom == other.bottom;
+  }
+
+  int get hashCode => _JenkinsSmiHash.hash4(left.hashCode, top.hashCode,
+      right.hashCode, bottom.hashCode);
+
+  /**
+   * Computes the intersection of `this` and [other].
+   *
+   * The intersection of two axis-aligned rectangles, if any, is always another
+   * axis-aligned rectangle.
+   *
+   * Returns the intersection of this and `other`, or `null` if they don't
+   * intersect.
+   */
+  Rectangle<num> intersection(Rectangle<num> other) {
+    var x0 = max(left, other.left);
+    var x1 = min(left + width, other.left + other.width);
+
+    if (x0 <= x1) {
+      var y0 = max(top, other.top);
+      var y1 = min(top + height, other.top + other.height);
+
+      if (y0 <= y1) {
+        return new Rectangle<num>(x0, y0, x1 - x0, y1 - y0);
+      }
+    }
+    return null;
+  }
+
+
+  /**
+   * Returns true if `this` intersects [other].
+   */
+  bool intersects(Rectangle<num> other) {
+    return (left <= other.left + other.width &&
+        other.left <= left + width &&
+        top <= other.top + other.height &&
+        other.top <= top + height);
+  }
+
+  /**
+   * Returns a new rectangle which completely contains `this` and [other].
+   */
+  Rectangle<num> boundingBox(Rectangle<num> other) {
+    var right = max(this.left + this.width, other.left + other.width);
+    var bottom = max(this.top + this.height, other.top + other.height);
+
+    var left = min(this.left, other.left);
+    var top = min(this.top, other.top);
+
+    return new Rectangle<num>(left, top, right - left, bottom - top);
+  }
+
+  /**
+   * Tests whether `this` entirely contains [another].
+   */
+  bool containsRectangle(Rectangle<num> another) {
+    return left <= another.left &&
+           left + width >= another.left + another.width &&
+           top <= another.top &&
+           top + height >= another.top + another.height;
+  }
+
+  /**
+   * Tests whether [another] is inside or along the edges of `this`.
+   */
+  bool containsPoint(Point<num> another) {
+    return another.x >= left &&
+           another.x <= left + width &&
+           another.y >= top &&
+           another.y <= top + height;
+  }
+
+  Point<num> get topLeft => new Point<num>(this.left, this.top);
+  Point<num> get topRight => new Point<num>(this.left + this.width, this.top);
+  Point<num> get bottomRight => new Point<num>(this.left + this.width,
+      this.top + this.height);
+  Point<num> get bottomLeft => new Point<num>(this.left,
+      this.top + this.height);
 }
 
 final _HEIGHT = ['top', 'bottom'];
@@ -44406,7 +44405,7 @@
    * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
    */
   Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
-    new _EventStream(e, _eventType, useCapture);
+    new _EventStream<T>(e, _eventType, useCapture);
 
   /**
    * Gets an [ElementEventStream] for this event type, on the specified element.
@@ -44430,7 +44429,7 @@
    * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
    */
   ElementStream<T> forElement(Element e, {bool useCapture: false}) {
-    return new _ElementEventStreamImpl(e, _eventType, useCapture);
+    return new _ElementEventStreamImpl<T>(e, _eventType, useCapture);
   }
 
   /**
@@ -44501,8 +44500,8 @@
   _EventStream(this._target, this._eventType, this._useCapture);
 
   // DOM events are inherently multi-subscribers.
-  Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription),
-                               void onCancel(StreamSubscription subscription)})
+  Stream<T> asBroadcastStream({void onListen(StreamSubscription<T> subscription),
+                               void onCancel(StreamSubscription<T> subscription)})
       => this;
   bool get isBroadcast => true;
 
@@ -44516,6 +44515,11 @@
   }
 }
 
+bool _matchesWithAncestors(Event event, String selector) {
+  var target = event.target;
+  return target is Element ? target.matchesWithAncestors(selector) : false;
+}
+
 /**
  * Adapter for exposing DOM Element events as streams, while also allowing
  * event delegation.
@@ -44526,7 +44530,7 @@
       super(target, eventType, useCapture);
 
   Stream<T> matches(String selector) => this.where(
-      (event) => event.target.matchesWithAncestors(selector)).map((e) {
+      (event) => _matchesWithAncestors(event, selector)).map((e) {
         e._selector = selector;
         return e;
       });
@@ -44550,7 +44554,7 @@
       this._targetList, this._eventType, this._useCapture);
 
   Stream<T> matches(String selector) => this.where(
-      (event) => event.target.matchesWithAncestors(selector)).map((e) {
+      (event) => _matchesWithAncestors(event, selector)).map((e) {
         e._selector = selector;
         return e;
       });
@@ -44560,37 +44564,46 @@
       { Function onError,
         void onDone(),
         bool cancelOnError}) {
-    var pool = new _StreamPool.broadcast();
+    var pool = new _StreamPool<T>.broadcast();
     for (var target in _targetList) {
-      pool.add(new _EventStream(target, _eventType, _useCapture));
+      pool.add(new _EventStream<T>(target, _eventType, _useCapture));
     }
     return pool.stream.listen(onData, onError: onError, onDone: onDone,
           cancelOnError: cancelOnError);
   }
 
   StreamSubscription<T> capture(void onData(T event)) {
-    var pool = new _StreamPool.broadcast();
+    var pool = new _StreamPool<T>.broadcast();
     for (var target in _targetList) {
-      pool.add(new _EventStream(target, _eventType, true));
+      pool.add(new _EventStream<T>(target, _eventType, true));
     }
     return pool.stream.listen(onData);
   }
 
-  Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription),
-                               void onCancel(StreamSubscription subscription)})
+  Stream<T> asBroadcastStream({void onListen(StreamSubscription<T> subscription),
+                               void onCancel(StreamSubscription<T> subscription)})
       => this;
   bool get isBroadcast => true;
 }
 
+// We would like this to just be EventListener<T> but that typdef cannot
+// use generics until dartbug/26276 is fixed.
+typedef _EventListener<T extends Event>(T event);
+
 class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
   int _pauseCount = 0;
   EventTarget _target;
   final String _eventType;
-  var _onData;
+  EventListener _onData;
   final bool _useCapture;
 
-  _EventStreamSubscription(this._target, this._eventType, onData,
-      this._useCapture) : _onData = _wrapZone(onData) {
+  // TODO(jacobr): for full strong mode correctness we should write
+  // _onData = onData == null ? null : _wrapZone/*<Event, dynamic>*/((e) => onData(e as T))
+  // but that breaks 114 co19 tests as well as multiple html tests as it is reasonable
+  // to pass the wrong type of event object to an event listener as part of a
+  // test.
+  _EventStreamSubscription(this._target, this._eventType, void onData(T event),
+      this._useCapture) : _onData = _wrapZone/*<Event, dynamic>*/(onData) {
     _tryResume();
   }
 
@@ -44612,8 +44625,7 @@
     }
     // Remove current event listener.
     _unlisten();
-
-    _onData = _wrapZone(handleData);
+    _onData = _wrapZone/*<Event, dynamic>*/(handleData);
     _tryResume();
   }
 
@@ -44692,8 +44704,8 @@
         onDone: onDone, cancelOnError: cancelOnError);
   }
 
-  Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription),
-                               void onCancel(StreamSubscription subscription)})
+  Stream<T> asBroadcastStream({void onListen(StreamSubscription<T> subscription),
+                               void onCancel(StreamSubscription<T> subscription)})
       => _streamController.stream;
 
   bool get isBroadcast => true;
@@ -44784,16 +44796,16 @@
   const _CustomEventStreamProvider(this._eventTypeGetter);
 
   Stream<T> forTarget(EventTarget e, {bool useCapture: false}) {
-    return new _EventStream(e, _eventTypeGetter(e), useCapture);
+    return new _EventStream<T>(e, _eventTypeGetter(e), useCapture);
   }
 
   ElementStream<T> forElement(Element e, {bool useCapture: false}) {
-    return new _ElementEventStreamImpl(e, _eventTypeGetter(e), useCapture);
+    return new _ElementEventStreamImpl<T>(e, _eventTypeGetter(e), useCapture);
   }
 
   ElementStream<T> _forElementList(ElementList e,
       {bool useCapture: false}) {
-    return new _ElementListEventStreamImpl(e, _eventTypeGetter(e), useCapture);
+    return new _ElementListEventStreamImpl<T>(e, _eventTypeGetter(e), useCapture);
   }
 
   String getEventType(EventTarget target) {
@@ -46172,7 +46184,7 @@
    * The set of keys that have been pressed down without seeing their
    * corresponding keyup event.
    */
-  final List<KeyboardEvent> _keyDownList = <KeyboardEvent>[];
+  final List<KeyEvent> _keyDownList = <KeyEvent>[];
 
   /** The type of KeyEvent we are tracking (keyup, keydown, keypress). */
   final String _type;
@@ -46231,8 +46243,9 @@
    * General constructor, performs basic initialization for our improved
    * KeyboardEvent controller.
    */
-  _KeyboardEventHandler(this._type): super(_EVENT_TYPE),
-      _stream = new _CustomKeyEventStreamImpl('event'), _target = null;
+  _KeyboardEventHandler(this._type):
+      _stream = new _CustomKeyEventStreamImpl('event'), _target = null,
+      super(_EVENT_TYPE);
 
   /**
    * Hook up all event listeners under the covers so we can estimate keycodes
@@ -46540,7 +46553,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
-
 /**
  * Class which helps construct standard node validation policies.
  *
@@ -46558,11 +46570,9 @@
  * appropriate.
  */
 class NodeValidatorBuilder implements NodeValidator {
-
   final List<NodeValidator> _validators = <NodeValidator>[];
 
-  NodeValidatorBuilder() {
-  }
+  NodeValidatorBuilder() {}
 
   /**
    * Creates a new NodeValidatorBuilder which accepts common constructs.
@@ -46691,29 +46701,17 @@
       {UriPolicy uriPolicy,
       Iterable<String> attributes,
       Iterable<String> uriAttributes}) {
-
     var tagNameUpper = tagName.toUpperCase();
-    var attrs;
-    if (attributes != null) {
-      attrs =
-          attributes.map((name) => '$tagNameUpper::${name.toLowerCase()}');
-    }
-    var uriAttrs;
-    if (uriAttributes != null) {
-      uriAttrs =
-          uriAttributes.map((name) => '$tagNameUpper::${name.toLowerCase()}');
-    }
+    var attrs = attributes
+        ?.map /*<String>*/ ((name) => '$tagNameUpper::${name.toLowerCase()}');
+    var uriAttrs = uriAttributes
+        ?.map /*<String>*/ ((name) => '$tagNameUpper::${name.toLowerCase()}');
     if (uriPolicy == null) {
       uriPolicy = new UriPolicy();
     }
 
     add(new _CustomElementNodeValidator(
-        uriPolicy,
-        [tagNameUpper],
-        attrs,
-        uriAttrs,
-        false,
-        true));
+        uriPolicy, [tagNameUpper], attrs, uriAttrs, false, true));
   }
 
   /**
@@ -46728,37 +46726,26 @@
       {UriPolicy uriPolicy,
       Iterable<String> attributes,
       Iterable<String> uriAttributes}) {
-
     var baseNameUpper = baseName.toUpperCase();
     var tagNameUpper = tagName.toUpperCase();
-    var attrs;
-    if (attributes != null) {
-      attrs =
-          attributes.map((name) => '$baseNameUpper::${name.toLowerCase()}');
-    }
-    var uriAttrs;
-    if (uriAttributes != null) {
-      uriAttrs =
-          uriAttributes.map((name) => '$baseNameUpper::${name.toLowerCase()}');
-    }
+    var attrs = attributes
+        ?.map /*<String>*/ ((name) => '$baseNameUpper::${name.toLowerCase()}');
+    var uriAttrs = uriAttributes
+        ?.map /*<String>*/ ((name) => '$baseNameUpper::${name.toLowerCase()}');
     if (uriPolicy == null) {
       uriPolicy = new UriPolicy();
     }
 
-    add(new _CustomElementNodeValidator(
-        uriPolicy,
-        [tagNameUpper, baseNameUpper],
-        attrs,
-        uriAttrs,
-        true,
-        false));
+    add(new _CustomElementNodeValidator(uriPolicy,
+        [tagNameUpper, baseNameUpper], attrs, uriAttrs, true, false));
   }
 
-  void allowElement(String tagName, {UriPolicy uriPolicy,
-    Iterable<String> attributes,
-    Iterable<String> uriAttributes}) {
-
-    allowCustomElement(tagName, uriPolicy: uriPolicy,
+  void allowElement(String tagName,
+      {UriPolicy uriPolicy,
+      Iterable<String> attributes,
+      Iterable<String> uriAttributes}) {
+    allowCustomElement(tagName,
+        uriPolicy: uriPolicy,
         attributes: attributes,
         uriAttributes: uriAttributes);
   }
@@ -46789,8 +46776,8 @@
   }
 
   bool allowsAttribute(Element element, String attributeName, String value) {
-    return _validators.any(
-        (v) => v.allowsAttribute(element, attributeName, value));
+    return _validators
+        .any((v) => v.allowsAttribute(element, attributeName, value));
   }
 }
 
@@ -46801,76 +46788,70 @@
   final UriPolicy uriPolicy;
 
   factory _SimpleNodeValidator.allowNavigation(UriPolicy uriPolicy) {
-    return new _SimpleNodeValidator(uriPolicy,
-      allowedElements: const [
-        'A',
-        'FORM'],
-      allowedAttributes: const [
-        'A::accesskey',
-        'A::coords',
-        'A::hreflang',
-        'A::name',
-        'A::shape',
-        'A::tabindex',
-        'A::target',
-        'A::type',
-        'FORM::accept',
-        'FORM::autocomplete',
-        'FORM::enctype',
-        'FORM::method',
-        'FORM::name',
-        'FORM::novalidate',
-        'FORM::target',
-      ],
-      allowedUriAttributes: const [
-        'A::href',
-        'FORM::action',
-      ]);
+    return new _SimpleNodeValidator(uriPolicy, allowedElements: const [
+      'A',
+      'FORM'
+    ], allowedAttributes: const [
+      'A::accesskey',
+      'A::coords',
+      'A::hreflang',
+      'A::name',
+      'A::shape',
+      'A::tabindex',
+      'A::target',
+      'A::type',
+      'FORM::accept',
+      'FORM::autocomplete',
+      'FORM::enctype',
+      'FORM::method',
+      'FORM::name',
+      'FORM::novalidate',
+      'FORM::target',
+    ], allowedUriAttributes: const [
+      'A::href',
+      'FORM::action',
+    ]);
   }
 
   factory _SimpleNodeValidator.allowImages(UriPolicy uriPolicy) {
-    return new _SimpleNodeValidator(uriPolicy,
-      allowedElements: const [
-        'IMG'
-      ],
-      allowedAttributes: const [
-        'IMG::align',
-        'IMG::alt',
-        'IMG::border',
-        'IMG::height',
-        'IMG::hspace',
-        'IMG::ismap',
-        'IMG::name',
-        'IMG::usemap',
-        'IMG::vspace',
-        'IMG::width',
-      ],
-      allowedUriAttributes: const [
-        'IMG::src',
-      ]);
+    return new _SimpleNodeValidator(uriPolicy, allowedElements: const [
+      'IMG'
+    ], allowedAttributes: const [
+      'IMG::align',
+      'IMG::alt',
+      'IMG::border',
+      'IMG::height',
+      'IMG::hspace',
+      'IMG::ismap',
+      'IMG::name',
+      'IMG::usemap',
+      'IMG::vspace',
+      'IMG::width',
+    ], allowedUriAttributes: const [
+      'IMG::src',
+    ]);
   }
 
   factory _SimpleNodeValidator.allowTextElements() {
-    return new _SimpleNodeValidator(null,
-      allowedElements: const [
-        'B',
-        'BLOCKQUOTE',
-        'BR',
-        'EM',
-        'H1',
-        'H2',
-        'H3',
-        'H4',
-        'H5',
-        'H6',
-        'HR',
-        'I',
-        'LI',
-        'OL',
-        'P',
-        'SPAN',
-        'UL',
-      ]);
+    return new _SimpleNodeValidator(null, allowedElements: const [
+      'B',
+      'BLOCKQUOTE',
+      'BR',
+      'EM',
+      'H1',
+      'H2',
+      'H3',
+      'H4',
+      'H5',
+      'H6',
+      'HR',
+      'I',
+      'LI',
+      'OL',
+      'P',
+      'SPAN',
+      'UL',
+    ]);
   }
 
   /**
@@ -46879,15 +46860,16 @@
    * lowercase attribute name. For example `'IMG:src'`.
    */
   _SimpleNodeValidator(this.uriPolicy,
-      {Iterable<String> allowedElements, Iterable<String> allowedAttributes,
-        Iterable<String> allowedUriAttributes}) {
+      {Iterable<String> allowedElements,
+      Iterable<String> allowedAttributes,
+      Iterable<String> allowedUriAttributes}) {
     this.allowedElements.addAll(allowedElements ?? const []);
     allowedAttributes = allowedAttributes ?? const [];
     allowedUriAttributes = allowedUriAttributes ?? const [];
-    var legalAttributes = allowedAttributes.where(
-        (x) => !_Html5NodeValidator._uriAttributes.contains(x));
-    var extraUriAttributes = allowedAttributes.where(
-        (x) => _Html5NodeValidator._uriAttributes.contains(x));
+    var legalAttributes = allowedAttributes
+        .where((x) => !_Html5NodeValidator._uriAttributes.contains(x));
+    var extraUriAttributes = allowedAttributes
+        .where((x) => _Html5NodeValidator._uriAttributes.contains(x));
     this.allowedAttributes.addAll(legalAttributes);
     this.allowedUriAttributes.addAll(allowedUriAttributes);
     this.allowedUriAttributes.addAll(extraUriAttributes);
@@ -46920,19 +46902,19 @@
   final bool allowTypeExtension;
   final bool allowCustomTag;
 
-  _CustomElementNodeValidator(UriPolicy uriPolicy,
+  _CustomElementNodeValidator(
+      UriPolicy uriPolicy,
       Iterable<String> allowedElements,
       Iterable<String> allowedAttributes,
       Iterable<String> allowedUriAttributes,
       bool allowTypeExtension,
-      bool allowCustomTag):
-
-      super(uriPolicy,
-          allowedElements: allowedElements,
-          allowedAttributes: allowedAttributes,
-          allowedUriAttributes: allowedUriAttributes),
-      this.allowTypeExtension = allowTypeExtension == true,
-      this.allowCustomTag = allowCustomTag == true;
+      bool allowCustomTag)
+      : this.allowTypeExtension = allowTypeExtension == true,
+        this.allowCustomTag = allowCustomTag == true,
+        super(uriPolicy,
+            allowedElements: allowedElements,
+            allowedAttributes: allowedAttributes,
+            allowedUriAttributes: allowedUriAttributes);
 
   bool allowsElement(Element element) {
     if (allowTypeExtension) {
@@ -46942,12 +46924,14 @@
             allowedElements.contains(Element._safeTagName(element));
       }
     }
-    return allowCustomTag && allowedElements.contains(Element._safeTagName(element));
+    return allowCustomTag &&
+        allowedElements.contains(Element._safeTagName(element));
   }
 
   bool allowsAttribute(Element element, String attributeName, String value) {
-   if (allowsElement(element)) {
-      if (allowTypeExtension && attributeName == 'is' &&
+    if (allowsElement(element)) {
+      if (allowTypeExtension &&
+          attributeName == 'is' &&
           allowedElements.contains(value.toUpperCase())) {
         return true;
       }
@@ -46958,19 +46942,22 @@
 }
 
 class _TemplatingNodeValidator extends _SimpleNodeValidator {
-  static const _TEMPLATE_ATTRS =
-      const <String>['bind', 'if', 'ref', 'repeat', 'syntax'];
+  static const _TEMPLATE_ATTRS = const <String>[
+    'bind',
+    'if',
+    'ref',
+    'repeat',
+    'syntax'
+  ];
 
   final Set<String> _templateAttrs;
 
-  _TemplatingNodeValidator():
-      super(null,
-          allowedElements: [
-            'TEMPLATE'
-          ],
-          allowedAttributes: _TEMPLATE_ATTRS.map((attr) => 'TEMPLATE::$attr')),
-      _templateAttrs = new Set<String>.from(_TEMPLATE_ATTRS) {
-  }
+  _TemplatingNodeValidator()
+      : _templateAttrs = new Set<String>.from(_TEMPLATE_ATTRS),
+        super(null,
+            allowedElements: ['TEMPLATE'],
+            allowedAttributes:
+                _TEMPLATE_ATTRS.map((attr) => 'TEMPLATE::$attr')) {}
 
   bool allowsAttribute(Element element, String attributeName, String value) {
     if (super.allowsAttribute(element, attributeName, value)) {
@@ -46981,14 +46968,13 @@
       return true;
     }
 
-    if (element.attributes['template'] == "" ) {
+    if (element.attributes['template'] == "") {
       return _templateAttrs.contains(attributeName);
     }
     return false;
   }
 }
 
-
 class _SvgNodeValidator implements NodeValidator {
   bool allowsElement(Element element) {
     if (element is svg.ScriptElement) {
@@ -46998,7 +46984,8 @@
     // foreignobject tag as SvgElement. We don't want foreignobject contents
     // anyway, so just remove the whole tree outright. And we can't rely
     // on IE recognizing the SvgForeignObject type, so go by tagName. Bug 23144
-    if (element is svg.SvgElement && Element._safeTagName(element) == 'foreignObject') {
+    if (element is svg.SvgElement &&
+        Element._safeTagName(element) == 'foreignObject') {
       return false;
     }
     if (element is svg.SvgElement) {
@@ -47345,7 +47332,7 @@
  */
 class _WrappedList<E extends Node> extends ListBase<E>
     implements NodeListWrapper {
-  final List _list;
+  final List<Node> _list;
 
   _WrappedList(this._list);
 
@@ -47365,13 +47352,13 @@
 
   // List APIs
 
-  E operator [](int index) => _list[index];
+  E operator [](int index) => _downcast/*<Node, E>*/(_list[index]);
 
   void operator []=(int index, E value) { _list[index] = value; }
 
   set length(int newLength) { _list.length = newLength; }
 
-  void sort([int compare(E a, E b)]) { _list.sort(compare); }
+  void sort([int compare(E a, E b)]) { _list.sort((Node a, Node b) => compare(_downcast/*<Node, E>*/(a), _downcast/*<Node, E>*/(b))); }
 
   int indexOf(Object element, [int start = 0]) => _list.indexOf(element, start);
 
@@ -47379,7 +47366,7 @@
 
   void insert(int index, E element) => _list.insert(index, element);
 
-  E removeAt(int index) => _list.removeAt(index);
+  E removeAt(int index) => _downcast/*<Node, E>*/(_list.removeAt(index));
 
   void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
     _list.setRange(start, end, iterable, skipCount);
@@ -47401,8 +47388,8 @@
 /**
  * Iterator wrapper for _WrappedList.
  */
-class _WrappedIterator<E> implements Iterator<E> {
-  Iterator _iterator;
+class _WrappedIterator<E extends Node> implements Iterator<E> {
+  Iterator<Node> _iterator;
 
   _WrappedIterator(this._iterator);
 
@@ -47410,8 +47397,11 @@
     return _iterator.moveNext();
   }
 
-  E get current => _iterator.current;
+  E get current => _downcast/*<Node, E>*/(_iterator.current);
 }
+
+// ignore: STRONG_MODE_DOWN_CAST_COMPOSITE
+/*=To*/ _downcast/*<From, To extends From>*/(dynamic /*=From*/ x) => x;
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
@@ -47852,17 +47842,25 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
-_wrapZone(callback(arg)) {
+// TODO(jacobr): remove these typedefs when dart:async supports generic types.
+typedef R _wrapZoneCallback<A, R>(A a);
+typedef R _wrapZoneBinaryCallback<A, B, R>(A a, B b);
+
+_wrapZoneCallback/*<A, R>*/ _wrapZone/*<A, R>*/(_wrapZoneCallback/*<A, R>*/ callback) {
   // For performance reasons avoid wrapping if we are in the root zone.
   if (Zone.current == Zone.ROOT) return callback;
   if (callback == null) return null;
-  return Zone.current.bindUnaryCallback(callback, runGuarded: true);
+  // TODO(jacobr): we cast to _wrapZoneCallback/*<A, R>*/ to hack around missing
+  // generic method support in zones.
+  return Zone.current.bindUnaryCallback(callback, runGuarded: true) as _wrapZoneCallback/*<A, R>*/;
 }
 
-_wrapBinaryZone(callback(arg1, arg2)) {
+_wrapZoneBinaryCallback/*<A, B, R>*/ _wrapBinaryZone/*<A, B, R>*/(_wrapZoneBinaryCallback/*<A, B, R>*/ callback) {
   if (Zone.current == Zone.ROOT) return callback;
   if (callback == null) return null;
-  return Zone.current.bindBinaryCallback(callback, runGuarded: true);
+  // We cast to _wrapZoneBinaryCallback/*<A, B, R>*/ to hack around missing
+  // generic method support in zones.
+  return Zone.current.bindBinaryCallback(callback, runGuarded: true) as _wrapZoneBinaryCallback/*<A, B, R>*/;
 }
 
 /**
diff --git a/sdk/lib/html/html_common/conversions.dart b/sdk/lib/html/html_common/conversions.dart
index de0d423..179b4e8 100644
--- a/sdk/lib/html/html_common/conversions.dart
+++ b/sdk/lib/html/html_common/conversions.dart
@@ -351,14 +351,3 @@
   }
   return imageData;
 }
-
-const String _serializedScriptValue =
-    'num|String|bool|'
-    'JSExtendableArray|=Object|'
-    'Blob|File|NativeByteBuffer|NativeTypedData'
-    // TODO(sra): Add Date, RegExp.
-    ;
-const annotation_Creates_SerializedScriptValue =
-    const Creates(_serializedScriptValue);
-const annotation_Returns_SerializedScriptValue =
-    const Returns(_serializedScriptValue);
diff --git a/sdk/lib/html/html_common/conversions_dart2js.dart b/sdk/lib/html/html_common/conversions_dart2js.dart
index b5a1064..15f9b2a 100644
--- a/sdk/lib/html/html_common/conversions_dart2js.dart
+++ b/sdk/lib/html/html_common/conversions_dart2js.dart
@@ -91,3 +91,14 @@
   var newPromise = JS('', '#.then(#)["catch"](#)', promise, then, error);
   return completer.future;
 }
+
+const String _serializedScriptValue =
+    'num|String|bool|'
+    'JSExtendableArray|=Object|'
+    'Blob|File|NativeByteBuffer|NativeTypedData'
+    // TODO(sra): Add Date, RegExp.
+    ;
+const annotation_Creates_SerializedScriptValue =
+    const Creates(_serializedScriptValue);
+const annotation_Returns_SerializedScriptValue =
+    const Returns(_serializedScriptValue);
diff --git a/sdk/lib/html/html_common/css_class_set.dart b/sdk/lib/html/html_common/css_class_set.dart
index 9c4b443..3e72600 100644
--- a/sdk/lib/html/html_common/css_class_set.dart
+++ b/sdk/lib/html/html_common/css_class_set.dart
@@ -56,11 +56,13 @@
 
   String join([String separator = ""]) => readClasses().join(separator);
 
-  Iterable map(f(String element)) => readClasses().map(f);
+  Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(String e)) =>
+      readClasses().map/*<T>*/(f);
 
   Iterable<String> where(bool f(String element)) => readClasses().where(f);
 
-  Iterable expand(Iterable f(String element)) => readClasses().expand(f);
+  Iterable/*<T>*/ expand/*<T>*/(Iterable/*<T>*/ f(String element)) =>
+      readClasses().expand/*<T>*/(f);
 
   bool every(bool f(String element)) => readClasses().every(f);
 
@@ -76,10 +78,11 @@
     return readClasses().reduce(combine);
   }
 
-  dynamic fold(dynamic initialValue,
-      dynamic combine(dynamic previousValue, String element)) {
-    return readClasses().fold(initialValue, combine);
+  dynamic/*=T*/ fold/*<T>*/(var/*=T*/ initialValue,
+      dynamic/*=T*/ combine(var/*=T*/ previousValue, String element)) {
+    return readClasses().fold/*<T>*/(initialValue, combine);
   }
+
   // interface Collection - END
 
   // interface Set - BEGIN
@@ -145,7 +148,7 @@
    * [removeClass](http://api.jquery.com/removeClass/).
    */
   void removeAll(Iterable<Object> iterable) {
-    modify((s) => s.removeAll(iterable.map(_validateToken)));
+    modify((s) => s.removeAll(iterable));
   }
 
   /**
@@ -183,7 +186,7 @@
   Set<String> union(Set<String> other) =>
     readClasses().union(other);
 
-  Set<String> difference(Set<String> other) =>
+  Set<String> difference(Set<Object> other) =>
     readClasses().difference(other);
 
   String get first => readClasses().first;
@@ -221,7 +224,7 @@
    *   After f returns, the modified set is written to the
    *       className property of this element.
    */
-  modify( f(Set<String> s)) {
+  modify(f(Set<String> s)) {
     Set<String> s = readClasses();
     var ret = f(s);
     writeClasses(s);
diff --git a/sdk/lib/html/html_common/filtered_element_list.dart b/sdk/lib/html/html_common/filtered_element_list.dart
index e9e4718..d4d40ae 100644
--- a/sdk/lib/html/html_common/filtered_element_list.dart
+++ b/sdk/lib/html/html_common/filtered_element_list.dart
@@ -26,12 +26,8 @@
 
   // We can't memoize this, since it's possible that children will be messed
   // with externally to this class.
-  //
-  // We can't use where directly because the types don't agree and there's
-  // no way to cast it, so take advantage of being in the SDK to construct
-  // a WhereIterable directly. Even so it has to be of dynamic.
   Iterable<Element> get _iterable =>
-      new WhereIterable(_childNodes, (n) => n is Element);
+      _childNodes.where((n) => n is Element).map/*<Element>*/((n) => n as Element);
   List<Element> get _filtered =>
       new List<Element>.from(_iterable, growable: false);
 
diff --git a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index f969eb3..65ebfc6 100644
--- a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -553,14 +553,14 @@
 
   @DomName('IDBFactory.deleteDatabase')
   Future<IdbFactory> deleteDatabase(String name,
-      {void onBlocked(Event)}) {
+      {void onBlocked(Event e)}) {
     try {
       var request = _deleteDatabase(name);
 
       if (onBlocked != null) {
         request.onBlocked.listen(onBlocked);
       }
-      var completer = new Completer.sync();
+      var completer = new Completer<IdbFactory>.sync();
       request.onSuccess.listen((e) {
         completer.complete(this);
       });
@@ -630,12 +630,13 @@
  * Ties a request to a completer, so the completer is completed when it succeeds
  * and errors out when the request errors.
  */
-Future _completeRequest(Request request) {
-  var completer = new Completer.sync();
+Future/*<T>*/ _completeRequest/*<T>*/(Request request) {
+  var completer = new Completer/*<T>*/.sync();
   // TODO: make sure that completer.complete is synchronous as transactions
   // may be committed if the result is not processed immediately.
   request.onSuccess.listen((e) {
-    completer.complete(request.result);
+    var result = _cast/*<T>*/(request.result);
+    completer.complete(result);
   });
   request.onError.listen(completer.completeError);
   return completer.future;
@@ -1175,18 +1176,18 @@
   /**
    * Helper for iterating over cursors in a request.
    */
-  static Stream<Cursor> _cursorStreamFromResult(Request request,
+  static Stream/*<T>*/ _cursorStreamFromResult/*<T extends Cursor>*/(Request request,
       bool autoAdvance) {
     // TODO: need to guarantee that the controller provides the values
     // immediately as waiting until the next tick will cause the transaction to
     // close.
-    var controller = new StreamController(sync: true);
+    var controller = new StreamController/*<T>*/(sync: true);
 
     //TODO: Report stacktrace once issue 4061 is resolved.
     request.onError.listen(controller.addError);
 
     request.onSuccess.listen((e) {
-      Cursor cursor = request.result;
+      var cursor = _cast/*<T>*/(request.result);
       if (cursor == null) {
         controller.close();
       } else {
@@ -1199,6 +1200,9 @@
     return controller.stream;
   }
 }
+
+// ignore: STRONG_MODE_DOWN_CAST_COMPOSITE
+/*=To*/ _cast/*<To>*/(dynamic x) => x;
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
diff --git a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
index 39c78ed..584abb0 100644
--- a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
+++ b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
@@ -497,14 +497,14 @@
 
   @DomName('IDBFactory.deleteDatabase')
   Future<IdbFactory> deleteDatabase(String name,
-      {void onBlocked(Event)}) {
+      {void onBlocked(Event e)}) {
     try {
       var request = _deleteDatabase(name);
 
       if (onBlocked != null) {
         request.onBlocked.listen(onBlocked);
       }
-      var completer = new Completer.sync();
+      var completer = new Completer<IdbFactory>.sync();
       request.onSuccess.listen((e) {
         completer.complete(this);
       });
@@ -574,12 +574,13 @@
  * Ties a request to a completer, so the completer is completed when it succeeds
  * and errors out when the request errors.
  */
-Future _completeRequest(Request request) {
-  var completer = new Completer.sync();
+Future/*<T>*/ _completeRequest/*<T>*/(Request request) {
+  var completer = new Completer/*<T>*/.sync();
   // TODO: make sure that completer.complete is synchronous as transactions
   // may be committed if the result is not processed immediately.
   request.onSuccess.listen((e) {
-    completer.complete(request.result);
+    var result = _cast/*<T>*/(request.result);
+    completer.complete(result);
   });
   request.onError.listen(completer.completeError);
   return completer.future;
@@ -1075,18 +1076,18 @@
   /**
    * Helper for iterating over cursors in a request.
    */
-  static Stream<Cursor> _cursorStreamFromResult(Request request,
+  static Stream/*<T>*/ _cursorStreamFromResult/*<T extends Cursor>*/(Request request,
       bool autoAdvance) {
     // TODO: need to guarantee that the controller provides the values
     // immediately as waiting until the next tick will cause the transaction to
     // close.
-    var controller = new StreamController(sync: true);
+    var controller = new StreamController/*<T>*/(sync: true);
 
     //TODO: Report stacktrace once issue 4061 is resolved.
     request.onError.listen(controller.addError);
 
     request.onSuccess.listen((e) {
-      Cursor cursor = request.result;
+      var cursor = _cast/*<T>*/(request.result);
       if (cursor == null) {
         controller.close();
       } else {
@@ -1099,6 +1100,9 @@
     return controller.stream;
   }
 }
+
+// ignore: STRONG_MODE_DOWN_CAST_COMPOSITE
+/*=To*/ _cast/*<To>*/(dynamic x) => x;
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
diff --git a/sdk/lib/internal/iterable.dart b/sdk/lib/internal/iterable.dart
index 7104c27..2bedb48 100644
--- a/sdk/lib/internal/iterable.dart
+++ b/sdk/lib/internal/iterable.dart
@@ -304,8 +304,8 @@
     if (_endOrLength != null && _endOrLength < end) end = _endOrLength;
     int length = end - start;
     if (length < 0) length = 0;
-    List result = growable ? (new List<E>()..length = length)
-                           : new List<E>(length);
+    List<E> result = growable ? (new List<E>()..length = length)
+                              : new List<E>(length);
     for (int i = 0; i < length; i++) {
       result[i] = _iterable.elementAt(start + i);
       if (_iterable.length < end) throw new ConcurrentModificationError(this);
@@ -353,7 +353,7 @@
   final Iterable<S> _iterable;
   final _Transformation<S, T> _f;
 
-  factory MappedIterable(Iterable iterable, T function(S value)) {
+  factory MappedIterable(Iterable<S> iterable, T function(S value)) {
     if (iterable is EfficientLength) {
       return new EfficientLengthMappedIterable<S, T>(iterable, function);
     }
@@ -377,7 +377,7 @@
 
 class EfficientLengthMappedIterable<S, T> extends MappedIterable<S, T>
                                           implements EfficientLength {
-  EfficientLengthMappedIterable(Iterable iterable, T function(S value))
+  EfficientLengthMappedIterable(Iterable<S> iterable, T function(S value))
       : super._(iterable, function);
 }
 
@@ -421,7 +421,7 @@
 
 class WhereIterable<E> extends Iterable<E> {
   final Iterable<E> _iterable;
-  final _ElementPredicate _f;
+  final _ElementPredicate<E> _f;
 
   WhereIterable(this._iterable, bool this._f(E element));
 
@@ -450,7 +450,7 @@
 
 class ExpandIterable<S, T> extends Iterable<T> {
   final Iterable<S> _iterable;
-  final _ExpandFunction _f;
+  final _ExpandFunction<S, T> _f;
 
   ExpandIterable(this._iterable, Iterable<T> this._f(S element));
 
@@ -459,7 +459,7 @@
 
 class ExpandIterator<S, T> implements Iterator<T> {
   final Iterator<S> _iterator;
-  final _ExpandFunction _f;
+  final _ExpandFunction<S, T> _f;
   // Initialize _currentExpansion to an empty iterable. A null value
   // marks the end of iteration, and we don't want to call _f before
   // the first moveNext call.
@@ -547,7 +547,7 @@
 
 class TakeWhileIterable<E> extends Iterable<E> {
   final Iterable<E> _iterable;
-  final _ElementPredicate _f;
+  final _ElementPredicate<E> _f;
 
   TakeWhileIterable(this._iterable, bool this._f(E element));
 
diff --git a/sdk/lib/internal/list.dart b/sdk/lib/internal/list.dart
index 37ee3f8..2f249f8 100644
--- a/sdk/lib/internal/list.dart
+++ b/sdk/lib/internal/list.dart
@@ -248,7 +248,7 @@
 
   ListMapView(this._values);
 
-  E operator[] (int key) => containsKey(key) ? _values[key] : null;
+  E operator[] (Object key) => containsKey(key) ? _values[key] : null;
   int get length => _values.length;
 
   Iterable<E> get values => new SubListIterable<E>(_values, 0, null);
@@ -257,7 +257,7 @@
   bool get isEmpty => _values.isEmpty;
   bool get isNotEmpty => _values.isNotEmpty;
   bool containsValue(Object value) => _values.contains(value);
-  bool containsKey(int key) => key is int && key >= 0 && key < length;
+  bool containsKey(Object key) => key is int && key >= 0 && key < length;
 
   void forEach(void f(int key, E value)) {
     int length = _values.length;
@@ -280,7 +280,7 @@
   }
 
   /** This operation is not supported by an unmodifiable map. */
-  E remove(int key) {
+  E remove(Object key) {
     throw new UnsupportedError("Cannot modify an unmodifiable map");
   }
 
diff --git a/sdk/lib/io/bytes_builder.dart b/sdk/lib/io/bytes_builder.dart
index 610c50a..2882402 100644
--- a/sdk/lib/io/bytes_builder.dart
+++ b/sdk/lib/io/bytes_builder.dart
@@ -113,7 +113,7 @@
     _length = required;
   }
 
-  void addByte(int byte) => add([byte]);
+  void addByte(int byte) { add([byte]); }
 
   List<int> takeBytes() {
     if (_buffer == null) return new Uint8List(0);
@@ -163,7 +163,7 @@
     _length += bytes.length;
   }
 
-  void addByte(int byte) => add([byte]);
+  void addByte(int byte) { add([byte]); }
 
   List<int> takeBytes() {
     if (_chunks.length == 0) return new Uint8List(0);
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart
index 620437c..d76b86d 100644
--- a/sdk/lib/io/directory_impl.dart
+++ b/sdk/lib/io/directory_impl.dart
@@ -252,6 +252,12 @@
   }
 }
 
+abstract class _AsyncDirectoryListerOps {
+  external factory _AsyncDirectoryListerOps(int pointer);
+
+  int getPointer();
+}
+
 class _AsyncDirectoryLister {
   static const int LIST_FILE = 0;
   static const int LIST_DIRECTORY = 1;
@@ -269,10 +275,10 @@
   final bool followLinks;
 
   StreamController controller;
-  int id;
   bool canceled = false;
   bool nextRunning = false;
   bool closed = false;
+  _AsyncDirectoryListerOps _ops;
   Completer closeCompleter = new Completer();
 
   _AsyncDirectoryLister(this.path, this.recursive, this.followLinks) {
@@ -282,13 +288,21 @@
                                       sync: true);
   }
 
+  // Calling this function will increase the reference count on the native
+  // object that implements the async directory lister operations. It should
+  // only be called to pass the pointer to the IO Service, which will decrement
+  // the reference count when it is finished with it.
+  int _pointer() {
+    return (_ops == null) ? null : _ops.getPointer();
+  }
+
   Stream get stream => controller.stream;
 
   void onListen() {
     _IOService._dispatch(_DIRECTORY_LIST_START, [path, recursive, followLinks])
         .then((response) {
           if (response is int) {
-            id = response;
+            _ops = new _AsyncDirectoryListerOps(response);
             next();
           } else if (response is Error) {
             controller.addError(response, response.stackTrace);
@@ -301,7 +315,9 @@
   }
 
   void onResume() {
-    if (!nextRunning) next();
+    if (!nextRunning) {
+      next();
+    }
   }
 
   Future onCancel() {
@@ -319,11 +335,15 @@
       close();
       return;
     }
-    if (id == null) return;
-    if (controller.isPaused) return;
-    if (nextRunning) return;
+    if (controller.isPaused || nextRunning) {
+      return;
+    }
+    var pointer = _pointer();
+    if (pointer == null) {
+      return;
+    }
     nextRunning = true;
-    _IOService._dispatch(_DIRECTORY_LIST_NEXT, [id]).then((result) {
+    _IOService._dispatch(_DIRECTORY_LIST_NEXT, [pointer]).then((result) {
       nextRunning = false;
       if (result is List) {
         next();
@@ -354,18 +374,27 @@
     });
   }
 
+  void _cleanup() {
+    controller.close();
+    closeCompleter.complete();
+    _ops = null;
+  }
+
   void close() {
-    if (closed) return;
-    if (nextRunning) return;
-    void cleanup() {
-      controller.close();
-      closeCompleter.complete();
+    if (closed) {
+      return;
+    }
+    if (nextRunning) {
+      return;
     }
     closed = true;
-    if (id != null) {
-      _IOService._dispatch(_DIRECTORY_LIST_STOP, [id]).whenComplete(cleanup);
+
+    var pointer = _pointer();
+    if (pointer == null) {
+      _cleanup();
     } else {
-      cleanup();
+      _IOService._dispatch(_DIRECTORY_LIST_STOP, [pointer])
+                .whenComplete(_cleanup);
     }
   }
 
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index d9b2cb4..4ac4486 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -751,7 +751,7 @@
    * already unlocked".
    */
   Future<RandomAccessFile> lock(
-      [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end]);
+      [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end = -1]);
 
   /**
    * Synchronously locks the file or part of the file.
@@ -784,7 +784,8 @@
    * already unlocked".
    *
    */
-  void lockSync([FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end]);
+  void lockSync(
+      [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end = -1]);
 
   /**
    * Unlocks the file or part of the file.
@@ -800,7 +801,7 @@
    *
    * See [lock] for more details.
    */
-  Future<RandomAccessFile> unlock([int start = 0, int end]);
+  Future<RandomAccessFile> unlock([int start = 0, int end = -1]);
 
   /**
    * Synchronously unlocks the file or part of the file.
@@ -816,7 +817,7 @@
    *
    * See [lockSync] for more details.
    */
-  void unlockSync([int start = 0, int end]);
+  void unlockSync([int start = 0, int end = -1]);
 
   /**
    * Returns a human-readable string for this RandomAccessFile instance.
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index 0d0bc9e..a6fdde8 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -564,19 +564,37 @@
   }
 }
 
+abstract class _RandomAccessFileOps {
+  external factory _RandomAccessFileOps(int pointer);
 
-class _RandomAccessFile
-    implements RandomAccessFile {
+  int getPointer();
+  int close();
+  readByte();
+  read(int bytes);
+  readInto(List<int> buffer, int start, int end);
+  writeByte(int value);
+  writeFrom(List<int> buffer, int start, int end);
+  position();
+  setPosition(int position);
+  truncate(int length);
+  length();
+  flush();
+  lock(int lock, int start, int end);
+}
+
+class _RandomAccessFile implements RandomAccessFile {
   static bool _connectedResourceHandler = false;
 
   final String path;
-  int _id;
+
   bool _asyncDispatched = false;
   SendPort _fileService;
 
   _FileResourceInfo _resourceInfo;
+  _RandomAccessFileOps _ops;
 
-  _RandomAccessFile(this._id, this.path) {
+  _RandomAccessFile(int pointer, this.path) {
+    _ops = new _RandomAccessFileOps(pointer);
     _resourceInfo = new _FileResourceInfo(this);
     _maybeConnectHandler();
   }
@@ -587,12 +605,10 @@
     }
   }
 
-  external static int _getFD(int id);
-
   _maybeConnectHandler() {
     if (!_connectedResourceHandler) {
-      // TODO(ricow): we probably need set these in some initialization code.
-      // We need to make sure that these are always awailable from the
+      // TODO(ricow): We probably need to set these in some initialization code.
+      // We need to make sure that these are always available from the
       // observatory even if no files (or sockets for the socket ones) are
       // open.
       registerExtension('ext.dart.io.getOpenFiles',
@@ -604,9 +620,9 @@
   }
 
   Future<RandomAccessFile> close() {
-    return _dispatch(_FILE_CLOSE, [_id], markClosed: true).then((result) {
+    return _dispatch(_FILE_CLOSE, [null], markClosed: true).then((result) {
       if (result != -1) {
-        _id = result;
+        closed = closed || (result == 0);
         _maybePerformCleanup();
         return this;
       } else {
@@ -615,20 +631,18 @@
     });
   }
 
-  external static int _close(int id);
-
   void closeSync() {
     _checkAvailable();
-    var id = _close(_id);
+    var id = _ops.close();
     if (id == -1) {
       throw new FileSystemException("Cannot close file", path);
     }
-    _id = id;
+    closed = closed || (id == 0);
     _maybePerformCleanup();
   }
 
   Future<int> readByte() {
-    return _dispatch(_FILE_READ_BYTE, [_id]).then((response) {
+    return _dispatch(_FILE_READ_BYTE, [null]).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response, "readByte failed", path);
       }
@@ -637,11 +651,9 @@
     });
   }
 
-  external static _readByte(int id);
-
   int readByteSync() {
     _checkAvailable();
-    var result = _readByte(_id);
+    var result = _ops.readByte();
     if (result is OSError) {
       throw new FileSystemException("readByte failed", path, result);
     }
@@ -653,7 +665,7 @@
     if (bytes is !int) {
       throw new ArgumentError(bytes);
     }
-    return _dispatch(_FILE_READ, [_id, bytes]).then((response) {
+    return _dispatch(_FILE_READ, [null, bytes]).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response, "read failed", path);
       }
@@ -662,14 +674,12 @@
     });
   }
 
-  external static _read(int id, int bytes);
-
   List<int> readSync(int bytes) {
     _checkAvailable();
     if (bytes is !int) {
       throw new ArgumentError(bytes);
     }
-    var result = _read(_id, bytes);
+    var result = _ops.read(bytes);
     if (result is OSError) {
       throw new FileSystemException("readSync failed", path, result);
     }
@@ -678,15 +688,17 @@
   }
 
   Future<int> readInto(List<int> buffer, [int start = 0, int end]) {
-    if (buffer is !List ||
-        (start != null && start is !int) ||
-        (end != null && end is !int)) {
+    if ((buffer is !List) ||
+        ((start != null) && (start is !int)) ||
+        ((end != null) && (end is !int))) {
       throw new ArgumentError();
     }
     end = RangeError.checkValidRange(start, end, buffer.length);
-    if (end == start) return new Future.value(0);
+    if (end == start) {
+      return new Future.value(0);
+    }
     int length = end - start;
-    return _dispatch(_FILE_READ_INTO, [_id, length]).then((response) {
+    return _dispatch(_FILE_READ_INTO, [null, length]).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response, "readInto failed", path);
       }
@@ -698,18 +710,18 @@
     });
   }
 
-  external static _readInto(int id, List<int> buffer, int start, int end);
-
   int readIntoSync(List<int> buffer, [int start = 0, int end]) {
     _checkAvailable();
-    if (buffer is !List ||
-        (start != null && start is !int) ||
-        (end != null && end is !int)) {
+    if ((buffer is !List) ||
+        ((start != null) && (start is !int)) ||
+        ((end != null) && (end is !int))) {
       throw new ArgumentError();
     }
     end = RangeError.checkValidRange(start, end, buffer.length);
-    if (end == start) return 0;
-    var result = _readInto(_id, buffer, start, end);
+    if (end == start) {
+      return 0;
+    }
+    var result = _ops.readInto(buffer, start, end);
     if (result is OSError) {
       throw new FileSystemException("readInto failed", path, result);
     }
@@ -721,7 +733,7 @@
     if (value is !int) {
       throw new ArgumentError(value);
     }
-    return _dispatch(_FILE_WRITE_BYTE, [_id, value]).then((response) {
+    return _dispatch(_FILE_WRITE_BYTE, [null, value]).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response, "writeByte failed", path);
       }
@@ -730,14 +742,12 @@
     });
   }
 
-  external static _writeByte(int id, int value);
-
   int writeByteSync(int value) {
     _checkAvailable();
     if (value is !int) {
       throw new ArgumentError(value);
     }
-    var result = _writeByte(_id, value);
+    var result = _ops.writeByte(value);
     if (result is OSError) {
       throw new FileSystemException("writeByte failed", path, result);
     }
@@ -748,12 +758,14 @@
   Future<RandomAccessFile> writeFrom(
       List<int> buffer, [int start = 0, int end]) {
     if ((buffer is !List) ||
-        (start != null && start is !int) ||
-        (end != null && end is !int)) {
+        ((start != null) && (start is !int)) ||
+        ((end != null) && (end is !int))) {
       throw new ArgumentError("Invalid arguments to writeFrom");
     }
     end = RangeError.checkValidRange(start, end, buffer.length);
-    if (end == start) return new Future.value(this);
+    if (end == start) {
+      return new Future.value(this);
+    }
     _BufferAndStart result;
     try {
       result = _ensureFastAndSerializableByteData(buffer, start, end);
@@ -762,7 +774,7 @@
     }
 
     List request = new List(4);
-    request[0] = _id;
+    request[0] = null;
     request[1] = result.buffer;
     request[2] = result.start;
     request[3] = end - (start - result.start);
@@ -775,23 +787,22 @@
     });
   }
 
-  external static _writeFrom(int id, List<int> buffer, int start, int end);
-
   void writeFromSync(List<int> buffer, [int start = 0, int end]) {
     _checkAvailable();
-    if (buffer is !List ||
-        (start != null && start is !int) ||
-        (end != null && end is !int)) {
+    if ((buffer is !List) ||
+        ((start != null) && (start is !int)) ||
+        ((end != null) && (end is !int))) {
       throw new ArgumentError("Invalid arguments to writeFromSync");
     }
     end = RangeError.checkValidRange(start, end, buffer.length);
-    if (end == start) return;
+    if (end == start) {
+      return;
+    }
     _BufferAndStart bufferAndStart =
         _ensureFastAndSerializableByteData(buffer, start, end);
-    var result = _writeFrom(_id,
-                            bufferAndStart.buffer,
-                            bufferAndStart.start,
-                            end - (start - bufferAndStart.start));
+    var result = _ops.writeFrom(bufferAndStart.buffer,
+                                bufferAndStart.start,
+                                end - (start - bufferAndStart.start));
     if (result is OSError) {
       throw new FileSystemException("writeFrom failed", path, result);
     }
@@ -816,7 +827,7 @@
   }
 
   Future<int> position() {
-    return _dispatch(_FILE_POSITION, [_id]).then((response) {
+    return _dispatch(_FILE_POSITION, [null]).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response, "position failed", path);
       }
@@ -824,11 +835,9 @@
     });
   }
 
-  external static _position(int id);
-
   int positionSync() {
     _checkAvailable();
-    var result = _position(_id);
+    var result = _ops.position();
     if (result is OSError) {
       throw new FileSystemException("position failed", path, result);
     }
@@ -836,7 +845,7 @@
   }
 
   Future<RandomAccessFile> setPosition(int position) {
-    return _dispatch(_FILE_SET_POSITION, [_id, position])
+    return _dispatch(_FILE_SET_POSITION, [null, position])
         .then((response) {
           if (_isErrorResponse(response)) {
             throw _exceptionFromResponse(response, "setPosition failed", path);
@@ -845,18 +854,16 @@
         });
   }
 
-  external static _setPosition(int id, int position);
-
   void setPositionSync(int position) {
     _checkAvailable();
-    var result = _setPosition(_id, position);
+    var result = _ops.setPosition(position);
     if (result is OSError) {
       throw new FileSystemException("setPosition failed", path, result);
     }
   }
 
   Future<RandomAccessFile> truncate(int length) {
-    return _dispatch(_FILE_TRUNCATE, [_id, length]).then((response) {
+    return _dispatch(_FILE_TRUNCATE, [null, length]).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response, "truncate failed", path);
       }
@@ -864,18 +871,16 @@
     });
   }
 
-  external static _truncate(int id, int length);
-
   void truncateSync(int length) {
     _checkAvailable();
-    var result = _truncate(_id, length);
+    var result = _ops.truncate(length);
     if (result is OSError) {
       throw new FileSystemException("truncate failed", path, result);
     }
   }
 
   Future<int> length() {
-    return _dispatch(_FILE_LENGTH, [_id]).then((response) {
+    return _dispatch(_FILE_LENGTH, [null]).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response, "length failed", path);
       }
@@ -883,11 +888,9 @@
     });
   }
 
-  external static _length(int id);
-
   int lengthSync() {
     _checkAvailable();
-    var result = _length(_id);
+    var result = _ops.length();
     if (result is OSError) {
       throw new FileSystemException("length failed", path, result);
     }
@@ -895,7 +898,7 @@
   }
 
   Future<RandomAccessFile> flush() {
-    return _dispatch(_FILE_FLUSH, [_id]).then((response) {
+    return _dispatch(_FILE_FLUSH, [null]).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
                                      "flush failed",
@@ -905,11 +908,9 @@
     });
   }
 
-  external static _flush(int id);
-
   void flushSync() {
     _checkAvailable();
-    var result = _flush(_id);
+    var result = _ops.flush();
     if (result is OSError) {
       throw new FileSystemException("flush failed", path, result);
     }
@@ -920,19 +921,15 @@
   static final int LOCK_EXCLUSIVE = 2;
 
   Future<RandomAccessFile> lock(
-      [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end]) {
-    if ((start != null && start is !int) ||
-        (end != null && end is !int) ||
-         mode is !FileLock) {
+      [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end = -1]) {
+    if ((mode is !FileLock) || (start is !int) || (end is !int)) {
       throw new ArgumentError();
     }
-    if (start == null) start = 0;
-    if (end == null) end = -1;
-    if (start < 0 || end < -1 || (end != -1 && start >= end)) {
+    if ((start < 0) || (end < -1) || ((end != -1) && (start >= end))) {
       throw new ArgumentError();
     }
-    int lock = mode == FileLock.EXCLUSIVE ? LOCK_EXCLUSIVE : LOCK_SHARED;
-    return _dispatch(_FILE_LOCK, [_id, lock, start, end])
+    int lock = (mode == FileLock.EXCLUSIVE) ? LOCK_EXCLUSIVE : LOCK_SHARED;
+    return _dispatch(_FILE_LOCK, [null, lock, start, end])
         .then((response) {
           if (_isErrorResponse(response)) {
             throw _exceptionFromResponse(response, 'lock failed', path);
@@ -941,15 +938,14 @@
         });
   }
 
-  Future<RandomAccessFile> unlock([int start = 0, int end]) {
-    if ((start != null && start is !int) ||
-        (end != null && end is !int)) {
+  Future<RandomAccessFile> unlock([int start = 0, int end = -1]) {
+    if ((start is !int) || (end is !int)) {
       throw new ArgumentError();
     }
-    if (start == null) start = 0;
-    if (end == null) end = -1;
-    if (start == end) throw new ArgumentError();
-    return _dispatch(_FILE_LOCK, [_id, LOCK_UNLOCK, start, end])
+    if (start == end) {
+      throw new ArgumentError();
+    }
+    return _dispatch(_FILE_LOCK, [null, LOCK_UNLOCK, start, end])
         .then((response) {
           if (_isErrorResponse(response)) {
             throw _exceptionFromResponse(response, 'unlock failed', path);
@@ -958,43 +954,43 @@
         });
   }
 
-  external static _lock(int id, int lock, int start, int end);
-
-  void lockSync([FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end]) {
+  void lockSync(
+      [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end = -1]) {
     _checkAvailable();
-    if ((start != null && start is !int) ||
-        (end != null && end is !int) ||
-         mode is !FileLock) {
+    if ((mode is !FileLock) || (start is !int) || (end is !int)) {
       throw new ArgumentError();
     }
-    if (start == null) start = 0;
-    if (end == null) end = -1;
-    if (start < 0 || end < -1 || (end != -1 && start >= end)) {
+    if ((start < 0) || (end < -1) || ((end != -1) && (start >= end))) {
       throw new ArgumentError();
     }
-    int lock = mode == FileLock.EXCLUSIVE ? LOCK_EXCLUSIVE : LOCK_SHARED;
-    var result = _lock(_id, lock, start, end);
+    int lock = (mode == FileLock.EXCLUSIVE) ? LOCK_EXCLUSIVE : LOCK_SHARED;
+    var result = _ops.lock(lock, start, end);
     if (result is OSError) {
       throw new FileSystemException('lock failed', path, result);
     }
   }
 
-  void unlockSync([int start = 0, int end]) {
+  void unlockSync([int start = 0, int end = -1]) {
     _checkAvailable();
-    if ((start != null && start is !int) ||
-        (end != null && end is !int)) {
+    if ((start is !int) || (end is !int)) {
       throw new ArgumentError();
     }
-    if (start == null) start = 0;
-    if (end == null) end = -1;
-    if (start == end) throw new ArgumentError();
-    var result = _lock(_id, LOCK_UNLOCK, start, end);
+    if (start == end) {
+      throw new ArgumentError();
+    }
+    var result = _ops.lock(LOCK_UNLOCK, start, end);
     if (result is OSError) {
       throw new FileSystemException('unlock failed', path, result);
     }
   }
 
-  bool get closed => _id == 0;
+  bool closed = false;
+
+  // Calling this function will increase the reference count on the native
+  // object that implements the file operations. It should only be called to
+  // pass the pointer to the IO Service, which will decrement the reference
+  // count when it is finished with it.
+  int _pointer() => _ops.getPointer();
 
   Future _dispatch(int request, List data, { bool markClosed: false }) {
     if (closed) {
@@ -1005,11 +1001,12 @@
       return new Future.error(new FileSystemException(msg, path));
     }
     if (markClosed) {
-      // Set the id_ to 0 (NULL) to ensure the no more async requests
-      // can be issued for this file.
-      _id = 0;
+      // Set closed to true to ensure that no more async requests can be issued
+      // for this file.
+      closed = true;
     }
     _asyncDispatched = true;
+    data[0] = _pointer();
     return _IOService._dispatch(request, data)
         .whenComplete(() {
           _asyncDispatched = false;
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index d002f30..846b724 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -1781,8 +1781,9 @@
     _authenticate = f;
   }
 
-  void addCredentials(Uri url, String realm, HttpClientCredentials cr) =>
-      _credentials.add(new _SiteCredentials(url, realm, cr));
+  void addCredentials(Uri url, String realm, HttpClientCredentials cr) {
+    _credentials.add(new _SiteCredentials(url, realm, cr));
+  }
 
   set authenticateProxy(
       Future<bool> f(String host, int port, String scheme, String realm)) {
@@ -1792,8 +1793,9 @@
   void addProxyCredentials(String host,
                            int port,
                            String realm,
-                           HttpClientCredentials cr) =>
-      _proxyCredentials.add(new _ProxyCredentials(host, port, realm, cr));
+                           HttpClientCredentials cr) {
+    _proxyCredentials.add(new _ProxyCredentials(host, port, realm, cr));
+  }
 
   set findProxy(String f(Uri uri)) => _findProxy = f;
 
@@ -2580,17 +2582,17 @@
     _socket.encoding = value;
   }
 
-  void write(Object obj) => _socket.write(obj);
+  void write(Object obj) { _socket.write(obj); }
 
-  void writeln([Object obj = ""]) => _socket.writeln(obj);
+  void writeln([Object obj = ""]) { _socket.writeln(obj); }
 
-  void writeCharCode(int charCode) => _socket.writeCharCode(charCode);
+  void writeCharCode(int charCode) { _socket.writeCharCode(charCode); }
 
   void writeAll(Iterable objects, [String separator = ""]) {
     _socket.writeAll(objects, separator);
   }
 
-  void add(List<int> bytes) => _socket.add(bytes);
+  void add(List<int> bytes) { _socket.add(bytes); }
 
   void addError(error, [StackTrace stackTrace]) =>
       _socket.addError(error, stackTrace);
@@ -2599,7 +2601,7 @@
     return _socket.addStream(stream);
   }
 
-  void destroy() => _socket.destroy();
+  void destroy() { _socket.destroy(); }
 
   Future flush() => _socket.flush();
 
@@ -2768,11 +2770,13 @@
     return "Basic $auth";
   }
 
-  void authorize(_Credentials _, HttpClientRequest request) =>
-      request.headers.set(HttpHeaders.AUTHORIZATION, authorization());
+  void authorize(_Credentials _, HttpClientRequest request) {
+    request.headers.set(HttpHeaders.AUTHORIZATION, authorization());
+  }
 
-  void authorizeProxy(_ProxyCredentials _, HttpClientRequest request) =>
-      request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, authorization());
+  void authorizeProxy(_ProxyCredentials _, HttpClientRequest request) {
+    request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, authorization());
+  }
 }
 
 
diff --git a/sdk/lib/io/http_session.dart b/sdk/lib/io/http_session.dart
index 159a54d..90075a5 100644
--- a/sdk/lib/io/http_session.dart
+++ b/sdk/lib/io/http_session.dart
@@ -53,8 +53,8 @@
   putIfAbsent(key, ifAbsent) => _data.putIfAbsent(key, ifAbsent);
   addAll(Map other) => _data.addAll(other);
   remove(key) => _data.remove(key);
-  void clear() => _data.clear();
-  void forEach(void f(key, value)) => _data.forEach(f);
+  void clear() { _data.clear(); }
+  void forEach(void f(key, value)) { _data.forEach(f); }
   Iterable get keys => _data.keys;
   Iterable get values => _data.values;
   int get length => _data.length;
@@ -104,7 +104,7 @@
     _startTimer();
   }
 
-  void close() => _stopTimer();
+  void close() { _stopTimer(); }
 
   void _bumpToEnd(_HttpSession session) {
     _removeFromTimeoutQueue(session);
diff --git a/sdk/lib/io/io_resource_info.dart b/sdk/lib/io/io_resource_info.dart
index 9267084..7cea231 100644
--- a/sdk/lib/io/io_resource_info.dart
+++ b/sdk/lib/io/io_resource_info.dart
@@ -54,7 +54,7 @@
   // In cases where we read but did not neccesarily get any bytes, use this to
   // update the readCount and timestamp. Manually update totalRead if any bytes
   // where acutally read.
-  void didRead() => addRead(0);
+  void didRead() { addRead(0); }
 
   void addWrite(int bytes) {
     totalWritten += bytes;
@@ -153,7 +153,7 @@
 
   String get name => process._path;
 
-  void stopped() => ProcessStopped(this);
+  void stopped() { ProcessStopped(this); }
 
   Map<String, String> get fullValueMap =>
     {
diff --git a/sdk/lib/io/platform_impl.dart b/sdk/lib/io/platform_impl.dart
index d7e722f..8c9d30c 100644
--- a/sdk/lib/io/platform_impl.dart
+++ b/sdk/lib/io/platform_impl.dart
@@ -109,8 +109,8 @@
     other.forEach((key, value) => this[key.toUpperCase()] = value);
   }
   V remove(String key) => _map.remove(key.toUpperCase());
-  void clear() => _map.clear();
-  void forEach(void f(String key, V value)) => _map.forEach(f);
+  void clear() { _map.clear(); }
+  void forEach(void f(String key, V value)) { _map.forEach(f); }
   Iterable<String> get keys => _map.keys;
   Iterable<V> get values => _map.values;
   int get length => _map.length;
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index 07ef23e..679aa71 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -412,7 +412,6 @@
   bool _filterActive = false;
 
   _SecureFilter _secureFilter = new _SecureFilter();
-  int _filterPointer;
   String _selectedProtocol;
 
   static Future<_RawSecureSocket> connect(
@@ -472,7 +471,6 @@
     // Throw an ArgumentError if any field is invalid.  After this, all
     // errors will be reported through the future or the stream.
     _secureFilter.init();
-    _filterPointer = _secureFilter._pointer();
     _secureFilter.registerHandshakeCompleteCallback(
         _secureHandshakeCompleteHandler);
     if (onBadCertificate != null) {
@@ -976,7 +974,7 @@
   Future<_FilterStatus> _pushAllFilterStages() {
     bool wasInHandshake = _status != CONNECTED;
     List args = new List(2 + NUM_BUFFERS * 2);
-    args[0] = _filterPointer;
+    args[0] = _secureFilter._pointer();
     args[1] = wasInHandshake;
     var bufs = _secureFilter.buffers;
     for (var i = 0; i < NUM_BUFFERS; ++i) {
@@ -1201,6 +1199,10 @@
   int processBuffer(int bufferIndex);
   void registerBadCertificateCallback(Function callback);
   void registerHandshakeCompleteCallback(Function handshakeCompleteHandler);
+
+  // This call may cause a reference counted pointer in the native
+  // implementation to be retained. It should only be called when the resulting
+  // value is passed to the IO service through a call to dispatch().
   int _pointer();
 
   List<_ExternalBuffer> get buffers;
diff --git a/sdk/lib/io/security_context.dart b/sdk/lib/io/security_context.dart
index 1909571..d99b05b 100644
--- a/sdk/lib/io/security_context.dart
+++ b/sdk/lib/io/security_context.dart
@@ -48,7 +48,10 @@
    * NB: This function calls [ReadFileAsBytesSync], and will block on file IO.
    * Prefer using [usePrivateKeyBytes].
    *
-   * iOS note: Not yet implemented.
+   * iOS note: Only PKCS12 data is supported. It should contain both the private
+   * key and the certificate chain. On iOS one call to [usePrivateKey] with this
+   * data is used instead of two calls to [useCertificateChain] and
+   * [usePrivateKey].
    */
   void usePrivateKey(String file, {String password});
 
@@ -57,8 +60,6 @@
    *
    * Like [usePrivateKey], but takes the contents of the file as a list
    * of bytes.
-   *
-   * iOS note: Not yet implemented.
    */
   void usePrivateKeyBytes(List<int> keyBytes, {String password});
 
@@ -74,6 +75,13 @@
    *
    * NB: This function calls [ReadFileAsBytesSync], and will block on file IO.
    * Prefer using [setTrustedCertificatesBytes].
+   *
+   * iOS note: On iOS, this call takes only the bytes for a single DER
+   * encoded X509 certificate. It may be called multiple times to add
+   * multiple trusted certificates to the context. A DER encoded certificate
+   * can be obtained from a PEM encoded certificate by using the openssl tool:
+   *
+   *   $ openssl x509 -outform der -in cert.pem -out cert.der
    */
   void setTrustedCertificates(String file, {String password});
 
@@ -82,13 +90,6 @@
    * client connections, when connecting to a secure server.
    *
    * Like [setTrustedCertificates] but takes the contents of the file.
-   *
-   * iOS note: On iOS, this call takes only the bytes for a single DER
-   * encoded X509 certificate. It may be called multiple times to add
-   * multiple trusted certificates to the context. A DER encoded certificate
-   * can be obtained from a PEM encoded certificate by using the openssl tool:
-   *
-   *   $ openssl x509 -outform der -in cert.pem -out cert.der
    */
   void setTrustedCertificatesBytes(List<int> certBytes, {String password});
 
@@ -107,7 +108,8 @@
    * NB: This function calls [ReadFileAsBytesSync], and will block on file IO.
    * Prefer using [useCertificateChainBytes].
    *
-   * iOS note: Not yet implemented.
+   * iOS note: As noted above, [usePrivateKey] does the job of both
+   * that call and this one. On iOS, this call is a no-op.
    */
   void useCertificateChain(String file, {String password});
 
@@ -116,8 +118,6 @@
    * when making secure connections, including the server certificate.
    *
    * Like [useCertificateChain] but takes the contents of the file.
-   *
-   * iOS note: Not yet implemented.
    */
   void useCertificateChainBytes(List<int> chainBytes, {String password});
 
@@ -135,7 +135,7 @@
    * NB: This function calls [ReadFileAsBytesSync], and will block on file IO.
    * Prefer using [setClientAuthoritiesBytes].
    *
-   * iOS note: Not yet implemented.
+   * iOS note: This call is not supported.
    */
   void setClientAuthorities(String file, {String password});
 
@@ -145,8 +145,6 @@
    * client.
    *
    * Like [setClientAuthority] but takes the contents of the file.
-   *
-   * iOS note: Not yet implemented.
    */
   void setClientAuthoritiesBytes(List<int> authCertBytes, {String password});
 
diff --git a/sdk/lib/io/socket.dart b/sdk/lib/io/socket.dart
index 4da5bb8..30e4eb2 100644
--- a/sdk/lib/io/socket.dart
+++ b/sdk/lib/io/socket.dart
@@ -145,8 +145,8 @@
 
 
 /**
- * A [NetworkInterface] represent an active network interface on the current
- * system. It contains a list of [InternetAddress]s, that's bound to the
+ * A [NetworkInterface] represents an active network interface on the current
+ * system. It contains a list of [InternetAddress]es that are bound to the
  * interface.
  */
 abstract class NetworkInterface {
@@ -161,12 +161,19 @@
   String get index;
 
   /**
-   * Get a list of [InternetAddress]s currently bound to this
+   * Get a list of [InternetAddress]es currently bound to this
    * [NetworkInterface].
    */
   List<InternetAddress> get addresses;
 
   /**
+   * Whether [list] is supported.
+   *
+   * [list] is currently unsupported on Android.
+   */
+  external static bool get listSupported;
+
+  /**
    * Query the system for [NetworkInterface]s.
    *
    * If [includeLoopback] is `true`, the returned list will include the
diff --git a/sdk/lib/io/stdio.dart b/sdk/lib/io/stdio.dart
index 9888d95..feea4ff 100644
--- a/sdk/lib/io/stdio.dart
+++ b/sdk/lib/io/stdio.dart
@@ -254,13 +254,14 @@
   void set encoding(Encoding encoding) {
     _sink.encoding = encoding;
   }
-  void write(object) => _sink.write(object);
-  void writeln([object = "" ]) => _sink.writeln(object);
-  void writeAll(objects, [sep = ""]) => _sink.writeAll(objects, sep);
-  void add(List<int> data) => _sink.add(data);
-  void addError(error, [StackTrace stackTrace]) =>
-      _sink.addError(error, stackTrace);
-  void writeCharCode(int charCode) => _sink.writeCharCode(charCode);
+  void write(object) { _sink.write(object); }
+  void writeln([object = "" ]) { _sink.writeln(object); }
+  void writeAll(objects, [sep = ""]) { _sink.writeAll(objects, sep); }
+  void add(List<int> data) { _sink.add(data); }
+  void addError(error, [StackTrace stackTrace]) {
+    _sink.addError(error, stackTrace);
+  }
+  void writeCharCode(int charCode) { _sink.writeCharCode(charCode); }
   Future addStream(Stream<List<int>> stream) => _sink.addStream(stream);
   Future flush() => _sink.flush();
   Future close() => _sink.close();
diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart
index 6acd661..0972e84 100644
--- a/sdk/lib/io/websocket_impl.dart
+++ b/sdk/lib/io/websocket_impl.dart
@@ -105,10 +105,11 @@
     });
   }
 
-  void addError(Object error, [StackTrace stackTrace]) =>
-      _eventSink.addError(error, stackTrace);
+  void addError(Object error, [StackTrace stackTrace]) {
+    _eventSink.addError(error, stackTrace);
+  }
 
-  void close() => _eventSink.close();
+  void close() { _eventSink.close(); }
 
   /**
    * Process data received from the underlying communication channel.
@@ -677,8 +678,9 @@
     addFrame(opcode, data);
   }
 
-  void addError(Object error, [StackTrace stackTrace]) =>
-      _eventSink.addError(error, stackTrace);
+  void addError(Object error, [StackTrace stackTrace]) {
+    _eventSink.addError(error, stackTrace);
+  }
 
   void close() {
     int code = webSocket._outCloseCode;
@@ -1161,9 +1163,10 @@
   int get closeCode => _closeCode;
   String get closeReason => _closeReason;
 
-  void add(data) => _sink.add(data);
-  void addError(error, [StackTrace stackTrace]) =>
-      _sink.addError(error, stackTrace);
+  void add(data) { _sink.add(data); }
+  void addError(error, [StackTrace stackTrace]) {
+    _sink.addError(error, stackTrace);
+  }
   Future addStream(Stream stream) => _sink.addStream(stream);
   Future get done => _sink.done;
 
diff --git a/sdk/lib/js/dartium/cached_patches.dart b/sdk/lib/js/dartium/cached_patches.dart
index f6bb4ab..81edc87 100644
--- a/sdk/lib/js/dartium/cached_patches.dart
+++ b/sdk/lib/js/dartium/cached_patches.dart
@@ -3922,15 +3922,6 @@
   get runtimeType => _HTMLMarqueeElement;
   toString() => super.toString();
 }
-patch class _MutationEvent {
-  static Type get instanceRuntimeType => _MutationEventImpl;
-
-}
-class _MutationEventImpl extends _MutationEvent implements js_library.JSObjectInterfacesDom {
-  _MutationEventImpl.internal_() : super.internal_();
-  get runtimeType => _MutationEvent;
-  toString() => super.toString();
-}
 patch class _NamedNodeMap {
   static Type get instanceRuntimeType => _NamedNodeMapImpl;
 
diff --git a/sdk/lib/svg/dart2js/svg_dart2js.dart b/sdk/lib/svg/dart2js/svg_dart2js.dart
index 4b967b9..e15ec4f 100644
--- a/sdk/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk/lib/svg/dart2js/svg_dart2js.dart
@@ -4646,12 +4646,8 @@
   @Experimental() // untriaged
   final StyleSheet sheet;
 
-  // Shadowing definition.
-  String get title => JS("String", "#.title", this);
-
-  set title(String value) {
-    JS("void", "#.title = #", this, value);
-  }
+  // Use implementation from Element.
+  // final String title;
 
   @DomName('SVGStyleElement.type')
   @DocsEditable()
@@ -5085,12 +5081,8 @@
   // Use implementation from Element.
   // final CssStyleDeclaration style;
 
-  // Shadowing definition.
-  int get tabIndex => JS("int", "#.tabIndex", this);
-
-  set tabIndex(int value) {
-    JS("void", "#.tabIndex = #", this, value);
-  }
+  // Use implementation from Element.
+  // final int tabIndex;
 
   @DomName('SVGElement.viewportElement')
   @DocsEditable()
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 2ca320e..0be5cac 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -286,7 +286,8 @@
 LibTest/typed_data/Uint8List/Uint8List.view_A05_t02: RuntimeError # co19-roll r559: Please triage this failure
 LibTest/typed_data/Uint8List/Uint8List.view_A05_t03: RuntimeError # co19-roll r559: Please triage this failure
 LibTest/typed_data/Uint8List/Uint8List_A02_t01: fail # co19-roll r576: Please triage this failure
-Utils/tests/Expect/identical_A01_t01: fail # co19-roll r546: Please triage this failure
+Utils/tests/Expect/identical_A01_t01: fail # co19-roll r546: Please triage this
+WebPlatformTest/DOMEvents/approved/domnodeinserted_t01: Skip # Issue 51
 WebPlatformTest/Utils/test/testFail_t01: RuntimeError # co19-roll r722: Please triage this failure.
 WebPlatformTest/dom/nodes/DOMImplementation-createHTMLDocument_t01: CompileTimeError # co19-roll r722: Please triage this failure.
 WebPlatformTest/dom/nodes/Document-createElement_t01: CompileTimeError # co19-roll r722: Please triage this failure.
@@ -918,6 +919,7 @@
 LayoutTests/fast/dom/SelectorAPI/dumpNodeList-2_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/SelectorAPI/dumpNodeList_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/StyleSheet/css-medialist-item_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/StyleSheet/detached-parent-rule-without-wrapper_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/TreeWalker/TreeWalker-basic_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Window/getMatchedCSSRules-nested-rules_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Window/getMatchedCSSRules-with-pseudo-elements-complex_t01: RuntimeError # Please triage this failure
@@ -935,6 +937,7 @@
 LayoutTests/fast/dom/custom/document-register-basic_t01: RuntimeError # Dartium JSInterop failure
 LayoutTests/fast/dom/custom/document-register-svg-extends_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/custom/element-names_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/dom/custom/upgrade-candidate-remove-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/dataset-xhtml_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/dataset_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/document-importNode-arguments_t01: RuntimeError # Please triage this failure
@@ -1469,6 +1472,9 @@
 WebPlatformTest/shadow-dom/events/event-retargeting/test-001_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/events/event-retargeting/test-002_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/events/event-retargeting/test-004_t01: RuntimeError # Please triage this failure
+WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-004_t01: RuntimeError # Please triage this failure
+WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-005_t01: RuntimeError # Please triage this failure
+WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-007_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-001_t01: Skip # Times out. Please triage this failure
 WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-001_t02: Skip # Times out. Please triage this failure
 WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-001_t05: Skip # Times out. Please triage this failure
@@ -1749,8 +1755,6 @@
 LayoutTests/fast/canvas/webgl/attrib-location-length-limits_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/bad-arguments-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/buffer-bind-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/buffer-data-array-buffer_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/canvas-2d-webgl-texture_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/canvas-resize-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/canvas-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/canvas-zero-size_t01: RuntimeError # Please triage this failure
@@ -1759,7 +1763,6 @@
 LayoutTests/fast/canvas/webgl/context-destroyed-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/context-lost-restored_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/context-lost_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/copy-tex-image-and-sub-image-2d_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/css-webkit-canvas-repaint_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/css-webkit-canvas_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/draw-arrays-out-of-bounds_t01: RuntimeError # Please triage this failure
@@ -1768,23 +1771,17 @@
 LayoutTests/fast/canvas/webgl/drawingbuffer-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/error-reporting_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/framebuffer-bindings-unaffected-on-resize_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/framebuffer-object-attachment_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/framebuffer-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/functions-returning-strings_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/get-active-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/gl-bind-attrib-location-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/gl-enable-enum-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/gl-enum-tests_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/gl-get-calls_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/gl-getshadersource_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-getstring_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/gl-object-get-calls_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-pixelstorei_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/gl-teximage_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/gl-uniformmatrix4fv_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/gl-vertex-attrib-zero-issues_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/gl-vertex-attrib_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-vertexattribpointer_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/glsl-conformance_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/incorrect-context-object-behaviour_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/index-validation-copies-indices_t01: RuntimeError # Please triage this failure
@@ -1792,11 +1789,8 @@
 LayoutTests/fast/canvas/webgl/index-validation-verifies-too-many-indices_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/index-validation-with-resized-buffer_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/index-validation_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/invalid-UTF-16_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/invalid-passed-params_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/is-object_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/null-object-behaviour_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/null-uniform-location_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/object-deletion-behaviour_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/oes-element-index-uint_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/oes-vertex-array-object_t01: RuntimeError # Please triage this failure
@@ -1804,7 +1798,6 @@
 LayoutTests/fast/canvas/webgl/premultiplyalpha-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/program-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/read-pixels-pack-alignment_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/read-pixels-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/renderbuffer-initialization_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/renderer-and-vendor-strings_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/shader-precision-format_t01: RuntimeError # Please triage this failure
@@ -1816,7 +1809,6 @@
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data-rgb565_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data-rgba4444_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data-rgba5551_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgb565_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgba4444_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgba5551_t01: RuntimeError # Please triage this failure
@@ -1833,7 +1825,6 @@
 LayoutTests/fast/canvas/webgl/tex-sub-image-cube-maps_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/texImage2DImageDataTest_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/texImageTest_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texture-active-bind_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/texture-bindings-uneffected-on-resize_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/texture-color-profile_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/texture-complete_t01: RuntimeError # Please triage this failure
@@ -1849,10 +1840,8 @@
 LayoutTests/fast/canvas/webgl/webgl-depth-texture_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/webgl-exceptions_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/webgl-large-texture_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-layer-update_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/webgl-specific_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/webgl-texture-binding-preserved_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-unprefixed-context-id_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/webgl-viewport-parameters-preserved_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-generated-content/malformed-url_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css-generated-content/pseudo-animation_t01: Pass, RuntimeError # Please triage this failure
@@ -2091,7 +2080,6 @@
 LayoutTests/fast/dom/Document/CaretRangeFromPoint/caretRangeFromPoint-in-zoom-and-scroll_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Document/CaretRangeFromPoint/caretRangeFromPoint-with-first-letter-style_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Document/CaretRangeFromPoint/hittest-relative-to-viewport_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/Document/CaretRangeFromPoint/replace-element_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Document/createElement-valid-names_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Document/createElementNS-namespace-err_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Document/document-title-get_t01: RuntimeError # Please triage this failure
@@ -3258,22 +3246,12 @@
 LayoutTests/fast/canvas/setWidthResetAfterForcedRender_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/canvas/webgl/bad-arguments-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/context-attributes-alpha-depth-stencil-antialias-t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/copy-tex-image-and-sub-image-2d_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/framebuffer-bindings-unaffected-on-resize_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/framebuffer-object-attachment_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/framebuffer-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-teximage_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/invalid-passed-params_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/object-deletion-behaviour_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-array-buffer-view_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas-rgb565_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas-rgba4444_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas-rgba5551_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data-rgb565_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data-rgba4444_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data-rgba5551_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgb565_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgba4444_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgba5551_t01: RuntimeError # Please triage this failure
@@ -3283,10 +3261,7 @@
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgba5551_t01: RuntimeError, Timeout # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video_t01: RuntimeError, Timeout # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-input-validation_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-sub-image-2d-bad-args_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-sub-image-2d_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-sub-image-cube-maps_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texImageTest_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/texture-transparent-pixels-initialized_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/uniform-location_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/uninitialized-test_t01: RuntimeError # Please triage this failure
@@ -3499,6 +3474,7 @@
 LayoutTests/fast/dom/Range/mutation_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Range/range-comparePoint_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Range/range-constructor_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/Range/range-created-during-remove-children_t01: RuntimeError
 LayoutTests/fast/dom/Range/range-detached-exceptions_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Range/range-exceptions_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Range/range-expand_t01: RuntimeError # Please triage this failure
@@ -3763,6 +3739,8 @@
 LayoutTests/fast/forms/plaintext-mode-1_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/search-popup-crasher_t01: Pass, RuntimeError # Fails on 7.1. Please triage this failure
 LayoutTests/fast/forms/selection-wrongtype_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/forms/select-set-length-with-mutation-remove_t01: RuntimeError
+LayoutTests/fast/forms/select-set-length-with-mutation-reparent_t01: RuntimeError
 LayoutTests/fast/forms/setrangetext_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/textarea-maxlength_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/textarea-paste-newline_t01: RuntimeError # Please triage this failure
@@ -8150,7 +8128,6 @@
 LayoutTests/fast/dom/Document/CaretRangeFromPoint/caretRangeFromPoint-in-zoom-and-scroll_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Document/CaretRangeFromPoint/caretRangeFromPoint-with-first-letter-style_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Document/CaretRangeFromPoint/hittest-relative-to-viewport_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/Document/CaretRangeFromPoint/replace-element_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Document/createElement-valid-names_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Document/createElementNS-namespace-err_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Element/attribute-uppercase_t01: RuntimeError # Please triage this failure
diff --git a/tests/co19/co19-dartium.status b/tests/co19/co19-dartium.status
index b788b84..1436313 100644
--- a/tests/co19/co19-dartium.status
+++ b/tests/co19/co19-dartium.status
@@ -203,7 +203,6 @@
 Language/Libraries_and_Scripts/URIs/syntax_t10: RuntimeError # Please triage this failure.
 Language/Libraries_and_Scripts/URIs/syntax_t14: RuntimeError # Please triage this failure.
 Language/Libraries_and_Scripts/URIs/syntax_t15: RuntimeError # Please triage this failure.
-Language/Metadata/before_param_t09: RuntimeError # Issue 26187
 Language/Metadata/before_variable_t01: RuntimeError # Please triage this failure.
 Language/Mixins/Mixin_Application/error_t01: Fail # co19 issue 43
 Language/Mixins/Mixin_Application/error_t02: Fail # co19 issue 43
@@ -1383,4 +1382,3 @@
 LibTest/html/Element/insertBefore_A01_t01: RuntimeError # Issue 26134
 LibTest/html/Element/insertAllBefore_A01_t01: RuntimeError # Issue 26134
 LibTest/html/CanvasRenderingContext2D/addEventListener_A01_t06: Skip # Issue 26134, timeout
-html/cross_domain_iframe_test: RuntimeError # Issue 26134
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 57ac699..59ebaf3 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -163,3 +163,8 @@
 LibTest/typed_data/Uint64List/runtimeType_A01_t01: Fail,OK  # Expects exact type name.
 LibTest/typed_data/Uint8ClampedList/runtimeType_A01_t01: Fail,OK  # Expects exact type name.
 LibTest/typed_data/Uint8List/runtimeType_A01_t01: Fail,OK  # Expects exact type name.
+
+[ ($arch == simdbc || $arch == simdbc64) && $mode == debug ]
+# TODO(vegorov) These tests are very slow on unoptimized SIMDBC
+LibTest/collection/ListMixin/ListMixin_class_A01_t02: Timeout
+LibTest/collection/ListBase/ListBase_class_A01_t02: Timeout
diff --git a/tests/compiler/dart2js/analyze_dart2js_helpers_test.dart b/tests/compiler/dart2js/analyze_dart2js_helpers_test.dart
index e774726..7f531eb 100644
--- a/tests/compiler/dart2js/analyze_dart2js_helpers_test.dart
+++ b/tests/compiler/dart2js/analyze_dart2js_helpers_test.dart
@@ -94,7 +94,7 @@
   }
 
   void analyze(ResolvedAst resolvedAst) {
-    if (resolvedAst.node == null) {
+    if (resolvedAst.kind != ResolvedAstKind.PARSED) {
       // Skip synthesized members.
       return;
     }
diff --git a/tests/compiler/dart2js/analyze_test_test.dart b/tests/compiler/dart2js/analyze_test_test.dart
index 5da181c..93cf7b9 100644
--- a/tests/compiler/dart2js/analyze_test_test.dart
+++ b/tests/compiler/dart2js/analyze_test_test.dart
@@ -49,6 +49,8 @@
   "backend_dart/",
   // Broken tests:
   "http_test.dart",
+  // Package directory
+  "packages/",
 ];
 
 const List<MessageKind> MESSAGE_SKIP_LIST = const <MessageKind>[
diff --git a/tests/compiler/dart2js/compiler_test.dart b/tests/compiler/dart2js/compiler_test.dart
index 691b86b..3e595c8 100644
--- a/tests/compiler/dart2js/compiler_test.dart
+++ b/tests/compiler/dart2js/compiler_test.dart
@@ -3,64 +3,27 @@
 // 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";
+import 'package:compiler/compiler.dart';
 import "package:compiler/src/elements/elements.dart";
-import "package:compiler/src/resolution/members.dart";
-import "package:compiler/src/diagnostics/diagnostic_listener.dart";
+import "package:expect/expect.dart";
+
 import "mock_compiler.dart";
-import "diagnostic_reporter_helper.dart";
-
-
-class CallbackMockCompiler extends MockCompiler {
-  CallbackReporter reporter;
-
-  CallbackMockCompiler() : super.internal() {
-    reporter = new CallbackReporter(super.reporter);
-  }
-
-}
-
-class CallbackReporter extends DiagnosticReporterWrapper {
-  final DiagnosticReporter reporter;
-
-  CallbackReporter(this.reporter);
-
-  var onError;
-  var onWarning;
-
-  setOnError(var f) => onError = f;
-  setOnWarning(var f) => onWarning = f;
-
-  void reportWarning(
-      DiagnosticMessage message,
-      [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
-    if (onWarning != null) {
-      onWarning(this, message.spannable, message.message);
-    }
-    super.reportWarning(message, infos);
-  }
-
-  void reportError(
-      DiagnosticMessage message,
-      [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
-    if (onError != null) {
-      onError(this, message.spannable, message.message);
-    }
-    super.reportError(message, infos);
-  }
-}
 
 Future testErrorHandling() {
   // Test that compiler.currentElement is set correctly when
   // reporting errors/warnings.
-  CallbackMockCompiler compiler = new CallbackMockCompiler();
+  MockCompiler compiler = new MockCompiler.internal();
   return compiler.init().then((_) {
-    ResolverVisitor visitor = compiler.resolverVisitor();
     compiler.parseScript('NoSuchPrefix.NoSuchType foo() {}');
     FunctionElement foo = compiler.mainApp.find('foo');
-    compiler.reporter.setOnWarning(
-        (c, n, m) => Expect.equals(foo, compiler.currentElement));
+    compiler.diagnosticHandler =
+        (Uri uri, int begin, int end, String message, Diagnostic kind) {
+      if (kind == Diagnostic.WARNING) {
+        Expect.equals(foo, compiler.currentElement);
+      }
+    };
     foo.computeType(compiler.resolution);
     Expect.equals(1, compiler.diagnosticCollector.warnings.length);
   });
diff --git a/tests/compiler/dart2js/diagnostic_helper.dart b/tests/compiler/dart2js/diagnostic_helper.dart
index c9b19e1..d87579f 100644
--- a/tests/compiler/dart2js/diagnostic_helper.dart
+++ b/tests/compiler/dart2js/diagnostic_helper.dart
@@ -36,11 +36,6 @@
 class DiagnosticCollector implements CompilerDiagnostics {
   List<CollectedMessage> messages = <CollectedMessage>[];
 
-  void call(Uri uri, int begin, int end, String message, Diagnostic kind) {
-    throw '';
-    report(null, uri, begin, end, message, kind);
-  }
-
   @override
   void report(Message message,
               Uri uri, int begin, int end, String text, Diagnostic kind) {
diff --git a/tests/compiler/dart2js/exit_code_test.dart b/tests/compiler/dart2js/exit_code_test.dart
index 715d4d6..b67b026 100644
--- a/tests/compiler/dart2js/exit_code_test.dart
+++ b/tests/compiler/dart2js/exit_code_test.dart
@@ -37,7 +37,7 @@
   final String testMarker;
   final String testType;
   final Function onTest;
-  DiagnosticReporter reporter;
+  TestDiagnosticReporter reporter;
 
   TestCompiler(api.CompilerInput inputProvider,
                api.CompilerOutput outputProvider,
@@ -51,7 +51,8 @@
                String this.testMarker,
                String this.testType,
                Function this.onTest)
-      : super(inputProvider, outputProvider, handler,
+      : reporter = new TestDiagnosticReporter(),
+        super(inputProvider, outputProvider, handler,
             new CompilerOptions.parse(
                 libraryRoot: libraryRoot,
                 packageRoot: packageRoot,
@@ -59,7 +60,8 @@
                 environment: environment,
                 packageConfig: packageConfig,
                 packagesDiscoveryProvider: findPackages)) {
-    reporter = new TestDiagnosticReporter(this, super.reporter);
+    reporter.compiler = this;
+    reporter.reporter = super.reporter;
     test('Compiler');
   }
 
@@ -136,10 +138,8 @@
 }
 
 class TestDiagnosticReporter extends DiagnosticReporterWrapper {
-  final TestCompiler compiler;
-  final DiagnosticReporter reporter;
-
-  TestDiagnosticReporter(this.compiler, this.reporter);
+  TestCompiler compiler;
+  DiagnosticReporter reporter;
 
   @override
   withCurrentElement(Element element, f()) {
diff --git a/tests/compiler/dart2js/find_my_name_test.dart b/tests/compiler/dart2js/find_my_name_test.dart
index dd93af3..3c5c22b 100644
--- a/tests/compiler/dart2js/find_my_name_test.dart
+++ b/tests/compiler/dart2js/find_my_name_test.dart
@@ -36,7 +36,7 @@
 testClass(String code, MockCompiler compiler) {
   int skip = code.indexOf('{');
   ClassElementX cls = parseUnit(code, compiler, compiler.mainApp).head;
-  cls.parseNode(compiler.parsing);
+  cls.parseNode(compiler.parsingContext);
   cls.forEachLocalMember((Element e) {
     String name = e.name;
     if (e.isConstructor) {
diff --git a/tests/compiler/dart2js/library_resolution_test.dart b/tests/compiler/dart2js/library_resolution_test.dart
index c5a5fa7..93a039e 100644
--- a/tests/compiler/dart2js/library_resolution_test.dart
+++ b/tests/compiler/dart2js/library_resolution_test.dart
@@ -37,12 +37,6 @@
             new CompilerOptions(
                 libraryRoot: libraryRoot,
                 packageRoot: packageRoot));
-
-  Uri lookupLibraryUri(String libraryName) {
-    if (libraryName == "m_o_c_k_1") return mock1LibraryUri;
-    if (libraryName == "m_o_c_k_2") return mock2LibraryUri;
-    return super.lookupLibraryUri(libraryName);
-  }
 }
 
 main() async {
@@ -87,6 +81,9 @@
 
   asyncStart();
   await compiler.setupSdk();
+  // TODO(het): Find cleaner way to do this
+  compiler.resolvedUriTranslator.sdkLibraries['m_o_c_k_1'] = mock1LibraryUri;
+  compiler.resolvedUriTranslator.sdkLibraries['m_o_c_k_2'] = mock2LibraryUri;
   var library =
       await compiler.libraryLoader.loadLibrary(Uri.parse("dart:m_o_c_k_1"));
   await checkLibrary(library);
diff --git a/tests/compiler/dart2js/memory_compiler.dart b/tests/compiler/dart2js/memory_compiler.dart
index 7c88613..47c1a43 100644
--- a/tests/compiler/dart2js/memory_compiler.dart
+++ b/tests/compiler/dart2js/memory_compiler.dart
@@ -181,15 +181,10 @@
 
     compiler.backend.constantCompilerTask.copyConstantValues(
         cachedCompiler.backend.constantCompilerTask);
-    compiler.symbolConstructor = cachedCompiler.symbolConstructor;
     compiler.mirrorSystemClass = cachedCompiler.mirrorSystemClass;
     compiler.mirrorsUsedClass = cachedCompiler.mirrorsUsedClass;
     compiler.mirrorSystemGetNameFunction =
         cachedCompiler.mirrorSystemGetNameFunction;
-    compiler.symbolImplementationClass =
-        cachedCompiler.symbolImplementationClass;
-    compiler.symbolValidatedConstructor =
-        cachedCompiler.symbolValidatedConstructor;
     compiler.mirrorsUsedConstructor = cachedCompiler.mirrorsUsedConstructor;
     compiler.deferredLibraryClass = cachedCompiler.deferredLibraryClass;
 
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index e2628b8..839c083 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -27,6 +27,7 @@
 import 'package:compiler/src/resolution/registry.dart';
 import 'package:compiler/src/resolution/scope.dart';
 import 'package:compiler/src/resolution/tree_elements.dart';
+import 'package:compiler/src/resolved_uri_translator.dart';
 import 'package:compiler/src/script.dart';
 import 'package:compiler/src/tree/tree.dart';
 import 'package:compiler/src/old_to_new_api.dart';
@@ -65,6 +66,8 @@
   final String testedPatchVersion;
   final LibrarySourceProvider librariesOverride;
   final DiagnosticCollector diagnosticCollector = new DiagnosticCollector();
+  final ResolvedUriTranslator resolvedUriTranslator =
+      new MockResolvedUriTranslator();
 
   MockCompiler.internal(
       {Map<String, String> coreSource,
@@ -257,9 +260,6 @@
     return new Future.value();
   }
 
-  Uri translateResolvedUri(LibraryElement importingLibrary,
-                           Uri resolvedUri, Spannable spannable) => resolvedUri;
-
   // The mock library doesn't need any patches.
   Uri resolvePatchUri(String dartLibraryName) {
     if (dartLibraryName == 'core') {
@@ -288,6 +288,17 @@
   }
 }
 
+class MockResolvedUriTranslator implements ResolvedUriTranslator {
+  static final _emptySet = new Set();
+
+  Uri translate(LibraryElement importingLibrary, Uri resolvedUri,
+          [Spannable spannable]) =>
+      resolvedUri;
+  Set<Uri> get disallowedLibraryUris => _emptySet;
+  bool get mockableLibraryUsed => false;
+  Map<String, Uri> get sdkLibraries => const <String, Uri>{};
+}
+
 class CollectingTreeElements extends TreeElementMapping {
   final Map<Node, Element> map = new LinkedHashMap<Node, Element>();
 
diff --git a/tests/compiler/dart2js/parser_helper.dart b/tests/compiler/dart2js/parser_helper.dart
index 028fa06..13556b7 100644
--- a/tests/compiler/dart2js/parser_helper.dart
+++ b/tests/compiler/dart2js/parser_helper.dart
@@ -124,7 +124,7 @@
   ElementX element = parseUnit(text, compiler, compiler.mainApp).head;
   Expect.isNotNull(element);
   Expect.equals(ElementKind.FUNCTION, element.kind);
-  return element.parseNode(compiler.parsing);
+  return element.parseNode(compiler.parsingContext);
 }
 
 Node parseMember(String text, {DiagnosticReporter reporter}) {
@@ -153,7 +153,7 @@
   var unit = new CompilationUnitElementX(script, library);
   DiagnosticReporter reporter = compiler.reporter;
   ElementListener listener = new ElementListener(
-      compiler.parsing.getScannerOptionsFor(library),
+      compiler.parsingContext.getScannerOptionsFor(library),
       reporter, unit, new IdGenerator());
   PartialParser parser = new PartialParser(listener, new MockParserOptions());
   reporter.withCurrentElement(unit, () => parser.parseUnit(tokens));
diff --git a/tests/compiler/dart2js/patch_test.dart b/tests/compiler/dart2js/patch_test.dart
index 3581b17..00ef722 100644
--- a/tests/compiler/dart2js/patch_test.dart
+++ b/tests/compiler/dart2js/patch_test.dart
@@ -45,7 +45,7 @@
 }
 
 void expectHasBody(compiler, ElementX element) {
-    var node = element.parseNode(compiler.parsing);
+    var node = element.parseNode(compiler.parsingContext);
     Expect.isNotNull(node, "Element isn't parseable, when a body was expected");
     Expect.isNotNull(node.body);
     // If the element has a body it is either a Block or a Return statement,
@@ -55,7 +55,7 @@
 }
 
 void expectHasNoBody(compiler, ElementX element) {
-    var node = element.parseNode(compiler.parsing);
+    var node = element.parseNode(compiler.parsingContext);
     Expect.isNotNull(node, "Element isn't parseable, when a body was expected");
     Expect.isFalse(node.hasBody);
 }
@@ -336,7 +336,7 @@
       """);
   var container = ensure(compiler, "Class", compiler.coreLibrary.find,
                          expectIsPatched: true);
-  container.parseNode(compiler.parsing);
+  container.parseNode(compiler.parsingContext);
   ensure(compiler, "Class", compiler.coreLibrary.patch.find,
          expectIsPatch: true);
 
@@ -366,7 +366,7 @@
       """);
   var container = ensure(compiler, "Class", compiler.coreLibrary.find,
                          expectIsPatched: true);
-  container.parseNode(compiler.parsing);
+  container.parseNode(compiler.parsingContext);
   ensure(compiler,
          "field",
          container.lookupLocalMember,
@@ -400,7 +400,7 @@
       """);
   var container = ensure(compiler, "Class", compiler.coreLibrary.find,
                          expectIsPatched: true);
-  container.parseNode(compiler.parsing);
+  container.parseNode(compiler.parsingContext);
   ensure(compiler, "Class", compiler.coreLibrary.patch.find,
          expectIsPatch: true);
 
@@ -429,7 +429,7 @@
       """);
   var container = ensure(compiler, "Class", compiler.coreLibrary.find,
                          expectIsPatched: true);
-  container.parseNode(compiler.parsing);
+  container.parseNode(compiler.parsingContext);
   ensure(compiler, "Class", compiler.coreLibrary.patch.find,
          expectIsPatch: true);
 
@@ -458,7 +458,7 @@
       """);
   var container = ensure(compiler, "Class", compiler.coreLibrary.find,
                          expectIsPatched: true);
-  container.parseNode(compiler.parsing);
+  container.parseNode(compiler.parsingContext);
   ensure(compiler, "Class", compiler.coreLibrary.patch.find,
          expectIsPatch: true);
 
@@ -555,7 +555,7 @@
   var container = ensure(compiler, "Class", compiler.coreLibrary.find,
                          expectIsPatched: true);
   container.ensureResolved(compiler.resolution);
-  container.parseNode(compiler.parsing);
+  container.parseNode(compiler.parsingContext);
   DiagnosticCollector collector = compiler.diagnosticCollector;
 
   void expect(String methodName, List infos, List errors) {
@@ -635,7 +635,7 @@
       """);
   var container = ensure(compiler, "Class", compiler.coreLibrary.find,
                          expectIsPatched: true);
-  container.parseNode(compiler.parsing);
+  container.parseNode(compiler.parsingContext);
   DiagnosticCollector collector = compiler.diagnosticCollector;
   collector.clear();
   compiler.resolver.resolveMethodElement(
@@ -696,7 +696,7 @@
       """);
   var container = ensure(compiler, "Class", compiler.coreLibrary.find,
                          expectIsPatched: true);
-  container.parseNode(compiler.parsing);
+  container.parseNode(compiler.parsingContext);
   DiagnosticCollector collector = compiler.diagnosticCollector;
 
   Expect.isTrue(collector.warnings.isEmpty,
@@ -784,7 +784,7 @@
       """);
   var container = ensure(compiler, "Class", compiler.coreLibrary.find,
                          expectIsPatched: true);
-  container.parseNode(compiler.parsing);
+  container.parseNode(compiler.parsingContext);
 
   DiagnosticCollector collector = compiler.diagnosticCollector;
   print('testPatchNonExternalMember.errors:${collector.errors}');
diff --git a/tests/compiler/dart2js/related_types.dart b/tests/compiler/dart2js/related_types.dart
index 12b60c5..d3f04e3 100644
--- a/tests/compiler/dart2js/related_types.dart
+++ b/tests/compiler/dart2js/related_types.dart
@@ -59,9 +59,9 @@
   if (!compiler.resolution.hasBeenResolved(member)) return;
 
   ResolvedAst resolvedAst = member.resolvedAst;
-  RelatedTypesChecker relatedTypesChecker =
-      new RelatedTypesChecker(compiler, resolvedAst);
-  if (resolvedAst.node != null) {
+  if (resolvedAst.kind == ResolvedAstKind.PARSED) {
+    RelatedTypesChecker relatedTypesChecker =
+        new RelatedTypesChecker(compiler, resolvedAst);
     compiler.reporter.withCurrentElement(member.implementation, () {
       relatedTypesChecker.apply(resolvedAst.node);
     });
diff --git a/tests/compiler/dart2js/resolver_test.dart b/tests/compiler/dart2js/resolver_test.dart
index a69ce72..f8fb479 100644
--- a/tests/compiler/dart2js/resolver_test.dart
+++ b/tests/compiler/dart2js/resolver_test.dart
@@ -227,7 +227,7 @@
             new ResolutionRegistry(compiler,
                 new CollectingTreeElements(fooB)));
     FunctionExpression node =
-        (fooB as FunctionElementX).parseNode(compiler.parsing);
+        (fooB as FunctionElementX).parseNode(compiler.parsingContext);
     visitor.visit(node.body);
     Map mapping = map(visitor);
 
@@ -271,7 +271,7 @@
               new ResolutionRegistry(compiler,
                   new CollectingTreeElements(funElement)));
       FunctionExpression function =
-          (funElement as FunctionElementX).parseNode(compiler.parsing);
+          (funElement as FunctionElementX).parseNode(compiler.parsingContext);
       visitor.visit(function.body);
       Map mapping = map(visitor);
       List<Element> values = mapping.values.toList();
@@ -296,7 +296,7 @@
           new ResolutionRegistry(compiler,
               new CollectingTreeElements(funElement)));
       FunctionExpression function =
-          (funElement as FunctionElementX).parseNode(compiler.parsing);
+          (funElement as FunctionElementX).parseNode(compiler.parsingContext);
       visitor.visit(function.body);
       DiagnosticCollector collector = compiler.diagnosticCollector;
       Expect.equals(0, collector.warnings.length);
@@ -665,7 +665,7 @@
     VariableElementX element = compiler.mainApp.find("a");
     Expect.equals(ElementKind.FIELD, element.kind);
     VariableDefinitions node =
-        element.variables.parseNode(element, compiler.parsing);
+        element.variables.parseNode(element, compiler.parsingContext);
     Identifier typeName = node.type.typeName;
     Expect.equals(typeName.source, 'int');
 
@@ -677,9 +677,9 @@
     Expect.isTrue(bElement != cElement);
 
     VariableDefinitions bNode =
-        bElement.variables.parseNode(bElement, compiler.parsing);
+        bElement.variables.parseNode(bElement, compiler.parsingContext);
     VariableDefinitions cNode =
-        cElement.variables.parseNode(cElement, compiler.parsing);
+        cElement.variables.parseNode(cElement, compiler.parsingContext);
     Expect.equals(bNode, cNode);
     Expect.isNull(bNode.type);
     Expect.isTrue(bNode.modifiers.isVar);
diff --git a/tests/compiler/dart2js/serialization_compilation_test.dart b/tests/compiler/dart2js/serialization_compilation_test.dart
new file mode 100644
index 0000000..590f57a
--- /dev/null
+++ b/tests/compiler/dart2js/serialization_compilation_test.dart
@@ -0,0 +1,61 @@
+// 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.
+
+library dart2js.serialization_compilation_test;
+
+import 'dart:async';
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/common/backend_api.dart';
+import 'package:compiler/src/common/names.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/filenames.dart';
+import 'memory_compiler.dart';
+import 'serialization_helper.dart';
+import 'serialization_test_data.dart';
+import 'output_collector.dart';
+
+main(List<String> args) {
+  asyncTest(() async {
+    Arguments arguments = new Arguments.from(args);
+    String serializedData = await serializeDartCore(
+        arguments: arguments,
+        serializeResolvedAst: true);
+    if (arguments.filename != null) {
+      Uri entryPoint = Uri.base.resolve(nativeToUriPath(arguments.filename));
+      await compile(serializedData, entryPoint, null);
+    } else {
+      Uri entryPoint = Uri.parse('memory:main.dart');
+      // TODO(johnniwinther): Handle the remaining tests.
+      for (Test test in TESTS.sublist(0, 1)) {
+        await compile(serializedData, entryPoint, test,
+                      verbose: arguments.verbose);
+      }
+    }
+  });
+}
+
+Future compile(String serializedData, Uri entryPoint, Test test,
+               {bool verbose: false}) async {
+  String testDescription =
+      test != null ? test.sourceFiles[entryPoint.path] : '${entryPoint}';
+  print('------------------------------------------------------------------');
+  print('compile ${testDescription}');
+  print('------------------------------------------------------------------');
+  OutputCollector outputCollector = new OutputCollector();
+  await runCompiler(
+      entryPoint: entryPoint,
+      memorySourceFiles: test != null ? test.sourceFiles : const {},
+      options: [Flags.disableTypeInference,
+                Flags.disableInlining],
+      outputProvider: outputCollector,
+      beforeRun: (Compiler compiler) {
+        deserialize(compiler, serializedData, deserializeResolvedAst: true);
+      });
+  if (verbose) {
+    print(outputCollector.getOutput('', 'js'));
+  }
+}
+
diff --git a/tests/compiler/dart2js/serialization_helper.dart b/tests/compiler/dart2js/serialization_helper.dart
index c863265..2d1ea1f 100644
--- a/tests/compiler/dart2js/serialization_helper.dart
+++ b/tests/compiler/dart2js/serialization_helper.dart
@@ -5,41 +5,95 @@
 library dart2js.serialization_helper;
 
 import 'dart:async';
-import 'package:async_helper/async_helper.dart';
-import 'package:expect/expect.dart';
-import 'package:compiler/compiler_new.dart';
+import 'dart:io';
+
 import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/common.dart';
 import 'package:compiler/src/common/backend_api.dart';
 import 'package:compiler/src/common/names.dart';
 import 'package:compiler/src/common/resolution.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/elements.dart';
-import 'package:compiler/src/filenames.dart';
 import 'package:compiler/src/io/source_file.dart';
 import 'package:compiler/src/scanner/scanner.dart';
-import 'package:compiler/src/serialization/element_serialization.dart';
+import 'package:compiler/src/script.dart';
 import 'package:compiler/src/serialization/impact_serialization.dart';
 import 'package:compiler/src/serialization/json_serializer.dart';
+import 'package:compiler/src/serialization/modelz.dart';
 import 'package:compiler/src/serialization/resolved_ast_serialization.dart';
 import 'package:compiler/src/serialization/serialization.dart';
-import 'package:compiler/src/serialization/modelz.dart';
 import 'package:compiler/src/serialization/task.dart';
 import 'package:compiler/src/tokens/token.dart';
-import 'package:compiler/src/script.dart';
+import 'package:compiler/src/universe/call_structure.dart';
 import 'package:compiler/src/universe/world_impact.dart';
+import 'package:compiler/src/universe/use.dart';
+
 import 'memory_compiler.dart';
 
+class Arguments {
+  final String filename;
+  final bool loadSerializedData;
+  final bool saveSerializedData;
+  final String serializedDataFileName;
+  final bool verbose;
 
-Future<String> serializeDartCore({bool serializeResolvedAst: false}) async {
-  Compiler compiler = compilerFor(
-      options: [Flags.analyzeAll]);
-  compiler.serialization.supportSerialization = true;
-  await compiler.run(Uris.dart_core);
-  return serialize(
-      compiler,
-      compiler.libraryLoader.libraries,
-      serializeResolvedAst: serializeResolvedAst)
-        .toText(const JsonSerializationEncoder());
+  const Arguments({
+    this.filename,
+    this.loadSerializedData: false,
+    this.saveSerializedData: false,
+    this.serializedDataFileName: 'out.data',
+    this.verbose: false});
+
+  factory Arguments.from(List<String> arguments) {
+    String filename;
+    for (String arg in arguments) {
+      if (!arg.startsWith('-')) {
+        filename = arg;
+      }
+    }
+    bool verbose = arguments.contains('-v');
+    bool loadSerializedData = arguments.contains('-l');
+    bool saveSerializedData = arguments.contains('-s');
+    return new Arguments(
+        filename: filename,
+        verbose: verbose,
+        loadSerializedData: loadSerializedData,
+        saveSerializedData: saveSerializedData);
+  }
+}
+
+
+Future<String> serializeDartCore(
+    {Arguments arguments: const Arguments(),
+     bool serializeResolvedAst: false}) async {
+  print('------------------------------------------------------------------');
+  print('serialize dart:core');
+  print('------------------------------------------------------------------');
+  String serializedData;
+  if (arguments.loadSerializedData) {
+    File file = new File(arguments.serializedDataFileName);
+    if (file.existsSync()) {
+      print('Loading data from $file');
+      serializedData = file.readAsStringSync();
+    }
+  }
+  if (serializedData == null) {
+    Compiler compiler = compilerFor(
+        options: [Flags.analyzeAll]);
+    compiler.serialization.supportSerialization = true;
+    await compiler.run(Uris.dart_core);
+    serializedData = serialize(
+        compiler,
+        compiler.libraryLoader.libraries,
+        serializeResolvedAst: serializeResolvedAst)
+          .toText(const JsonSerializationEncoder());
+    if (arguments.saveSerializedData) {
+      File file = new File(arguments.serializedDataFileName);
+      print('Saving data to $file');
+      file.writeAsStringSync(serializedData);
+    }
+  }
+  return serializedData;
 }
 
 Serializer serialize(
@@ -53,7 +107,7 @@
   serializer.plugins.add(new ResolutionImpactSerializer(compiler.resolution));
   if (serializeResolvedAst) {
     serializer.plugins.add(
-        new ResolvedAstSerializerPlugin(compiler.resolution));
+        new ResolvedAstSerializerPlugin(compiler.resolution, compiler.backend));
   }
 
   for (LibraryElement library in libraries) {
@@ -91,7 +145,7 @@
     if (resolution.hasBeenResolved(element)) {
       ResolutionImpact impact = resolution.getResolutionImpact(element);
       ObjectEncoder encoder = createEncoder(WORLD_IMPACT_TAG);
-      new ImpactSerializer(encoder).serialize(impact);
+      new ImpactSerializer(element, encoder).serialize(impact);
     }
   }
 }
@@ -103,7 +157,8 @@
   void onElement(Element element, ObjectDecoder getDecoder(String tag)) {
     ObjectDecoder decoder = getDecoder(WORLD_IMPACT_TAG);
     if (decoder != null) {
-      impactMap[element] = ImpactDeserializer.deserializeImpact(decoder);
+      impactMap[element] =
+          ImpactDeserializer.deserializeImpact(element, decoder);
     }
   }
 }
@@ -126,7 +181,8 @@
       : this._compiler = compiler,
         this._deserializeResolvedAst = deserializeResolvedAst,
         this._resolvedAstDeserializer = deserializeResolvedAst
-           ? new ResolvedAstDeserializerPlugin(compiler.parsing) : null {
+           ? new ResolvedAstDeserializerPlugin(
+               compiler.parsingContext, compiler.backend) : null {
     _deserializer.plugins.add(_resolutionImpactDeserializer);
     if (_deserializeResolvedAst) {
       _deserializer.plugins.add(_resolvedAstDeserializer);
@@ -141,9 +197,10 @@
       if (_deserializeResolvedAst) {
         return Future.forEach(library.compilationUnits,
             (CompilationUnitElement compilationUnit) {
-          Script script = compilationUnit.script;
+          ScriptZ script = compilationUnit.script;
           return _compiler.readScript(script.readableUri)
               .then((Script newScript) {
+            script.file = newScript.file;
             _resolvedAstDeserializer.sourceFiles[script.resourceUri] =
                 newScript.file;
           });
@@ -154,6 +211,14 @@
   }
 
   @override
+  bool hasResolvedAst(Element element) {
+    if (_resolvedAstDeserializer != null) {
+      return _resolvedAstDeserializer.hasResolvedAst(element);
+    }
+    return false;
+  }
+
+  @override
   ResolvedAst getResolvedAst(Element element) {
     if (_resolvedAstDeserializer != null) {
       return _resolvedAstDeserializer.getResolvedAst(element);
@@ -162,19 +227,41 @@
   }
 
   @override
+  bool hasResolutionImpact(Element element) {
+    if (element.isConstructor &&
+            element.enclosingClass.isUnnamedMixinApplication) {
+      return true;
+    }
+    return _resolutionImpactDeserializer.impactMap.containsKey(element);
+  }
+
+  @override
   ResolutionImpact getResolutionImpact(Element element) {
+    if (element.isConstructor &&
+        element.enclosingClass.isUnnamedMixinApplication) {
+      ClassElement superclass =  element.enclosingClass.superclass;
+      ConstructorElement superclassConstructor =
+          superclass.lookupConstructor(element.name);
+      assert(invariant(element, superclassConstructor != null,
+          message: "Superclass constructor '${element.name}' called from "
+                   "${element} not found in ${superclass}."));
+      // TODO(johnniwinther): Compute callStructure. Currently not used.
+      CallStructure callStructure;
+      return _resolutionImpactDeserializer.impactMap.putIfAbsent(element, () {
+        return new DeserializedResolutionImpact(
+            staticUses: <StaticUse>[new StaticUse.superConstructorInvoke(
+                superclassConstructor, callStructure)]);
+      });
+    }
     return _resolutionImpactDeserializer.impactMap[element];
   }
 
   @override
   WorldImpact computeWorldImpact(Element element) {
     ResolutionImpact resolutionImpact = getResolutionImpact(element);
-    if (resolutionImpact == null) {
-      print('No impact found for $element (${element.library})');
-      return const WorldImpact();
-    } else {
-      return _impactTransformer.transformResolutionImpact(resolutionImpact);
-    }
+    assert(invariant(element, resolutionImpact != null,
+        message: 'No impact found for $element (${element.library})'));
+    return _impactTransformer.transformResolutionImpact(resolutionImpact);
   }
 
   @override
@@ -187,28 +274,42 @@
 
 class ResolvedAstSerializerPlugin extends SerializerPlugin {
   final Resolution resolution;
+  final Backend backend;
 
-  ResolvedAstSerializerPlugin(this.resolution);
+  ResolvedAstSerializerPlugin(this.resolution, this.backend);
 
   @override
   void onElement(Element element, ObjectEncoder createEncoder(String tag)) {
-    if (element is MemberElement && resolution.hasResolvedAst(element)) {
+    assert(invariant(element, element.isDeclaration,
+        message: "Element $element must be the declaration"));
+    if (element is MemberElement) {
+      assert(invariant(element, resolution.hasResolvedAst(element),
+          message: "Element $element must have a resolved ast"));
       ResolvedAst resolvedAst = resolution.getResolvedAst(element);
       ObjectEncoder objectEncoder = createEncoder(RESOLVED_AST_TAG);
-      new ResolvedAstSerializer(objectEncoder, resolvedAst).serialize();
+      new ResolvedAstSerializer(
+          objectEncoder,
+          resolvedAst,
+          backend.serialization.serializer).serialize();
     }
   }
 }
 
 class ResolvedAstDeserializerPlugin extends DeserializerPlugin {
-  final Parsing parsing;
+  final ParsingContext parsingContext;
+  final Backend backend;
   final Map<Uri, SourceFile> sourceFiles = <Uri, SourceFile>{};
 
   Map<Element, ResolvedAst> _resolvedAstMap = <Element, ResolvedAst>{};
   Map<Element, ObjectDecoder> _decoderMap = <Element, ObjectDecoder>{};
   Map<Uri, Token> beginTokenMap = <Uri, Token>{};
 
-  ResolvedAstDeserializerPlugin(this.parsing);
+  ResolvedAstDeserializerPlugin(this.parsingContext, this.backend);
+
+  bool hasResolvedAst(Element element) {
+    return _resolvedAstMap.containsKey(element) ||
+        _decoderMap.containsKey(element);
+  }
 
   ResolvedAst getResolvedAst(Element element) {
     ResolvedAst resolvedAst = _resolvedAstMap[element];
@@ -217,7 +318,8 @@
       if (decoder != null) {
         resolvedAst = _resolvedAstMap[element] =
             ResolvedAstDeserializer.deserialize(
-                element, decoder, parsing, findToken);
+                element, decoder, parsingContext, findToken,
+                backend.serialization.deserializer);
         _decoderMap.remove(element);
       }
     }
diff --git a/tests/compiler/dart2js/serialization_impact_test.dart b/tests/compiler/dart2js/serialization_impact_test.dart
index 05d91d6..6f5fd15 100644
--- a/tests/compiler/dart2js/serialization_impact_test.dart
+++ b/tests/compiler/dart2js/serialization_impact_test.dart
@@ -16,15 +16,18 @@
 import 'serialization_helper.dart';
 import 'serialization_test_helper.dart';
 
-main(List<String> arguments) {
+main(List<String> args) {
+  Arguments arguments = new Arguments.from(args);
   asyncTest(() async {
-    String serializedData = await serializeDartCore();
-    if (arguments.isNotEmpty) {
-      Uri entryPoint = Uri.base.resolve(nativeToUriPath(arguments.last));
+    String serializedData = await serializeDartCore(arguments: arguments);
+    if (arguments.filename != null) {
+      Uri entryPoint = Uri.base.resolve(nativeToUriPath(arguments.filename));
       await check(serializedData, entryPoint);
     } else {
       Uri entryPoint = Uri.parse('memory:main.dart');
-      await check(serializedData, entryPoint, {'main.dart': 'main() {}'});
+      await check(serializedData, entryPoint,
+                  sourceFiles:  {'main.dart': 'main() {}'},
+                  verbose: arguments.verbose);
     }
   });
 }
@@ -32,20 +35,21 @@
 Future check(
   String serializedData,
   Uri entryPoint,
-  [Map<String, String> sourceFiles = const <String, String>{}]) async {
+  {Map<String, String> sourceFiles: const <String, String>{},
+   bool verbose: false}) async {
 
   Compiler compilerNormal = compilerFor(
       memorySourceFiles: sourceFiles,
-      options: [Flags.analyzeOnly]);
+      options: [Flags.analyzeAll]);
   compilerNormal.resolution.retainCachesForTesting = true;
   await compilerNormal.run(entryPoint);
 
   Compiler compilerDeserialized = compilerFor(
       memorySourceFiles: sourceFiles,
-      options: [Flags.analyzeOnly]);
+      options: [Flags.analyzeAll]);
   compilerDeserialized.resolution.retainCachesForTesting = true;
   deserialize(compilerDeserialized, serializedData);
   await compilerDeserialized.run(entryPoint);
 
-  checkAllImpacts(compilerNormal, compilerDeserialized, verbose: true);
+  checkAllImpacts(compilerNormal, compilerDeserialized, verbose: verbose);
 }
diff --git a/tests/compiler/dart2js/serialization_model_test.dart b/tests/compiler/dart2js/serialization_model_test.dart
index 0e5363f..52547ae 100644
--- a/tests/compiler/dart2js/serialization_model_test.dart
+++ b/tests/compiler/dart2js/serialization_model_test.dart
@@ -30,52 +30,23 @@
 import 'serialization_test_data.dart';
 import 'serialization_test_helper.dart';
 
-main(List<String> arguments) {
-  String filename;
-  for (String arg in arguments) {
-    if (!arg.startsWith('-')) {
-      filename = arg;
-    }
-  }
-  bool verbose = arguments.contains('-v');
-
+main(List<String> args) {
   asyncTest(() async {
-    print('------------------------------------------------------------------');
-    print('serialize dart:core');
-    print('------------------------------------------------------------------');
-    String serializedData;
-    File file = new File('out.data');
-    if (arguments.contains('-l')) {
-      if (file.existsSync()) {
-        print('Loading data from $file');
-        serializedData = file.readAsStringSync();
-      }
-    }
-    if (serializedData == null) {
-      serializedData = await serializeDartCore();
-      if (arguments.contains('-s')) {
-        print('Saving data to $file');
-        file.writeAsStringSync(serializedData);
-      }
-    }
-    if (filename != null) {
-      Uri entryPoint = Uri.base.resolve(nativeToUriPath(filename));
+    Arguments arguments = new Arguments.from(args);
+    String serializedData = await serializeDartCore(arguments: arguments);
+    if (arguments.filename != null) {
+      Uri entryPoint = Uri.base.resolve(nativeToUriPath(arguments.filename));
       await check(serializedData, entryPoint);
     } else {
       Uri entryPoint = Uri.parse('memory:main.dart');
       for (Test test in TESTS) {
-        if (test.sourceFiles['main.dart']
-                .contains('main(List<String> arguments)')) {
-          // TODO(johnniwinther): Check this test.
-          continue;
-        }
         print('==============================================================');
         print(test.sourceFiles);
         await check(
           serializedData,
           entryPoint,
           sourceFiles: test.sourceFiles,
-          verbose: verbose);
+          verbose: arguments.verbose);
       }
     }
   });
diff --git a/tests/compiler/dart2js/serialization_resolved_ast_test.dart b/tests/compiler/dart2js/serialization_resolved_ast_test.dart
index af5d8a3..7712f9a 100644
--- a/tests/compiler/dart2js/serialization_resolved_ast_test.dart
+++ b/tests/compiler/dart2js/serialization_resolved_ast_test.dart
@@ -20,11 +20,13 @@
 import 'serialization_test_helper.dart';
 
 
-main(List<String> arguments) {
+main(List<String> args) {
+  Arguments arguments = new Arguments.from(args);
   asyncTest(() async {
-    String serializedData = await serializeDartCore(serializeResolvedAst: true);
-    if (arguments.isNotEmpty) {
-      Uri entryPoint = Uri.base.resolve(nativeToUriPath(arguments.last));
+    String serializedData = await serializeDartCore(
+        arguments: arguments, serializeResolvedAst: true);
+    if (arguments.filename != null) {
+      Uri entryPoint = Uri.base.resolve(nativeToUriPath(arguments.filename));
       await check(serializedData, entryPoint);
     } else {
       Uri entryPoint = Uri.parse('memory:main.dart');
@@ -43,13 +45,13 @@
 
   Compiler compilerNormal = compilerFor(
       memorySourceFiles: sourceFiles,
-      options: [Flags.analyzeOnly]);
+      options: [Flags.analyzeAll]);
   compilerNormal.resolution.retainCachesForTesting = true;
   await compilerNormal.run(entryPoint);
 
   Compiler compilerDeserialized = compilerFor(
       memorySourceFiles: sourceFiles,
-      options: [Flags.analyzeOnly]);
+      options: [Flags.analyzeAll]);
   compilerDeserialized.resolution.retainCachesForTesting = true;
   deserialize(
       compilerDeserialized, serializedData, deserializeResolvedAst: true);
@@ -69,7 +71,7 @@
         return compiler1.resolution.hasResolvedAst(member1);
       },
       checkResolvedAsts,
-      verbose: true);
+      verbose: verbose);
 }
 
 
diff --git a/tests/compiler/dart2js/serialization_test.dart b/tests/compiler/dart2js/serialization_test.dart
index fd6ae58..9d15022 100644
--- a/tests/compiler/dart2js/serialization_test.dart
+++ b/tests/compiler/dart2js/serialization_test.dart
@@ -8,6 +8,7 @@
 import 'memory_compiler.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/common.dart';
 import 'package:compiler/src/constants/constructors.dart';
 import 'package:compiler/src/constants/expressions.dart';
 import 'package:compiler/src/dart_types.dart';
@@ -347,7 +348,6 @@
           throw message;
         }
       }
-      //print('Checking member ${member1} against ${member2}');
       visit(member1, member2);
     }
   }
@@ -480,6 +480,10 @@
         checkElementProperties);
     check(element1, element2, 'isOperator',
           element1.isOperator, element2.isOperator);
+    check(
+        element1, element2, 'asyncMarker',
+        element1.asyncMarker,
+        element2.asyncMarker);
 
     checkElementIdentities(
         element1, element2, 'library',
@@ -490,6 +494,44 @@
     checkElementIdentities(
         element1, element2, 'enclosingClass',
         element1.enclosingClass, element2.enclosingClass);
+
+    check(
+        element1, element2, 'functionSignature.type',
+        element1.functionSignature.type,
+        element2.functionSignature.type,
+        areTypesEquivalent);
+    checkElementLists(
+        element1, element2, 'functionSignature.requiredParameters',
+        element1.functionSignature.requiredParameters,
+        element2.functionSignature.requiredParameters);
+    checkElementLists(
+        element1, element2, 'functionSignature.optionalParameters',
+        element1.functionSignature.optionalParameters,
+        element2.functionSignature.optionalParameters);
+    check(
+        element1, element2, 'functionSignature.requiredParameterCount',
+        element1.functionSignature.requiredParameterCount,
+        element2.functionSignature.requiredParameterCount);
+    check(
+        element1, element2, 'functionSignature.optionalParameterCount',
+        element1.functionSignature.optionalParameterCount,
+        element2.functionSignature.optionalParameterCount);
+    check(
+        element1, element2, 'functionSignature.optionalParametersAreNamed',
+        element1.functionSignature.optionalParametersAreNamed,
+        element2.functionSignature.optionalParametersAreNamed);
+    check(
+        element1, element2, 'functionSignature.hasOptionalParameters',
+        element1.functionSignature.hasOptionalParameters,
+        element2.functionSignature.hasOptionalParameters);
+    check(
+        element1, element2, 'functionSignature.parameterCount',
+        element1.functionSignature.parameterCount,
+        element2.functionSignature.parameterCount);
+    checkElementLists(
+        element1, element2, 'functionSignature.orderedOptionalParameters',
+        element1.functionSignature.orderedOptionalParameters,
+        element2.functionSignature.orderedOptionalParameters);
   }
 
   @override
@@ -586,6 +628,9 @@
     check(
         element1, element2, 'isNamed',
         element1.isNamed, element2.isNamed);
+    check(
+        element1, element2, 'isFinal',
+        element1.isFinal, element2.isFinal);
     check(element1, element2, 'name', element1.name, element2.name);
     if (element1.isOptional) {
       checkConstants(
diff --git a/tests/compiler/dart2js/serialization_test_data.dart b/tests/compiler/dart2js/serialization_test_data.dart
index 67d400c..3056735 100644
--- a/tests/compiler/dart2js/serialization_test_data.dart
+++ b/tests/compiler/dart2js/serialization_test_data.dart
@@ -188,6 +188,19 @@
   },
   expectedWarningCount: 1,
   expectedInfoCount: 0),
+
+  const Test(const {
+    'main.dart': '''
+main() {
+  loop: for (var a in []) {
+    for (var b in []) {
+      continue loop;
+    }
+    break;
+  }      
+}'''
+  }),
+
 ];
 
 class Test {
diff --git a/tests/compiler/dart2js/serialization_test_helper.dart b/tests/compiler/dart2js/serialization_test_helper.dart
index 97d5134..4ee842d 100644
--- a/tests/compiler/dart2js/serialization_test_helper.dart
+++ b/tests/compiler/dart2js/serialization_test_helper.dart
@@ -104,9 +104,9 @@
 bool check(var object1, var object2, String property, var value1, var value2,
            [bool equivalence(a, b) = equality]) {
   if (!equivalence(value1, value2)) {
-    throw "property='$property' "
-          "object1=$object1 (${object1.runtimeType}), value='${value1}' <> "
-          "object2=$object2 (${object2.runtimeType}), value='${value2}'";
+    throw "property='$property'\n "
+          "object1=$object1 (${object1.runtimeType})\n value='${value1}' <>\n "
+          "object2=$object2 (${object2.runtimeType})\n value='${value2}'";
   }
   return true;
 }
@@ -212,12 +212,8 @@
     Object object1, Object object2, String property,
     Element element1, Element element2) {
   if (identical(element1, element2)) return true;
-  if (element1 == null || element2 == null) {
-    return check(object1, object2, property, element1, element2);
-  } else {
-    return const ElementIdentityEquivalence(const CheckStrategy())
-        .visit(element1, element2);
-  }
+  return check(object1, object2,
+      property, element1, element2, areElementsEquivalent);
 }
 
 /// Checks the pair-wise equivalence of the identity (but not properties) of the
@@ -298,9 +294,20 @@
     if (member1.isClass && member2.isClass) {
       ClassElement class1 = member1;
       ClassElement class2 = member2;
+      if (!class1.isResolved) return;
+
       class1.forEachLocalMember((m1) {
-        checkMembers(m1, class2.lookupLocalMember(m1.name));
+        checkMembers(m1, class2.localLookup(m1.name));
       });
+      ClassElement superclass1 = class1.superclass;
+      ClassElement superclass2 = class2.superclass;
+      while (superclass1 != null && superclass1.isUnnamedMixinApplication) {
+        for (ConstructorElement c1 in superclass1.constructors) {
+          checkMembers(c1, superclass2.lookupConstructor(c1.name));
+        }
+        superclass1 = superclass1.superclass;
+        superclass2 = superclass2.superclass;
+      }
       return;
     }
 
@@ -309,7 +316,7 @@
     }
 
     if (member2 == null) {
-      return;
+      throw 'Missing member for ${member1}';
     }
 
     if (areElementsEquivalent(member1, member2)) {
@@ -344,7 +351,7 @@
         return compiler1.resolution.hasResolutionImpact(member1);
       },
       checkImpacts,
-      verbose: true);
+      verbose: verbose);
 }
 
 /// Check equivalence of resolution impact for [member1] and [member2].
@@ -352,14 +359,20 @@
                   Compiler compiler2, Element member2,
                   {bool verbose: false}) {
   ResolutionImpact impact1 = compiler1.resolution.getResolutionImpact(member1);
-  ResolutionImpact impact2 =
-      compiler2.serialization.deserializer.getResolutionImpact(member2);
+  ResolutionImpact impact2 = compiler2.resolution.getResolutionImpact(member2);
 
-  if (impact1 == null || impact2 == null) return;
+  if (impact1 == null && impact2 == null) return;
 
   if (verbose) {
     print('Checking impacts for $member1 vs $member2');
   }
 
+  if (impact1 == null) {
+    throw 'Missing impact for $member1. $member2 has $impact2';
+  }
+  if (impact2 == null) {
+    throw 'Missing impact for $member2. $member1 has $impact1';
+  }
+
   testResolutionImpactEquivalence(impact1, impact2, const CheckStrategy());
 }
diff --git a/tests/compiler/dart2js/type_checker_test.dart b/tests/compiler/dart2js/type_checker_test.dart
index 446062f..0b3fb87 100644
--- a/tests/compiler/dart2js/type_checker_test.dart
+++ b/tests/compiler/dart2js/type_checker_test.dart
@@ -2513,13 +2513,13 @@
         classElement.forEachLocalMember((Element e) {
           if (!e.isSynthesized) {
             element = e;
-            node = element.parseNode(compiler.parsing);
+            node = element.parseNode(compiler.parsingContext);
             compiler.resolver.resolve(element);
             mapping = element.treeElements;
           }
         });
       } else {
-        node = element.parseNode(compiler.parsing);
+        node = element.parseNode(compiler.parsingContext);
         compiler.resolver.resolve(element);
         mapping = element.treeElements;
       }
diff --git a/tests/compiler/dart2js/user_crash_test.dart b/tests/compiler/dart2js/user_crash_test.dart
new file mode 100644
index 0000000..305de2a
--- /dev/null
+++ b/tests/compiler/dart2js/user_crash_test.dart
@@ -0,0 +1,102 @@
+// 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:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+import 'package:compiler/compiler_new.dart';
+import 'memory_compiler.dart';
+
+final EXCEPTION = 'Crash';
+
+main() {
+  asyncTest(() async {
+    test('Empty program', await run());
+    test('Crash diagnostics',
+         await run(diagnostics: new CrashingDiagnostics()),
+         expectedLines: [
+           'Uncaught exception in diagnostic handler: $EXCEPTION',
+           null /* Stack trace*/],
+         expectedExceptions: [EXCEPTION]);
+    test('Throw in package discovery',
+         await run(packagesDiscoveryProvider: (_) { throw EXCEPTION; }),
+         expectedLines: [
+           'Uncaught exception in package discovery: $EXCEPTION',
+           null /* Stack trace*/],
+         expectedExceptions: [EXCEPTION]);
+    test('new Future.error in package discovery',
+         await run(packagesDiscoveryProvider:
+             (_) => new Future.error(EXCEPTION)),
+         expectedExceptions: [EXCEPTION]);
+    test('Throw in input provider',
+         await run(memorySourceFiles: new CrashingMap()),
+         expectedLines: [
+           'Uncaught exception in input provider: $EXCEPTION',
+           null, // Stack trace
+           'memory:main.dart:\nError: $EXCEPTION' /* READ_SELF_ERROR */]);
+  });
+}
+
+void test(String title, RunResult result,
+          {List expectedLines: const [],
+           List expectedExceptions: const []}) {
+  print('--------------------------------------------------------------------');
+  print('Running $title');
+  print('--------------------------------------------------------------------');
+  print('lines:');
+  result.lines.forEach(print);
+  print('exceptions:');
+  result.exceptions.forEach(print);
+  Expect.equals(expectedLines.length, result.lines.length,
+      "Unexpected number of calls to print.");
+  Expect.equals(expectedExceptions.length, result.exceptions.length,
+      "Unexpected number of exceptions.");
+  for (int i = 0; i < expectedLines.length; i++) {
+    if (expectedLines[i] != null) {
+      Expect.equals(expectedLines[i], result.lines[i]);
+    }
+  }
+}
+
+Future<RunResult> run(
+    {Map<String, String> memorySourceFiles: const {'main.dart': 'main() {}'},
+     CompilerDiagnostics diagnostics,
+     PackagesDiscoveryProvider packagesDiscoveryProvider}) async {
+  RunResult result = new RunResult();
+  await runZoned(() async {
+    try {
+      await runCompiler(
+          entryPoint: Uri.parse('memory:main.dart'),
+          memorySourceFiles: memorySourceFiles,
+          diagnosticHandler: diagnostics,
+          packagesDiscoveryProvider: packagesDiscoveryProvider);
+    } catch (e) {
+      result.exceptions.add(e);
+    }
+
+  },
+  zoneSpecification: new ZoneSpecification(print:
+    (Zone self, ZoneDelegate parent, Zone zone, String line) {
+    result.lines.add(line);
+  }));
+  return result;
+}
+
+class RunResult {
+  List<String> lines = <String>[];
+  List exceptions = [];
+}
+
+class CrashingDiagnostics extends DiagnosticCollector {
+  @override
+  void report(code, Uri uri, int begin, int end, String text, Diagnostic kind) {
+    throw EXCEPTION;
+  }
+}
+
+class CrashingMap implements Map<String, String> {
+  operator [](_) => throw EXCEPTION;
+
+  noSuchMethod(_) => null;
+}
\ No newline at end of file
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index fe92613..60a6bc5 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -207,4 +207,7 @@
 data_resource_test: Skip # Resolve URI not supported yet in product mode.
 package_resource_test: Skip # Resolve URI not supported yet in product mode.
 file_resource_test: Skip # Resolve URI not supported yet in product mode.
-http_resource_test: Skip # Resolve URI not supported yet in product mode.
\ No newline at end of file
+http_resource_test: Skip # Resolve URI not supported yet in product mode.
+
+[ $arch == simdbc || $arch == simdbc64 ]
+regexp/stack-overflow_test: RuntimeError, OK # Smaller limit with irregex interpreter
diff --git a/tests/corelib/uri_test.dart b/tests/corelib/uri_test.dart
index fd281c5..f1dce7a 100644
--- a/tests/corelib/uri_test.dart
+++ b/tests/corelib/uri_test.dart
@@ -407,7 +407,8 @@
       var fragment = uri1.hasFragment ? uri1.fragment : null;
 
       var tmp1 = uri1;
-      test() {
+
+      void test() {
         var tmp2 = new Uri(scheme: scheme, userInfo: userInfo, host: host,
                            port: port, path: path,
                            query: query == "" ? null : query,
@@ -452,6 +453,14 @@
   var uri = Uri.parse("/no-authorty/");
   uri = uri.replace(fragment: "fragment");
   Expect.isFalse(uri.hasAuthority);
+
+  uri = new Uri(scheme: "foo", path: "bar");
+  uri = uri.replace(
+      queryParameters: {"x": ["42", "37"], "y": ["43", "38"]});
+  var params = uri.queryParametersAll;
+  Expect.equals(2, params.length);
+  Expect.listEquals(["42", "37"], params["x"]);
+  Expect.listEquals(["43", "38"], params["y"]);
 }
 
 main() {
diff --git a/tests/html/element_test.dart b/tests/html/element_test.dart
index 42c4ebe..c1f74b5 100644
--- a/tests/html/element_test.dart
+++ b/tests/html/element_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 library ElementTest;
+
 import 'package:unittest/unittest.dart';
 import 'package:unittest/html_individual_config.dart';
 import 'dart:async';
@@ -47,7 +48,7 @@
   Element makeElement() => new Element.tag('div');
 
   Element makeElementWithChildren() =>
-    new Element.html("<div><br/><img/><input/></div>");
+      new Element.html("<div><br/><img/><input/></div>");
 
   group('position', () {
     test('computedStyle', () {
@@ -87,8 +88,8 @@
       expect(() => new Element.html('<br/><br/>'), throwsStateError);
     });
 
-    test('.html has no parent', () =>
-        expect(new Element.html('<br/>').parent, isNull));
+    test('.html has no parent',
+        () => expect(new Element.html('<br/>').parent, isNull));
 
     test('.html table', () {
       // http://developers.whatwg.org/tabular-data.html#tabular-data
@@ -126,8 +127,10 @@
     test('.html caption', () {
       var table = new TableElement();
       var node = table.createFragment('<caption><p>Table 1.').nodes.single;
-      expect(node, predicate((x) => x is TableCaptionElement,
-          'is a TableCaptionElement'));
+      expect(
+          node,
+          predicate(
+              (x) => x is TableCaptionElement, 'is a TableCaptionElement'));
       expect(node.tagName, 'CAPTION');
       expect(node.parent, isNull);
       expect(node.innerHtml, '<p>Table 1.</p>');
@@ -137,8 +140,8 @@
       var table = new TableElement();
       var node =
           table.createFragment('<colgroup> <col> <col> <col>').nodes.single;
-      expect(node, predicate((x) => x is TableColElement,
-          'is a TableColElement'));
+      expect(
+          node, predicate((x) => x is TableColElement, 'is a TableColElement'));
       expect(node.tagName, 'COLGROUP');
       expect(node.parent, isNull);
       expect(node.innerHtml, ' <col> <col> <col>');
@@ -148,8 +151,10 @@
       var innerHtml = '<tr><td headers="n r1">Sad</td><td>Happy</td></tr>';
       var table = new TableElement();
       var node = table.createFragment('<tbody>$innerHtml').nodes.single;
-      expect(node, predicate((x) => x is TableSectionElement,
-          'is a TableSectionElement'));
+      expect(
+          node,
+          predicate(
+              (x) => x is TableSectionElement, 'is a TableSectionElement'));
       expect(node.tagName, 'TBODY');
       expect(node.parent, isNull);
       expect(node.rows.length, 1);
@@ -161,8 +166,10 @@
       var innerHtml = '<tr><th id="n">Negative</th><th>Positive</th></tr>';
       var table = new TableElement();
       var node = table.createFragment('<thead>$innerHtml').nodes.single;
-      expect(node, predicate((x) => x is TableSectionElement,
-          'is a TableSectionElement'));
+      expect(
+          node,
+          predicate(
+              (x) => x is TableSectionElement, 'is a TableSectionElement'));
       expect(node.tagName, 'THEAD');
       expect(node.parent, isNull);
       expect(node.rows.length, 1);
@@ -174,8 +181,10 @@
       var innerHtml = '<tr><th>percentage</th><td>34.3%</td></tr>';
       var table = new TableElement();
       var node = table.createFragment('<tfoot>$innerHtml').nodes.single;
-      expect(node, predicate((x) => x is TableSectionElement,
-          'is a TableSectionElement'));
+      expect(
+          node,
+          predicate(
+              (x) => x is TableSectionElement, 'is a TableSectionElement'));
       expect(node.tagName, 'TFOOT');
       expect(node.parent, isNull);
       expect(node.rows.length, 1);
@@ -188,8 +197,8 @@
       document.body.append(table);
       var tBody = table.createTBody();
       var node = tBody.createFragment('<tr><td>foo<td>bar').nodes.single;
-      expect(node, predicate((x) => x is TableRowElement,
-          'is a TableRowElement'));
+      expect(
+          node, predicate((x) => x is TableRowElement, 'is a TableRowElement'));
       expect(node.tagName, 'TR');
       expect(node.parent, isNull);
       expect(node.cells.map((c) => c.innerHtml), ['foo', 'bar']);
@@ -201,8 +210,8 @@
       var tBody = table.createTBody();
       var tRow = tBody.addRow();
       var node = tRow.createFragment('<td>foobar').nodes.single;
-      expect(node, predicate((x) => x is TableCellElement,
-          'is a TableCellElement'));
+      expect(node,
+          predicate((x) => x is TableCellElement, 'is a TableCellElement'));
       expect(node.tagName, 'TD');
       expect(node.parent, isNull);
       expect(node.innerHtml, 'foobar');
@@ -214,8 +223,8 @@
       var tBody = table.createTBody();
       var tRow = tBody.addRow();
       var node = tRow.createFragment('<th>foobar').nodes.single;
-      expect(node, predicate((x) => x is TableCellElement,
-          'is a TableCellElement'));
+      expect(node,
+          predicate((x) => x is TableCellElement, 'is a TableCellElement'));
       expect(node.tagName, 'TH');
       expect(node.parent, isNull);
       expect(node.innerHtml, 'foobar');
@@ -234,15 +243,15 @@
 
   group('eventListening', () {
     test('streams', () {
-      final target = new Element.tag('div');
+      final target = new TextAreaElement();
 
-      void testEvent(Stream stream, String type) {
+      void testEvent(Stream stream, String type, [createEvent(String type)]) {
         var firedOnEvent = false;
         stream.listen((e) {
           firedOnEvent = true;
         });
         expect(firedOnEvent, isFalse);
-        var event = new Event(type);
+        var event = createEvent != null ? createEvent(type) : new Event(type);
         target.dispatchEvent(event);
 
         expect(firedOnEvent, isTrue);
@@ -254,38 +263,53 @@
       testEvent(target.onBeforePaste, 'beforepaste');
       testEvent(target.onBlur, 'blur');
       testEvent(target.onChange, 'change');
-      testEvent(target.onContextMenu, 'contextmenu');
+      testEvent(
+          target.onContextMenu, 'contextmenu', (type) => new MouseEvent(type));
+      // We cannot test dispatching a true ClipboardEvent as the DOM does not
+      // provide a way to create a fake ClipboardEvent.
       testEvent(target.onCopy, 'copy');
       testEvent(target.onCut, 'cut');
-      testEvent(target.onDoubleClick, 'dblclick');
-      testEvent(target.onDrag, 'drag');
-      testEvent(target.onDragEnd, 'dragend');
-      testEvent(target.onDragEnter, 'dragenter');
-      testEvent(target.onDragLeave, 'dragleave');
-      testEvent(target.onDragOver, 'dragover');
-      testEvent(target.onDragStart, 'dragstart');
-      testEvent(target.onDrop, 'drop');
+      testEvent(target.onPaste, 'paste');
+
+      testEvent(
+          target.onDoubleClick, 'dblclick', (type) => new MouseEvent(type));
+      testEvent(target.onDrag, 'drag', (type) => new MouseEvent(type));
+      testEvent(target.onDragEnd, 'dragend', (type) => new MouseEvent(type));
+      testEvent(
+          target.onDragEnter, 'dragenter', (type) => new MouseEvent(type));
+      testEvent(
+          target.onDragLeave, 'dragleave', (type) => new MouseEvent(type));
+      testEvent(target.onDragOver, 'dragover', (type) => new MouseEvent(type));
+      testEvent(
+          target.onDragStart, 'dragstart', (type) => new MouseEvent(type));
+      testEvent(target.onDrop, 'drop', (type) => new MouseEvent(type));
       testEvent(target.onError, 'error');
       testEvent(target.onFocus, 'focus');
       testEvent(target.onFullscreenChange, 'webkitfullscreenchange');
       testEvent(target.onInput, 'input');
       testEvent(target.onInvalid, 'invalid');
-      testEvent(target.onKeyDown, 'keydown');
-      testEvent(target.onKeyPress, 'keypress');
-      testEvent(target.onKeyUp, 'keyup');
+      testEvent(target.onKeyDown, 'keydown', (type) => new KeyboardEvent(type));
+      testEvent(
+          target.onKeyPress, 'keypress', (type) => new KeyboardEvent(type));
+      testEvent(target.onKeyUp, 'keyup', (type) => new KeyboardEvent(type));
       testEvent(target.onLoad, 'load');
-      testEvent(target.onMouseDown, 'mousedown');
-      testEvent(target.onMouseMove, 'mousemove');
-      testEvent(target.onMouseOut, 'mouseout');
-      testEvent(target.onMouseOver, 'mouseover');
-      testEvent(target.onMouseUp, 'mouseup');
-      testEvent(target.onPaste, 'paste');
+      testEvent(
+          target.onMouseDown, 'mousedown', (type) => new MouseEvent(type));
+      testEvent(
+          target.onMouseMove, 'mousemove', (type) => new MouseEvent(type));
+      testEvent(target.onMouseOut, 'mouseout', (type) => new MouseEvent(type));
+      testEvent(
+          target.onMouseOver, 'mouseover', (type) => new MouseEvent(type));
+      testEvent(target.onMouseUp, 'mouseup', (type) => new MouseEvent(type));
       testEvent(target.onReset, 'reset');
       testEvent(target.onScroll, 'scroll');
       testEvent(target.onSearch, 'search');
       testEvent(target.onSelect, 'select');
       testEvent(target.onSelectStart, 'selectstart');
       testEvent(target.onSubmit, 'submit');
+      // We would prefer to create new touch events for this test via
+      // new TouchEvent(null, null, null, type)
+      // but that fails on desktop browsers as touch is not enabled.
       testEvent(target.onTouchCancel, 'touchcancel');
       testEvent(target.onTouchEnd, 'touchend');
       testEvent(target.onTouchLeave, 'touchleave');
@@ -319,66 +343,67 @@
   });
 
   group('attributes', () {
-      test('manipulation', () {
-        final element = new Element.html(
-            '''<div class="foo" style="overflow: hidden" data-foo="bar"
+    test('manipulation', () {
+      final element = new Element.html(
+          '''<div class="foo" style="overflow: hidden" data-foo="bar"
                    data-foo2="bar2" dir="rtl">
-               </div>''', treeSanitizer: new NullTreeSanitizer());
-        final attributes = element.attributes;
-        expect(attributes['class'], 'foo');
-        expect(attributes['style'], startsWith('overflow: hidden'));
-        expect(attributes['data-foo'], 'bar');
-        expect(attributes['data-foo2'], 'bar2');
-        expect(attributes.length, 5);
-        expect(element.dataset.length, 2);
-        element.dataset['foo'] = 'baz';
-        expect(element.dataset['foo'], 'baz');
-        expect(attributes['data-foo'], 'baz');
-        attributes['data-foo2'] = 'baz2';
-        expect(attributes['data-foo2'], 'baz2');
-        expect(element.dataset['foo2'], 'baz2');
-        expect(attributes['dir'], 'rtl');
+               </div>''',
+          treeSanitizer: new NullTreeSanitizer());
+      final attributes = element.attributes;
+      expect(attributes['class'], 'foo');
+      expect(attributes['style'], startsWith('overflow: hidden'));
+      expect(attributes['data-foo'], 'bar');
+      expect(attributes['data-foo2'], 'bar2');
+      expect(attributes.length, 5);
+      expect(element.dataset.length, 2);
+      element.dataset['foo'] = 'baz';
+      expect(element.dataset['foo'], 'baz');
+      expect(attributes['data-foo'], 'baz');
+      attributes['data-foo2'] = 'baz2';
+      expect(attributes['data-foo2'], 'baz2');
+      expect(element.dataset['foo2'], 'baz2');
+      expect(attributes['dir'], 'rtl');
 
-        final dataset = element.dataset;
-        dataset.remove('foo2');
-        expect(attributes.length, 4);
-        expect(dataset.length, 1);
-        attributes.remove('style');
-        expect(attributes.length, 3);
-        dataset['foo3'] = 'baz3';
-        expect(dataset.length, 2);
-        expect(attributes.length, 4);
-        attributes['style'] = 'width: 300px;';
-        expect(attributes.length, 5);
-      });
+      final dataset = element.dataset;
+      dataset.remove('foo2');
+      expect(attributes.length, 4);
+      expect(dataset.length, 1);
+      attributes.remove('style');
+      expect(attributes.length, 3);
+      dataset['foo3'] = 'baz3';
+      expect(dataset.length, 2);
+      expect(attributes.length, 4);
+      attributes['style'] = 'width: 300px;';
+      expect(attributes.length, 5);
+    });
 
-      test('namespaces', () {
-        var element = new svg.SvgElement.svg(
-          '''<svg xmlns="http://www.w3.org/2000/svg"
+    test('namespaces', () {
+      var element =
+          new svg.SvgElement.svg('''<svg xmlns="http://www.w3.org/2000/svg"
                   xmlns:xlink="http://www.w3.org/1999/xlink">
             <image xlink:href="foo" data-foo="bar"/>
           </svg>''').children[0];
 
-        var attributes = element.attributes;
-        expect(attributes.length, 1);
-        expect(attributes['data-foo'], 'bar');
+      var attributes = element.attributes;
+      expect(attributes.length, 1);
+      expect(attributes['data-foo'], 'bar');
 
-        var xlinkAttrs =
-            element.getNamespacedAttributes('http://www.w3.org/1999/xlink');
-        expect(xlinkAttrs.length, 1);
-        expect(xlinkAttrs['href'], 'foo');
+      var xlinkAttrs =
+          element.getNamespacedAttributes('http://www.w3.org/1999/xlink');
+      expect(xlinkAttrs.length, 1);
+      expect(xlinkAttrs['href'], 'foo');
 
-        xlinkAttrs.remove('href');
-        expect(xlinkAttrs.length, 0);
+      xlinkAttrs.remove('href');
+      expect(xlinkAttrs.length, 0);
 
-        xlinkAttrs['href'] = 'bar';
-        expect(xlinkAttrs['href'], 'bar');
+      xlinkAttrs['href'] = 'bar';
+      expect(xlinkAttrs['href'], 'bar');
 
-        var randomAttrs = element.getNamespacedAttributes('http://example.com');
-        expect(randomAttrs.length, 0);
-        randomAttrs['href'] = 'bar';
-        expect(randomAttrs.length, 1);
-      });
+      var randomAttrs = element.getNamespacedAttributes('http://example.com');
+      expect(randomAttrs.length, 0);
+      randomAttrs['href'] = 'bar';
+      expect(randomAttrs.length, 1);
+    });
   });
 
   group('children', () {
@@ -421,8 +446,8 @@
     });
 
     test('where', () {
-      var filtered = makeElementWithChildren().children.
-        where((n) => n is ImageElement);
+      var filtered =
+          makeElementWithChildren().children.where((n) => n is ImageElement);
       expect(1, filtered.length);
       expect(filtered.first, isImageElement);
       expect(filtered, isElementIterable);
@@ -764,25 +789,27 @@
     test('matches', () {
       Element clickOne = new Element.a();
       Element selectorOne = new Element.div()
-          ..classes.add('selector')
-          ..children.add(clickOne);
+        ..classes.add('selector')
+        ..children.add(clickOne);
 
       Element clickTwo = new Element.a();
       Element selectorTwo = new Element.div()
-          ..classes.add('selector')
-          ..children.add(clickTwo);
+        ..classes.add('selector')
+        ..children.add(clickTwo);
       document.body.append(selectorOne);
       document.body.append(selectorTwo);
 
-      document.body.onClick.matches('.selector').listen(expectAsync(
-          (Event event) {
+      document.body.onClick
+          .matches('.selector')
+          .listen(expectAsync((Event event) {
         expect(event.currentTarget, document.body);
         expect(event.target, clickOne);
         expect(event.matchingTarget, selectorOne);
       }));
 
-      selectorOne.onClick.matches('.selector').listen(expectAsync(
-          (Event event) {
+      selectorOne.onClick
+          .matches('.selector')
+          .listen(expectAsync((Event event) {
         expect(event.currentTarget, selectorOne);
         expect(event.target, clickOne);
         expect(event.matchingTarget, selectorOne);
@@ -896,12 +923,8 @@
 
       var event = new Event('custom_event', canBubble: true);
       c.dispatchEvent(event);
-      expect(eventOrder, [
-        'a capture',
-        'b capture',
-        'b no-capture',
-        'a no-capture'
-      ]);
+      expect(eventOrder,
+          ['a capture', 'b capture', 'b no-capture', 'a no-capture']);
     });
   });
 
@@ -917,7 +940,7 @@
 
     ElementList<Element> makeElementList() =>
         (new Element.html("<div>Foo<br/><!--baz--><br/><br/></div>"))
-        .queryAll('br');
+            .queryAll('br');
 
     test('hashCode', () {
       var nodes = makeElementList();
@@ -934,7 +957,7 @@
       var a = [makeElementList(), makeElementList(), null];
       for (int i = 0; i < a.length; i++) {
         for (int j = 0; j < a.length; j++) {
-          expect(i == j,  a[i] == a[j]);
+          expect(i == j, a[i] == a[j]);
         }
       }
     });
@@ -973,6 +996,5 @@
       expect(range[0], isBRElement);
       expect(range[1], isBRElement);
     });
-
   });
 }
diff --git a/tests/html/events_test.dart b/tests/html/events_test.dart
index b2c448a..9d09bf6 100644
--- a/tests/html/events_test.dart
+++ b/tests/html/events_test.dart
@@ -51,7 +51,7 @@
     element.dispatchEvent(event);
     expect(invocationCounter, isZero);
 
-    var provider = new EventStreamProvider<CustomEvent>('test');
+    var provider = new EventStreamProvider<Event>('test');
 
     var sub = provider.forTarget(element).listen(handler);
     invocationCounter = 0;
diff --git a/tests/html/html.status b/tests/html/html.status
index 4beb9f4..2b538fc 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -60,9 +60,7 @@
 fileapi_test/getFile: Pass, Fail # Issue 20488
 async_test: RuntimeError, OK  # Uses Isolate.spawn.
 isolates_test: RuntimeError, OK  # Uses Isolate.spawn.
-
-[ $compiler == none && ($runtime == drt || $runtime == dartium ) && $checked]
-cross_domain_iframe_test: RuntimeError # Issue 26134
+custom/created_callback_test: Fail # Support for created constructor. Issue 14835
 
 [ $compiler == none && ($runtime == drt || $runtime == dartium ) && $mode == debug ]
 websocket_test/websocket: Skip # Issue 17666
diff --git a/tests/language/generic_functions_test.dart b/tests/language/generic_functions_test.dart
index 54ab173..814163a 100644
--- a/tests/language/generic_functions_test.dart
+++ b/tests/language/generic_functions_test.dart
@@ -2,11 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import "package:expect/expect.dart";
+/// Dart test verifying that the parser can handle type parameterization of
+/// function declarations and function invocations. Variant of code from
+/// DEP #22, adjusted to use generic top level functions.
 
-// Dart test verifying that the parser can handle type parameterization of
-// function declarations and function invocations. Variant of code from
-// DEP #22, adjusted to use generic top level functions.
+library generic_functions_test;
+
+import "package:expect/expect.dart";
 
 class BinaryTreeNode<K extends Comparable<K>, V> {
   final K _key;
diff --git a/tests/language/generic_local_functions_test.dart b/tests/language/generic_local_functions_test.dart
new file mode 100644
index 0000000..6a350d4
--- /dev/null
+++ b/tests/language/generic_local_functions_test.dart
@@ -0,0 +1,22 @@
+// 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.
+
+/// Dart test verifying that the parser can handle type parameterization of
+/// local function declarations, and declarations of function parameters.
+
+library generic_functions_test;
+
+import "package:expect/expect.dart";
+
+// Declare a generic function parameter.
+String f(int g<X, Y>(Map<X, Y> arg)) => null;
+
+main() {
+  // Declare a generic local function
+  int h<X extends Y, Y>(Map<X, Y> arg) => null;
+  // Pass a generic local function as an argument.
+  f(h);
+  // Pass a function expression as an argument.
+  f(<X, Y super X>(Map<X, Y> arg) => 42);
+}
diff --git a/tests/language/generic_local_functions_test.options b/tests/language/generic_local_functions_test.options
new file mode 100644
index 0000000..86e2aac
--- /dev/null
+++ b/tests/language/generic_local_functions_test.options
@@ -0,0 +1,3 @@
+analyzer:
+  language:
+    enableGenericMethods: true
diff --git a/tests/language/generic_methods_test.dart b/tests/language/generic_methods_test.dart
index 3fd6d24..9151fc3 100644
--- a/tests/language/generic_methods_test.dart
+++ b/tests/language/generic_methods_test.dart
@@ -2,11 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import "package:expect/expect.dart";
+/// Dart test verifying that the parser can handle type parameterization of
+/// method declarations and method invocations. Slightly adjusted version of
+/// code from DEP #22.
 
-// Dart test verifying that the parser can handle type parameterization of
-// method declarations and method invocations. Slightly adjusted version of
-// code from DEP #22.
+library generic_methods_test;
+
+import "package:expect/expect.dart";
 
 class BinaryTreeNode<K extends Comparable<K>, V> {
   final K _key;
diff --git a/tests/language/generic_sends_test.dart b/tests/language/generic_sends_test.dart
index 2e98215d..57befee 100644
--- a/tests/language/generic_sends_test.dart
+++ b/tests/language/generic_sends_test.dart
@@ -2,9 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// Dart test verifying that the parser can handle certain cases where
-// grammar ambiguity is resolved in favor of generic sends, not
-// relational expressions.
+/// Dart test verifying that the parser can handle certain cases where
+/// grammar ambiguity is resolved in favor of generic sends, not
+/// relational expressions.
+
+library generic_sends_test;
 
 f(arg1, [arg2]) => null;
 g<X, Y>(arg) => null;
diff --git a/tests/language/language.status b/tests/language/language.status
index 044e7a5..c3a14b9 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -47,6 +47,7 @@
 # Experimental feature: Syntactic support for generic methods.
 generic_methods_test: CompiletimeError # Issue 25869
 generic_functions_test: CompiletimeError # Issue 25869
+generic_local_functions_test: CompiletimeError # Issue 25869
 generic_sends_test: CompiletimeError # Issue 25869
 
 [ ($compiler == none || $compiler == precompiler || $compiler == dart2app) && ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_product) ]
@@ -91,7 +92,9 @@
 # Experimental feature: Syntactic support for generic methods.
 generic_methods_test: RuntimeError # Issue 25869
 generic_functions_test: RuntimeError # Issue 25869
+generic_local_functions_test: RuntimeError # Issue 25869
 generic_sends_test: RuntimeError # Issue 25869
+config_import_test: Skip  # Issue 26250
 
 [ $compiler == none && $runtime == dartium && $system == linux && $arch != x64 ]
 issue_22780_test/01: Pass, Timeout # Issue 24473
@@ -208,3 +211,11 @@
 [ $noopt || $compiler == precompiler || $mode == product ]
 # The following tests are supposed to fail.
 library_env_test/has_mirror_support: RuntimeError, OK
+
+[ $arch == simdbc || $arch == simdbc64 ]
+# TODO(vegorov) StopInstr is unimplemented.
+vm/debug_break_enabled_vm_test/none: Skip
+
+# TODO(vegorov) Encoding limitation: StoreField bytecode only supports 256
+# fields in an object.
+large_class_declaration_test: Skip
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status
index c8c95f3..a588be3 100644
--- a/tests/language/language_analyzer2.status
+++ b/tests/language/language_analyzer2.status
@@ -520,5 +520,6 @@
 
 # Experimental feature: Syntactic support for generic methods.
 generic_functions_test: CompileTimeError # Issue 25868
+generic_local_functions_test: CompileTimeError # Issue 25868
 generic_methods_test: CompileTimeError # Issue 25868
 generic_sends_test: CompileTimeError # Issue 25868
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index f10bd63..4a95853 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -37,6 +37,7 @@
 
 # Experimental feature: Syntactic support for generic methods.
 generic_functions_test: CompileTimeError # Issue 25835
+generic_local_functions_test: CompileTimeError # Issue 25835
 generic_methods_test: CompileTimeError # Issue 25835
 generic_sends_test: CompileTimeError # Issue 25835
 
diff --git a/tests/language/regress_26230_test.dart b/tests/language/regress_26230_test.dart
new file mode 100644
index 0000000..c6de7d7
--- /dev/null
+++ b/tests/language/regress_26230_test.dart
@@ -0,0 +1,27 @@
+// 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.
+
+class _RenderTabBar extends RenderBox with
+    ContainerRenderObjectMixin<RenderBox, _TabBarParentData>,
+    RenderBoxContainerDefaultsMixin<RenderBox, _TabBarParentData> { }
+class RenderObject { }
+class RenderSector extends RenderObject { }
+class RenderBox extends RenderObject { }
+class ParentData { }
+class BoxParentData extends ParentData { }
+class SectorParentData extends ParentData { }
+class ContainerParentDataMixin<ChildType extends RenderObject> { }
+class ContainerRenderObjectMixin<ChildType extends RenderObject, ParentDataType extends ContainerParentDataMixin<ChildType>> { }
+class SectorChildListParentData extends SectorParentData with ContainerParentDataMixin<RenderSector> { }
+class RenderDecoratedSector extends RenderSector { }
+class RenderSectorWithChildren extends RenderDecoratedSector with ContainerRenderObjectMixin<RenderSector, SectorChildListParentData> { }
+class ContainerBoxParentDataMixin<ChildType extends RenderObject> extends BoxParentData with ContainerParentDataMixin<ChildType> { }
+class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, ParentDataType extends ContainerBoxParentDataMixin<ChildType>> implements ContainerRenderObjectMixin<ChildType, ParentDataType> { }
+class FlexParentData extends ContainerBoxParentDataMixin<RenderBox> { }
+class _TabBarParentData extends ContainerBoxParentDataMixin<RenderBox> { }
+
+main() {
+  new _RenderTabBar();
+}
+
diff --git a/tests/lib/analyzer/analyze_library.status b/tests/lib/analyzer/analyze_library.status
index 3288d18..b86abdc 100644
--- a/tests/lib/analyzer/analyze_library.status
+++ b/tests/lib/analyzer/analyze_library.status
@@ -17,12 +17,12 @@
 lib/web_sql/dart2js/web_sql_dart2js: CompileTimeError # Issue 16522
 
 [ $compiler == dart2analyzer ]
-lib/web_gl/dartium/web_gl_dartium: CompileTimeError # Issue 21647
-lib/web_sql/dartium/web_sql_dartium: CompileTimeError # Issue 21647
-lib/html/dartium/html_dartium: CompileTimeError # Issue 21647
-lib/html/html_common/html_common: CompileTimeError # Issue 21647
-lib/indexed_db/dartium/indexed_db_dartium: CompileTimeError # Issue 21647
-lib/web_audio/dartium/web_audio_dartium: CompileTimeError # Issue 21647
-lib/svg/dartium/svg_dartium: CompileTimeError # Issue 21647
-lib/_blink/dartium/_blink_dartium: CompileTimeError # Undefined Creates and Returns classes
-lib/js/dartium/js_dartium: CompileTimeError # Undefined Creates and Returns classes
\ No newline at end of file
+lib/web_gl/dartium/web_gl_dartium: StaticWarning # Issue 21647
+lib/web_sql/dartium/web_sql_dartium: StaticWarning # Issue 21647
+lib/html/dartium/html_dartium: StaticWarning # Issue 21647
+lib/html/html_common/html_common: StaticWarning # Issue 21647
+lib/indexed_db/dartium/indexed_db_dartium: StaticWarning # Issue 21647
+lib/web_audio/dartium/web_audio_dartium: StaticWarning # Issue 21647
+lib/svg/dartium/svg_dartium: StaticWarning # Issue 21647
+lib/_blink/dartium/_blink_dartium: StaticWarning # Undefined Creates and Returns classes
+lib/js/dartium/js_dartium: StaticWarning # Undefined Creates and Returns classes
\ No newline at end of file
diff --git a/tests/lib/convert/close_test.dart b/tests/lib/convert/close_test.dart
new file mode 100644
index 0000000..541c1fa
--- /dev/null
+++ b/tests/lib/convert/close_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import "dart:convert";
+
+class MySink implements Sink<List<int>> {
+  List<int> accumulated = <int>[];
+  bool isClosed = false;
+
+  add(List<int> list) {
+    accumulated.addAll(list);
+    return list.length;
+  }
+
+  close() {
+    isClosed = true;
+    // Returning a value here triggered a bug, where the caller was trying to
+    // pass the value through its 'void' return type.
+    // Example: void close() => _sink.close();
+    return "done";
+  }
+}
+
+main() {
+  var mySink = new MySink();
+  var byteSink = new ByteConversionSink.from(mySink);
+  byteSink.add([1, 2, 3]);
+  byteSink.close();
+  Expect.listEquals([1, 2, 3], mySink.accumulated);
+  Expect.isTrue(mySink.isClosed);
+}
diff --git a/tests/lib/convert/streamed_conversion_json_utf8_decode_test.dart b/tests/lib/convert/streamed_conversion_json_utf8_decode_test.dart
index 783e079..ab014ee 100644
--- a/tests/lib/convert/streamed_conversion_json_utf8_decode_test.dart
+++ b/tests/lib/convert/streamed_conversion_json_utf8_decode_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 // Test write barrier verification mode.
-// VMOptions=--verified_mem --verify_before_gc --verify_after_gc --old_gen_growth_rate=1
+// VMOptions=--verify_before_gc --verify_after_gc --old_gen_growth_rate=1 --no-background-compilation
 // VMOptions=
 
 import "package:expect/expect.dart";
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 8b9fb54..c0a201e 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -102,6 +102,7 @@
 mirrors/variable_is_const_test/none: RuntimeError # Issue 14671
 mirrors/raw_type_test/01: RuntimeError # Issue 6490
 mirrors/mirrors_reader_test: Slow, RuntimeError # Issue 16589
+mirrors/regress_26187_test: RuntimeError # Issue 6490
 
 [ $runtime == safari || $runtime == safarimobilesim ]
 typed_data/int32x4_test: Fail, Pass # Safari has an optimization bug (nightlies are already fine).
@@ -361,3 +362,8 @@
 [ $noopt || $compiler == precompiler ]
 convert/chunked_conversion_utf88_test: Pass, Timeout
 convert/utf85_test: Pass, Timeout
+
+[ $arch == simdbc || $arch == simdbc64 ]
+# TODO(vegorov) LoadField bytecode supports only up to 256 fields. Need a long
+# version.
+mirrors/accessor_cache_overflow_test: Skip
diff --git a/tests/lib/mirrors/reflected_type_function_type_test.dart b/tests/lib/mirrors/reflected_type_function_type_test.dart
index 4b7cf03..bf57c47 100644
--- a/tests/lib/mirrors/reflected_type_function_type_test.dart
+++ b/tests/lib/mirrors/reflected_type_function_type_test.dart
@@ -18,5 +18,5 @@
       (reflectType(Predicate) as TypedefMirror).referent;
 
   expectReflectedType(numToBool1, somePredicate.runtimeType);
-  expectReflectedType(numToBool2, somePredicate.runtimeType);
+  expectReflectedType(numToBool2, Predicate);
 }
diff --git a/tests/lib/mirrors/regress_26187_test.dart b/tests/lib/mirrors/regress_26187_test.dart
new file mode 100644
index 0000000..1d99362
--- /dev/null
+++ b/tests/lib/mirrors/regress_26187_test.dart
@@ -0,0 +1,25 @@
+// 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:mirrors';
+import 'package:expect/expect.dart';
+
+class A {
+  const A();
+}
+
+class B {
+  const B();
+}
+
+typedef void f(@A() int, String);
+
+typedef void g(@B() int, String);
+
+main() {
+  ParameterMirror fParamMirror = (reflectType(f) as TypedefMirror).referent.parameters[0];
+  ParameterMirror gParamMirror = (reflectType(g) as TypedefMirror).referent.parameters[0];
+  Expect.equals('.A', MirrorSystem.getName(fParamMirror.metadata[0].type.qualifiedName));
+  Expect.equals('.B', MirrorSystem.getName(gParamMirror.metadata[0].type.qualifiedName));
+}
diff --git a/tests/standalone/io/addlatexhash_test.dart b/tests/standalone/io/addlatexhash_test.dart
index 1f189ab..582b75a 100755
--- a/tests/standalone/io/addlatexhash_test.dart
+++ b/tests/standalone/io/addlatexhash_test.dart
@@ -80,12 +80,16 @@
   if (dartExecutable == "") throw "dart executable not available";
 
   // actions to take
-  runAddHash() =>
-      Process.runSync(dartExecutable,
-                      [path.join(dartRootPath, "tools", "addlatexhash.dart"),
-                       tmpPar8timesPath,
-                       hashPath,
-                       listPath]);
+  runAddHash() {
+    var args = [
+      '--package-root=${Platform.packageRoot}',
+      path.join(dartRootPath, "tools", "addlatexhash.dart"),
+      tmpPar8timesPath,
+      hashPath,
+      listPath
+    ];
+    return Process.runSync(dartExecutable, args);
+  }
 
   // perform test
   new File(par8timesPath).copySync(tmpPar8timesPath);
@@ -149,12 +153,16 @@
   runLatex(fileName,workingDirectory) =>
       Process.runSync("latex", [fileName], workingDirectory: workingDirectory);
 
-  runAddHash() =>
-      Process.runSync(dartExecutable,
-                      [path.join(dartRootPath, "tools", "addlatexhash.dart"),
-                       tmpSpecPath,
-                       hashPath,
-                       listPath]);
+  runAddHash() {
+    var args = [
+      '--package-root=${Platform.packageRoot}',
+      path.join(dartRootPath, "tools", "addlatexhash.dart"),
+      tmpSpecPath,
+      hashPath,
+      listPath
+    ];
+    return Process.runSync(dartExecutable, args);
+  }
 
   runDvi2tty(dviFile) =>
       Process.runSync("dvi2tty", [dviFile], workingDirectory: tmpDirPath);
diff --git a/tests/standalone/io/file_lock_test.dart b/tests/standalone/io/file_lock_test.dart
index d84ca2b..ca590c1 100644
--- a/tests/standalone/io/file_lock_test.dart
+++ b/tests/standalone/io/file_lock_test.dart
@@ -36,11 +36,11 @@
 }
 
 checkLocked(String path,
-            [int start, int end, FileLock mode = FileLock.EXCLUSIVE]) =>
+    [int start = 0, int end = -1, FileLock mode = FileLock.EXCLUSIVE]) =>
     check(path, start, end, mode, locked: true);
 
 checkNotLocked(String path,
-               [int start, int end, FileLock mode = FileLock.EXCLUSIVE]) =>
+    [int start = 0, int end = -1, FileLock mode = FileLock.EXCLUSIVE]) =>
     check(path, start, end, mode, locked: false);
 
 void testLockWholeFile() {
diff --git a/tests/standalone/io/http_auth_digest_test.dart b/tests/standalone/io/http_auth_digest_test.dart
index 5512cd0..6a902b0 100644
--- a/tests/standalone/io/http_auth_digest_test.dart
+++ b/tests/standalone/io/http_auth_digest_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import "package:convert/convert.dart";
 import "package:crypto/crypto.dart";
 import "package:expect/expect.dart";
 import 'dart:async';
@@ -31,9 +32,8 @@
     String realm = "test";
     String username = "dart";
     String password = "password";
-    var hasher = new MD5();
-    hasher.add("${username}:${realm}:${password}".codeUnits);
-    ha1 = CryptoUtils.bytesToHex(hasher.close());
+    var hasher = md5.convert("${username}:${realm}:${password}".codeUnits);
+    ha1 = hex.encode(hasher.bytes);
 
     var nonce = "12345678";  // No need for random nonce in test.
 
@@ -96,18 +96,17 @@
             }
             Expect.isNotNull(header.parameters["response"]);
 
-            var hasher = new MD5();
-            hasher.add("${request.method}:${uri}".codeUnits);
-            var ha2 = CryptoUtils.bytesToHex(hasher.close());
+            var hasher = md5.convert("${request.method}:${uri}".codeUnits);
+            var ha2 = hex.encode(hasher.bytes);
 
             var x;
-            hasher = new MD5();
+            Digest digest;
             if (qop == null || qop == "" || qop == "none") {
-              hasher.add("$ha1:${nonce}:$ha2".codeUnits);
+              digest = md5.convert("$ha1:${nonce}:$ha2".codeUnits);
             } else {
-              hasher.add("$ha1:${nonce}:${nc}:${cnonce}:${qop}:$ha2".codeUnits);
+              digest = md5.convert("$ha1:${nonce}:${nc}:${cnonce}:${qop}:$ha2".codeUnits);
             }
-            Expect.equals(CryptoUtils.bytesToHex(hasher.close()),
+            Expect.equals(hex.encode(digest.bytes),
                           header.parameters["response"]);
 
             successCount++;
diff --git a/tests/standalone/io/http_auth_test.dart b/tests/standalone/io/http_auth_test.dart
index d259bdf..8433067 100644
--- a/tests/standalone/io/http_auth_test.dart
+++ b/tests/standalone/io/http_auth_test.dart
@@ -42,7 +42,7 @@
           List<String> tokens = authorization.split(" ");
           Expect.equals("Basic", tokens[0]);
           String auth =
-              CryptoUtils.bytesToBase64(UTF8.encode("$username:$password"));
+              BASE64.encode(UTF8.encode("$username:$password"));
           if (passwordChanged && auth != tokens[1]) {
             response.statusCode = HttpStatus.UNAUTHORIZED;
             response.headers.set(HttpHeaders.WWW_AUTHENTICATE,
diff --git a/tests/standalone/io/http_proxy_advanced_test.dart b/tests/standalone/io/http_proxy_advanced_test.dart
index 1d2e585..7a349d1 100644
--- a/tests/standalone/io/http_proxy_advanced_test.dart
+++ b/tests/standalone/io/http_proxy_advanced_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import "package:convert/convert.dart";
 import "package:crypto/crypto.dart";
 import "package:expect/expect.dart";
 import "package:path/path.dart";
@@ -115,9 +116,8 @@
     authScheme = "Digest";
 
     // Calculate ha1.
-    var hasher = new MD5();
-    hasher.add("${username}:${realm}:${password}".codeUnits);
-    ha1 = CryptoUtils.bytesToHex(hasher.close());
+    var digest = md5.convert("${username}:${realm}:${password}".codeUnits);
+    ha1 = hex.encode(digest.bytes);
   }
 
   basicAuthenticationRequired(request) {
@@ -173,7 +173,7 @@
               List<String> tokens = authorization.split(" ");
               Expect.equals("Basic", tokens[0]);
               String auth =
-                  CryptoUtils.bytesToBase64(UTF8.encode("$username:$password"));
+                  BASE64.encode(UTF8.encode("$username:$password"));
               if (auth != tokens[1]) {
                 basicAuthenticationRequired(request);
                 return;
@@ -206,19 +206,17 @@
               }
               Expect.isNotNull(header.parameters["response"]);
 
-              var hasher = new MD5();
-              hasher.add("${request.method}:${uri}".codeUnits);
-              var ha2 = CryptoUtils.bytesToHex(hasher.close());
+              var digest = md5.convert("${request.method}:${uri}".codeUnits);
+              var ha2 = hex.encode(digest.bytes);
 
               var x;
-              hasher = new MD5();
               if (qop == null || qop == "" || qop == "none") {
-                hasher.add("$ha1:${nonce}:$ha2".codeUnits);
+                digest = md5.convert("$ha1:${nonce}:$ha2".codeUnits);
               } else {
-                hasher.add(
+                digest = md5.convert(
                     "$ha1:${nonce}:${nc}:${cnonce}:${qop}:$ha2".codeUnits);
               }
-              Expect.equals(CryptoUtils.bytesToHex(hasher.close()),
+              Expect.equals(hex.encode(digest.bytes),
                             header.parameters["response"]);
 
               // Add a bogus Proxy-Authentication-Info for testing.
diff --git a/tests/standalone/io/http_proxy_test.dart b/tests/standalone/io/http_proxy_test.dart
index e2505f3..70a7f8c 100644
--- a/tests/standalone/io/http_proxy_test.dart
+++ b/tests/standalone/io/http_proxy_test.dart
@@ -2,9 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import "package:convert/convert.dart";
 import "package:crypto/crypto.dart";
 import "package:expect/expect.dart";
-import "package:path/path.dart";
 import "dart:async";
 import "dart:io";
 import 'dart:convert';
@@ -109,17 +109,6 @@
     authScheme = "Basic";
   }
 
-  void useDigestAuthentication(String username, String password) {
-    this.username = username;
-    this.password = password;
-    authScheme = "Digest";
-
-    // Calculate ha1.
-    var hasher = new MD5();
-    hasher.add("${username}:${realm}:${password}".codeUnits);
-    ha1 = CryptoUtils.bytesToHex(hasher.close());
-  }
-
   basicAuthenticationRequired(request) {
     request.fold(null, (x, y) {}).then((_) {
       var response = request.response;
@@ -173,7 +162,7 @@
               List<String> tokens = authorization.split(" ");
               Expect.equals("Basic", tokens[0]);
               String auth =
-                  CryptoUtils.bytesToBase64(UTF8.encode("$username:$password"));
+                  BASE64.encode(UTF8.encode("$username:$password"));
               if (auth != tokens[1]) {
                 basicAuthenticationRequired(request);
                 return;
@@ -206,20 +195,17 @@
               }
               Expect.isNotNull(header.parameters["response"]);
 
-              var hasher = new MD5();
-              hasher.add("${request.method}:${uri}".codeUnits);
-              var ha2 = CryptoUtils.bytesToHex(hasher.close());
+              var digest = md5.convert("${request.method}:${uri}".codeUnits);
+              var ha2 = hex.encode(digest.bytes);
 
-              var x;
-              hasher = new MD5();
               if (qop == null || qop == "" || qop == "none") {
-                hasher.add("$ha1:${nonce}:$ha2".codeUnits);
+                digest = md5.convert("$ha1:${nonce}:$ha2".codeUnits);
               } else {
-                hasher.add(
+                digest = md5.convert(
                     "$ha1:${nonce}:${nc}:${cnonce}:${qop}:$ha2".codeUnits);
               }
-              Expect.equals(CryptoUtils.bytesToHex(hasher.close()),
-                            header.parameters["response"]);
+              Expect.equals(hex.encode(digest.bytes),
+                  header.parameters["response"]);
 
               // Add a bogus Proxy-Authentication-Info for testing.
               var info = 'rspauth="77180d1ab3d6c9de084766977790f482", '
diff --git a/tests/standalone/io/named_pipe_script_test.dart b/tests/standalone/io/named_pipe_script_test.dart
new file mode 100644
index 0000000..83df737
--- /dev/null
+++ b/tests/standalone/io/named_pipe_script_test.dart
@@ -0,0 +1,32 @@
+// 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.
+// Testing file input stream, VM-only, standalone test.
+
+import "dart:convert";
+import "dart:io";
+
+import "package:expect/expect.dart";
+
+main() {
+  // Reading a script from a named pipe is only supported on Linux and MacOS.
+  if (!Platform.isLinux && !Platform.isMacOS) {
+    return;
+  }
+
+  final String script = 'int main() {print("Hello, World!");}';
+  final String stdinPipePath = '/dev/fd/0';
+  StringBuffer output = new StringBuffer();
+  Process.start(Platform.executable, [stdinPipePath]).then((Process process) {
+    process.stdout.transform(UTF8.decoder).listen(output.write);
+    process.stderr.transform(UTF8.decoder).listen((data) {
+      Expect.fail(data);
+    });
+    process.stdin.writeln(script);
+    process.stdin.close();
+    process.exitCode.then((int status) {
+      Expect.equals(0, status);
+      Expect.equals("Hello, World!\n", output.toString());
+    });
+  });
+}
diff --git a/tests/standalone/io/network_interface_test.dart b/tests/standalone/io/network_interface_test.dart
index 2d49ce0..71f8312 100644
--- a/tests/standalone/io/network_interface_test.dart
+++ b/tests/standalone/io/network_interface_test.dart
@@ -47,6 +47,9 @@
 
 
 void main() {
+  if (!NetworkInterface.listSupported) {
+    return;
+  }
   testListLoopback();
   testListLinkLocal();
   testListIndex();
diff --git a/tests/standalone/io/test_extension_test.dart b/tests/standalone/io/test_extension_test.dart
index 0f03233..40d768e 100644
--- a/tests/standalone/io/test_extension_test.dart
+++ b/tests/standalone/io/test_extension_test.dart
@@ -12,6 +12,7 @@
 
 Future copyFileToDirectory(String file, String directory) {
   switch (Platform.operatingSystem) {
+    case 'android':
     case 'linux':
     case 'macos':
       return Process.run('cp', [file, directory]);
@@ -22,30 +23,67 @@
   }
 }
 
-String getExtensionPath(String buildDirectory) {
+// Returns a list containing the source file name in the first element and the
+// target file name in the second element.
+List<String> getExtensionNames(String arch) {
   switch (Platform.operatingSystem) {
+    case 'android':
     case 'linux':
-      return join(buildDirectory, 'lib.target', 'libtest_extension.so');
+      return ['libtest_extension.so', 'libtest_extension$arch.so'];
     case 'macos':
-      return join(buildDirectory, 'libtest_extension.dylib');
+      return ['libtest_extension.dylib', 'libtest_extension$arch.dylib'];
     case 'windows':
-      return join(buildDirectory, 'test_extension.dll');
+      return ['test_extension.dll','test_extension$arch.dll'];
     default:
       Expect.fail('Unknown operating system ${Platform.operatingSystem}');
   }
 }
 
-void main() {
+String getExtensionPath(String buildDirectory, String filename) {
+  switch (Platform.operatingSystem) {
+    case 'android':
+    case 'linux':
+      return join(buildDirectory, 'lib.target', filename);
+    case 'macos':
+    case 'windows':
+      return join(buildDirectory, filename);
+    default:
+      Expect.fail('Unknown operating system ${Platform.operatingSystem}');
+  }
+}
+
+String getArchFromBuildDir(String buildDirectory) {
+  if (buildDirectory.endsWith('SIMARM')) return '';
+  if (buildDirectory.endsWith('SIMARM64')) return '';
+  if (buildDirectory.endsWith('SIMDBC')) return '';
+  if (buildDirectory.endsWith('SIMMIPS')) return '';
+  if (buildDirectory.endsWith('ARM')) return '-arm';
+  if (buildDirectory.endsWith('ARM64')) return '-arm64';
+  if (buildDirectory.endsWith('IA32')) return '-ia32';
+  if (buildDirectory.endsWith('MIPS')) return '-mips';
+  if (buildDirectory.endsWith('X64')) return '-x64';
+  return 'unknown';
+}
+
+Future testExtension(bool withArchSuffix) {
   String scriptDirectory = dirname(Platform.script.toFilePath());
   String buildDirectory = dirname(Platform.executable);
   Directory tempDirectory =
       Directory.systemTemp.createTempSync('dart_test_extension');
   String testDirectory = tempDirectory.path;
 
+  List<String> fileNames;
+  if (withArchSuffix) {
+    String arch = getArchFromBuildDir(buildDirectory);
+    fileNames = getExtensionNames(arch);
+  } else {
+    fileNames = getExtensionNames('');
+  }
+
   // Copy test_extension shared library, test_extension.dart and
   // test_extension_tester.dart to the temporary test directory.
-  copyFileToDirectory(getExtensionPath(buildDirectory),
-                      testDirectory).then((_) {
+  return copyFileToDirectory(getExtensionPath(buildDirectory, fileNames[0]),
+                      join(testDirectory, fileNames[1])).then((_) {
     var extensionDartFile = join(scriptDirectory, 'test_extension.dart');
     return copyFileToDirectory(extensionDartFile, testDirectory);
   }).then((_) {
@@ -69,3 +107,16 @@
     tempDirectory.deleteSync(recursive: true);
   });
 }
+
+Future testWithArchSuffix() {
+  return testExtension(true);
+}
+
+Future testWithoutArchSuffix() {
+  return testExtension(false);
+}
+
+main() async {
+  await testWithArchSuffix();
+  await testWithoutArchSuffix();
+}
diff --git a/tests/standalone/io/web_socket_compression_test.dart b/tests/standalone/io/web_socket_compression_test.dart
index e25bc1b..99f341e 100644
--- a/tests/standalone/io/web_socket_compression_test.dart
+++ b/tests/standalone/io/web_socket_compression_test.dart
@@ -57,7 +57,7 @@
     for (int i = 0; i < 16; i++) {
       nonceData[i] = random.nextInt(256);
     }
-    String nonce = CryptoUtils.bytesToBase64(nonceData);
+    String nonce = BASE64.encode(nonceData);
 
     uri = new Uri(
         scheme: uri.scheme == "wss" ? "https" : "http",
@@ -71,7 +71,7 @@
       if (uri.userInfo != null && !uri.userInfo.isEmpty) {
         // If the URL contains user information use that for basic
         // authorization.
-        String auth = CryptoUtils.bytesToBase64(UTF8.encode(uri.userInfo));
+        String auth = BASE64.encode(UTF8.encode(uri.userInfo));
         request.headers.set(HttpHeaders.AUTHORIZATION, "Basic $auth");
       }
       // Setup the initial handshake.
@@ -175,8 +175,8 @@
         Expect.equals('websocket', request.headers.value(HttpHeaders.UPGRADE));
 
         var key = request.headers.value('Sec-WebSocket-Key');
-        var sha1 = new SHA1()..add("$key$WEB_SOCKET_GUID".codeUnits);
-        var accept = CryptoUtils.bytesToBase64(sha1.close());
+        var digest = sha1.convert("$key$WEB_SOCKET_GUID".codeUnits);
+        var accept = BASE64.encode(digest.bytes);
         request.response
             ..statusCode = HttpStatus.SWITCHING_PROTOCOLS
             ..headers.add(HttpHeaders.CONNECTION, "Upgrade")
diff --git a/tests/standalone/io/web_socket_test.dart b/tests/standalone/io/web_socket_test.dart
index f7ff673..3977e84 100644
--- a/tests/standalone/io/web_socket_test.dart
+++ b/tests/standalone/io/web_socket_test.dart
@@ -13,6 +13,7 @@
 import "dart:typed_data";
 
 import "package:async_helper/async_helper.dart";
+import "package:convert/convert.dart";
 import "package:crypto/crypto.dart";
 import "package:expect/expect.dart";
 import "package:path/path.dart";
@@ -467,8 +468,8 @@
         Expect.equals('websocket', request.headers.value(HttpHeaders.UPGRADE));
 
         var key = request.headers.value('Sec-WebSocket-Key');
-        var sha1 = new SHA1()..add("$key$WEB_SOCKET_GUID".codeUnits);
-        var accept = CryptoUtils.bytesToBase64(sha1.close());
+        var digest = sha1.convert("$key$WEB_SOCKET_GUID".codeUnits);
+        var accept = BASE64.encode(digest.bytes);
         request.response
             ..statusCode = HttpStatus.SWITCHING_PROTOCOLS
             ..headers.add(HttpHeaders.CONNECTION, "Upgrade")
@@ -535,7 +536,7 @@
       server.listen((request) {
         Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request));
         String auth =
-              CryptoUtils.bytesToBase64(UTF8.encode(userInfo));
+              BASE64.encode(UTF8.encode(userInfo));
         Expect.equals('Basic $auth', request.headers['Authorization'][0]);
         Expect.equals(1, request.headers['Authorization'].length);
         WebSocketTransformer.upgrade(request).then((webSocket) {
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 4103c33..46f4331 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -14,7 +14,7 @@
 package/scenarios/invalid/invalid_package_name_test: RuntimeError, CompileTimeError # Errors intentionally
 package/scenarios/invalid/same_package_twice_test.dart: RuntimeError, CompileTimeError # Errors intentionally
 full_coverage_test: Pass, Slow, Timeout
-
+verified_mem_test: Pass, Slow, Timeout # Does verify before and after GC.
 
 issue14236_test: Pass # Do not remove this line. It serves as a marker for Issue 14516 comment #4.
 
@@ -255,6 +255,7 @@
 io/code_collection_test: Skip # Platform.executable
 io/raw_socket_cross_process_test: Skip # Platform.executable
 io/test_extension_test: Skip # Platform.executable
+io/named_pipe_script_test: Skip # Platform.executable
 io/regress_7679_test: Skip # Platform.executable
 io/process_*: Skip # Most use Platform.executable
 assert_test: SkipByDesign # Requires checked mode.
@@ -284,3 +285,13 @@
 package/scenarios/empty_packages_file/empty_packages_file_noimports_test: Skip
 package/scenarios/packages_option_only/packages_option_only_noimports_test: Skip
 package/scenarios/packages_option_only/packages_option_only_test: Skip
+
+[ $arch == simdbc || $arch == simdbc64 ]
+# TODO(vegorov) SIMDBC interpreter doesn't support coverage yet.
+full_coverage_test: Skip
+
+# SIMDBC interpreter doesn't support lazy linking of natives.
+link_natives_lazily_test: SkipByDesign
+
+# SIMDBC interpreter doesn't support --no_lazy_dispatchers
+no_lazy_dispatchers_test: SkipByDesign
diff --git a/tests/standalone/verified_mem_test.dart b/tests/standalone/verified_mem_test.dart
index 7139e09..53da2ca 100644
--- a/tests/standalone/verified_mem_test.dart
+++ b/tests/standalone/verified_mem_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 //
 // Test write barrier verification mode.
-// VMOptions=--verified_mem --verify_before_gc --verify_after_gc --old_gen_growth_rate=1
+// VMOptions=--verify_before_gc --verify_after_gc --old_gen_growth_rate=1
 
 var a = [];
 
diff --git a/tests/try/poi/apply_updates_test.dart b/tests/try/poi/apply_updates_test.dart
index e8c8429..6c7c6cd 100644
--- a/tests/try/poi/apply_updates_test.dart
+++ b/tests/try/poi/apply_updates_test.dart
@@ -40,7 +40,7 @@
   Future run() => loadMainApp().then((LibraryElement library) {
     // Capture the current version of [before] before invoking the [updater].
     PartialFunctionElement before = library.localLookup(expectedUpdate);
-    var beforeNode = before.parseNode(compiler.parsing);
+    var beforeNode = before.parseNode(compiler.parsingContext);
 
     var context = new IncrementalCompilerContext();
     LibraryUpdater updater =
@@ -56,10 +56,10 @@
 
     // Check that the [updater] didn't modify the changed element.
     Expect.identical(before, update.before);
-    Expect.identical(beforeNode, before.parseNode(compiler.parsing));
+    Expect.identical(beforeNode, before.parseNode(compiler.parsingContext));
 
     PartialFunctionElement after = update.after;
-    var afterNode = after.parseNode(compiler.parsing);
+    var afterNode = after.parseNode(compiler.parsingContext);
 
     // Check that pretty-printing the elements match [source] (before), and
     // [newSource] (after).
@@ -72,7 +72,7 @@
 
     // Check that the update was applied by pretty-printing [before]. Make no
     // assumptions about [after], as the update may destroy that element.
-    beforeNode = before.parseNode(compiler.parsing);
+    beforeNode = before.parseNode(compiler.parsingContext);
     Expect.notEquals(source, '$beforeNode');
     Expect.stringEquals(newSource, '$beforeNode');
   });
diff --git a/third_party/boringssl/BUILD.gn b/third_party/boringssl/BUILD.gn
new file mode 100644
index 0000000..dc26330
--- /dev/null
+++ b/third_party/boringssl/BUILD.gn
@@ -0,0 +1,95 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/config.gni")
+import("//build/config/sanitizers/sanitizers.gni")
+
+# Config for us and everybody else depending on BoringSSL.
+config("external_config") {
+  include_dirs = [ "src/include" ]
+  if (is_component_build) {
+    defines = [ "BORINGSSL_SHARED_LIBRARY" ]
+  }
+}
+
+
+# Config internal to this build file, shared by boringssl and boringssl_fuzzer.
+config("internal_config") {
+  visibility = [ ":*" ]  # Only targets in this file can depend on this.
+  defines = [
+    "BORINGSSL_IMPLEMENTATION",
+    "BORINGSSL_NO_STATIC_INITIALIZER",
+    "OPENSSL_SMALL_FOOTPRINT",
+  ]
+}
+
+
+config("no_asm_config") {
+  visibility = [ ":*" ]  # Only targets in this file can depend on this.
+  defines = [ "OPENSSL_NO_ASM" ]
+}
+
+
+# The list of BoringSSL files is kept in boringssl.gypi.
+gypi_values =
+    exec_script("../../tools/gypi_to_gn.py",
+                [ rebase_path("boringssl.gypi") ],
+                "scope",
+                [ "boringssl.gypi" ])
+boringssl_sources =
+    gypi_values.boringssl_crypto_sources + gypi_values.boringssl_ssl_sources
+
+
+source_set("boringssl_asm") {
+  visibility = [ ":*" ]  # Only targets in this file can depend on this.
+  sources = []
+  #asmflags = []
+  include_dirs = [
+    "src/include",
+    # This is for arm_arch.h, which is needed by some asm files. Since the
+    # asm files are generated and kept in a different directory, they
+    # cannot use relative paths to find this file.
+    "src/crypto",
+  ]
+
+  if (current_cpu == "x64") {
+    if (is_ios) {
+      defines += [ "OPENSSL_NO_ASM" ]
+    } else if (is_mac) {
+      sources += gypi_values.boringssl_mac_x86_64_sources
+    } else if (is_linux || is_android) {
+      sources += gypi_values.boringssl_linux_x86_64_sources
+    } else {
+      public_configs = [ ":no_asm_config" ]
+    }
+  } else if (current_cpu == "x86") {
+    if (is_ios) {
+      defines += [ "OPENSSL_NO_ASM" ]
+    } else if (is_mac) {
+      sources += gypi_values.boringssl_mac_x86_sources
+    } else if (is_linux || is_android) {
+      sources += gypi_values.boringssl_linux_x86_sources
+    } else {
+      public_configs = [ ":no_asm_config" ]
+    }
+  } else if (current_cpu == "arm" && (is_linux || is_android)) {
+    sources += gypi_values.boringssl_linux_arm_sources
+  } else if (current_cpu == "arm64" && (is_linux || is_android)) {
+    sources += gypi_values.boringssl_linux_aarch64_sources
+  } else {
+    public_configs = [ ":no_asm_config" ]
+  }
+}
+
+
+component("boringssl") {
+  sources = boringssl_sources
+  deps = [
+    ":boringssl_asm",
+  ]
+  public_configs = [ ":external_config" ]
+  configs += [ ":internal_config" ]
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [ "//build/config/compiler:no_chromium_code" ]
+}
diff --git a/third_party/boringssl/boringssl_configurations.gypi b/third_party/boringssl/boringssl_configurations.gypi
index 0a82431..b963505 100644
--- a/third_party/boringssl/boringssl_configurations.gypi
+++ b/third_party/boringssl/boringssl_configurations.gypi
@@ -87,6 +87,13 @@
           'OPENSSL_NO_ASM',
         ],
       },
+      # Android 64-bit dbc build is for arm64, disable temporarily as well.
+      'Dart_Android_arm64_Base': {
+        'abstract': 1,
+        'defines': [
+          'OPENSSL_NO_ASM',
+        ],
+      },
       # When being built for Android nss expects __linux__ to be defined.
       'Dart_Android_Base': {
         'target_conditions': [
diff --git a/tools/VERSION b/tools/VERSION
index da869b8..24fcc60 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -25,7 +25,7 @@
 #
 CHANNEL dev
 MAJOR 1
-MINOR 16
+MINOR 17
 PATCH 0
-PRERELEASE 5
-PRERELEASE_PATCH 5
+PRERELEASE 0
+PRERELEASE_PATCH 0
diff --git a/tools/addlatexhash.dart b/tools/addlatexhash.dart
index a8872d5..48e655c 100755
--- a/tools/addlatexhash.dart
+++ b/tools/addlatexhash.dart
@@ -11,7 +11,9 @@
 // hash listing file name as the third argument. From docs/language a
 // typical usage would be as follows:
 //
-//   dart ../../tools/addlatexhash.dart dartLangSpec.tex out.tex hash.txt
+//   dart
+//     --package-root=<build dir>/packages \ 
+//     ../../tools/addlatexhash.dart dartLangSpec.tex out.tex hash.txt
 //
 // This will produce a normalized variant out.tex of the language
 // specification with hash values filled in, and a listing hash.txt of
@@ -24,8 +26,10 @@
 
 import 'dart:io';
 import 'dart:convert';
-import '../third_party/pkg/utf/lib/utf.dart';
-import '../third_party/pkg/crypto/lib/crypto.dart';
+
+import 'package:crypto/crypto.dart';
+import 'package:convert/convert.dart';
+import 'package:utf/utf.dart';
 
 // ----------------------------------------------------------------------
 // Normalization of the text: removal or normalization of parts that
@@ -484,16 +488,15 @@
 /// in [lines], stopping just before [nextIndex].  SIDE EFFECT:
 /// Outputs the simplified text and its hash value to [listSink].
 computeHashValue(lines, startIndex, nextIndex, listSink) {
-  final hashEncoder = new SHA1();
   final gatheredLine = gatherLines(lines, startIndex, nextIndex);
   final simplifiedLine = simplifyLine(gatheredLine);
   listSink.write("  % $simplifiedLine\n");
-  hashEncoder.add(encodeUtf8(simplifiedLine));
-  return hashEncoder.close();
+  var digest = sha1.convert(encodeUtf8(simplifiedLine));
+  return digest.bytes;
 }
 
 computeHashString(lines, startIndex, nextIndex, listSink) =>
-    CryptoUtils.bytesToHex(computeHashValue(lines,
+    hex.encode(computeHashValue(lines,
                                             startIndex,
                                             nextIndex,
                                             listSink));
diff --git a/tools/android_link.py b/tools/android_link.py
index 6efea04..7854ce4 100755
--- a/tools/android_link.py
+++ b/tools/android_link.py
@@ -48,9 +48,10 @@
   link_args = sys.argv[4:]
 
   # Check arguments.
-  if target_arch not in ['arm', 'arm64', 'ia32', 'x64']:
+  if target_arch not in ['arm', 'arm64', 'ia32', 'x64', 'simdbc', 'simdbc64']:
     raise Exception(sys.argv[0] +
-        " first argument must be 'arm', 'arm64', 'ia32', or 'x64'")
+        " first argument must be 'arm', 'arm64', 'ia32', 'x64', "
+        "'simdbc', or 'simdbc64'")
   if link_type not in ['executable', 'library', 'shared_library']:
     raise Exception(sys.argv[0] +
                     " second argument must be 'executable' or 'library'")
@@ -77,7 +78,7 @@
 
   # Set up the directory of the Android NDK cross-compiler toolchain.
   toolchain_arch = 'arm-linux-androideabi-4.9'
-  if target_arch == 'arm64':
+  if target_arch == 'arm64' or target_arch == "simdbc64":
     toolchain_arch = 'aarch64-linux-android-4.9'
   if target_arch == 'ia32':
     toolchain_arch = 'x86-4.9'
@@ -91,7 +92,7 @@
 
   # Set up the path to the linker executable.
   android_linker = os.path.join(android_toolchain, 'arm-linux-androideabi-g++')
-  if target_arch == 'arm64':
+  if target_arch == 'arm64' or target_arch == "simdbc64":
     android_linker = os.path.join(
         android_toolchain, 'aarch64-linux-android-c++')
   if target_arch == 'ia32':
@@ -102,7 +103,7 @@
   # Grab the path to libgcc.a, which we must explicitly add to the link,
   # by invoking the cross-compiler with the -print-libgcc-file-name flag.
   android_gcc = os.path.join(android_toolchain, 'arm-linux-androideabi-gcc')
-  if target_arch == 'arm64':
+  if target_arch == 'arm64' or target_arch == "simdbc64":
     android_gcc = os.path.join(android_toolchain, 'aarch64-linux-android-gcc')
   if target_arch == 'ia32':
     android_gcc = os.path.join(android_toolchain, 'i686-linux-android-gcc')
@@ -116,7 +117,7 @@
   android_ndk_sysroot = os.path.join(android_ndk_root,
       'platforms', 'android-14', 'arch-arm')
   libdir = 'lib'
-  if target_arch == 'arm64':
+  if target_arch == 'arm64' or target_arch == "simdbc64":
     android_ndk_sysroot = os.path.join(android_ndk_root,
       'platforms', 'android-21', 'arch-arm64')
   if target_arch == 'ia32':
diff --git a/tools/build.py b/tools/build.py
index 3ec70d2..4b9df2a 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -56,7 +56,7 @@
   result.add_option("-a", "--arch",
       help='Target architectures (comma-separated).',
       metavar='[all,ia32,x64,simarm,arm,simarmv6,armv6,simarmv5te,armv5te,'
-              'simmips,mips,simarm64,arm64,]',
+              'simmips,mips,simarm64,arm64,simdbc,]',
       default=utils.GuessArchitecture())
   result.add_option("--os",
     help='Target OSs (comma-separated).',
@@ -102,7 +102,8 @@
       return False
   for arch in options.arch:
     archs = ['ia32', 'x64', 'simarm', 'arm', 'simarmv6', 'armv6',
-             'simarmv5te', 'armv5te', 'simmips', 'mips', 'simarm64', 'arm64',]
+             'simarmv5te', 'armv5te', 'simmips', 'mips', 'simarm64', 'arm64',
+             'simdbc', 'simdbc64']
     if not arch in archs:
       print "Unknown arch %s" % arch
       return False
@@ -119,7 +120,8 @@
         print ("Cross-compilation to %s is not supported on host os %s."
                % (os_name, HOST_OS))
         return False
-      if not arch in ['ia32', 'x64', 'arm', 'armv6', 'armv5te', 'arm64', 'mips']:
+      if not arch in ['ia32', 'x64', 'arm', 'armv6', 'armv5te', 'arm64', 'mips',
+                      'simdbc', 'simdbc64']:
         print ("Cross-compilation to %s is not supported for architecture %s."
                % (os_name, arch))
         return False
@@ -137,9 +139,9 @@
 
   if target_os == 'android':
     android_toolchain = GetAndroidToolchainDir(HOST_OS, arch)
-    if arch == 'arm':
+    if arch == 'arm' or arch == 'simdbc':
       return os.path.join(android_toolchain, 'arm-linux-androideabi')
-    if arch == 'arm64':
+    if arch == 'arm64' or arch == 'simdbc64':
       return os.path.join(android_toolchain, 'aarch64-linux-android')
     if arch == 'ia32':
       return os.path.join(android_toolchain, 'i686-linux-android')
@@ -197,7 +199,7 @@
   global THIRD_PARTY_ROOT
   if host_os not in ['linux']:
     raise Exception('Unsupported host os %s' % host_os)
-  if target_arch not in ['ia32', 'x64', 'arm', 'arm64']:
+  if target_arch not in ['ia32', 'x64', 'arm', 'arm64', 'simdbc', 'simdbc64']:
     raise Exception('Unsupported target architecture %s' % target_arch)
 
   # Set up path to the Android NDK.
@@ -209,7 +211,7 @@
 
   # Set up the directory of the Android NDK cross-compiler toolchain.
   toolchain_arch = 'arm-linux-androideabi-4.9'
-  if target_arch == 'arm64':
+  if target_arch == 'arm64' or target_arch == 'simdbc64':
     toolchain_arch = 'aarch64-linux-android-4.9'
   if target_arch == 'ia32':
     toolchain_arch = 'x86-4.9'
diff --git a/tools/dom/idl/dart/dart.idl b/tools/dom/idl/dart/dart.idl
index 533a448..11a8cc95 100644
--- a/tools/dom/idl/dart/dart.idl
+++ b/tools/dom/idl/dart/dart.idl
@@ -422,6 +422,22 @@
     [DartSuppress] void send(sequence<unsigned long> data, optional double timestamp);
 };
 
+[DartSuppress]
+interface MutationEvent {};
+
+// Tweaks types required for Dart strong mode.
+[DartSupplemental]
+interface HTMLCollection {
+
+    // FIXME: The index argument should not be optional.
+    getter Node? item([Default=Undefined] optional unsigned long index);
+    getter any namedItem(DOMString name);
+
+    [DartSuppress] getter Element? item([Default=Undefined] optional unsigned long index);
+    [DartSuppress] getter Element? namedItem(DOMString name);
+
+};
+
 Element implements GlobalEventHandlers;
 
 
diff --git a/tools/dom/scripts/htmldartgenerator.py b/tools/dom/scripts/htmldartgenerator.py
index 007f3f5..c66ce5b 100644
--- a/tools/dom/scripts/htmldartgenerator.py
+++ b/tools/dom/scripts/htmldartgenerator.py
@@ -587,7 +587,7 @@
         inits = self._members_emitter.Emit(
             '\n  $(METADATA)'
             'factory $CONSTRUCTOR($PARAMS) {\n'
-            '    var e = $FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n'
+            '    $CONSTRUCTOR e = $FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n'
             '$!INITS'
             '    return e;\n'
             '  }\n',
diff --git a/tools/dom/scripts/htmleventgenerator.py b/tools/dom/scripts/htmleventgenerator.py
index 6e83fd3..2bf39b6 100644
--- a/tools/dom/scripts/htmleventgenerator.py
+++ b/tools/dom/scripts/htmleventgenerator.py
@@ -114,7 +114,7 @@
   '*.webkitfullscreenchange': ('fullscreenChange', 'Event'),
   '*.webkitfullscreenerror': ('fullscreenError', 'Event'),
   '*.wheel': ('wheel', 'WheelEvent'),
-  'AbstractWorker.error': ('error', 'ErrorEvent'),
+  'AbstractWorker.error': ('error', 'Event'),
   'AudioContext.complete': ('complete', 'Event'),
   'ApplicationCache.cached': ('cached', 'Event'),
   'ApplicationCache.checking': ('checking', 'Event'),
@@ -123,6 +123,7 @@
   'ApplicationCache.obsolete': ('obsolete', 'Event'),
   'ApplicationCache.progress': ('progress', 'ProgressEvent'),
   'ApplicationCache.updateready': ('updateReady', 'Event'),
+  'CompositorWorker.error': ('error', 'Event'),
   'Document.readystatechange': ('readyStateChange', 'Event'),
   'Document.securitypolicyviolation': ('securityPolicyViolation', 'SecurityPolicyViolationEvent'),
   'Document.selectionchange': ('selectionChange', 'Event'),
@@ -190,6 +191,7 @@
   'RTCPeerConnection.removestream': ('removeStream', 'MediaStreamEvent'),
   'RTCPeerConnection.signalingstatechange': ('signalingStateChange', 'Event'),
   'ScriptProcessorNode.audioprocess': ('audioProcess', 'AudioProcessingEvent'),
+  'SharedWorker.error': ('error', 'Event'),
   'SharedWorkerGlobalScope.connect': ('connect', 'Event'),
   'SpeechRecognition.audioend': ('audioEnd', 'Event'),
   'SpeechRecognition.audiostart': ('audioStart', 'Event'),
@@ -221,6 +223,7 @@
   'Window.pageshow': ('pageShow', 'Event'),
   'Window.progress': ('progress', 'Event'),
   'Window.webkittransitionend': ('webkitTransitionEnd', 'TransitionEvent'),
+  'Worker.error': ('error', 'Event'),
   'XMLHttpRequestEventTarget.abort': ('abort', 'ProgressEvent'),
   'XMLHttpRequestEventTarget.error': ('error', 'ProgressEvent'),
   'XMLHttpRequestEventTarget.load': ('load', 'ProgressEvent'),
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index 2712916..8b9311b 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -97,7 +97,6 @@
   'HTMLFrameSetElement',
   'HTMLMarqueeElement',
   'IDBAny',
-  'MutationEvent',
   'Notation',
   'PagePopupController',
   'RGBColor',
@@ -242,11 +241,14 @@
   'Document.title',
   'Document.webkitCancelFullScreen',
   'Document.webkitExitFullscreen',
+   # Not prefixed.
   'Document.webkitFullscreenElement',
   'Document.webkitFullscreenEnabled',
   'Document.webkitHidden',
   'Document.webkitIsFullScreen',
   'Document.webkitVisibilityState',
+   # Not prefixed but requires custom implementation for cross-browser compatibility.
+  'Document.visibilityState',
 
   'Element.animate',
   'Element.children',
@@ -318,13 +320,10 @@
   'MouseEvent.clientY',
   'MouseEvent.movementX',
   'MouseEvent.movementY',
-  'MouseEvent.webkitMovementX',
-  'MouseEvent.webkitMovementY',
   'MouseEvent.offsetX',
   'MouseEvent.offsetY',
   'MouseEvent.screenX',
   'MouseEvent.screenY',
-  'MutationEvent.initMutationEvent',
   'MutationObserver.observe',
   'Node.attributes',
   'Node.localName',
@@ -511,6 +510,7 @@
 # subclasses.
 # TODO(jacobr): cleanup and augment this list.
 removed_html_members = monitored.Set('htmlrenamer.removed_html_members', [
+    'Attr.textContent', # Not needed as it is the same as Node.textContent.
     'AudioBufferSourceNode.looping', # TODO(vsm): Use deprecated IDL annotation
     'CSSStyleDeclaration.getPropertyCSSValue',
     'CanvasRenderingContext2D.clearShadow',
@@ -768,6 +768,8 @@
     'MessageEvent.data',
     'MessageEvent.ports',
     'MessageEvent.webkitInitMessageEvent',
+    'MouseEvent.webkitMovementX',
+    'MouseEvent.webkitMovementY',
     'MouseEvent.x',
     'MouseEvent.y',
     'Navigator.registerServiceWorker',
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index efceff6..75e38fd 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -19,6 +19,21 @@
 HTML_LIBRARY_NAMES = ['html', 'indexed_db', 'svg',
                       'web_audio', 'web_gl', 'web_sql']
 
+# The following two sets let us avoid shadowing fields with properties.
+# This information could be derived from the IDL files but would require
+# a significant refactor to compute accurately. Instead we manually compute
+# these sets based on manual triage of strong mode errors.
+_force_property_members = monitored.Set('systemhtml._force_property_members', [
+    'Element.outerHtml',
+    'Element.isContentEditable',
+    'AudioContext.createGain',
+    'AudioContext.createScriptProcessor',
+    ])
+_safe_to_ignore_shadowing_members = monitored.Set('systemhtml._safe_to_ignore_shadowing_members', [
+    'SVGElement.tabIndex',
+    'SVGStyleElement.title',
+    ])
+
 _js_custom_members = monitored.Set('systemhtml._js_custom_members', [
     'AudioBufferSourceNode.start',
     'AudioBufferSourceNode.stop',
@@ -58,6 +73,10 @@
     'Document.createTreeWalker',
     'DOMException.name',
     'DOMException.toString',
+    # ListMixin already provides this method although the implementation
+    # is slower. As this class is obsolete anyway, we ignore the slowdown in
+    # DOMStringList performance.
+    'DOMStringList.contains',
     'Element.animate',
     'Element.createShadowRoot',
     'Element.insertAdjacentElement',
@@ -891,8 +910,13 @@
     #  is renamed.
     (super_attribute, super_attribute_interface) = self._FindShadowedAttribute(
         attribute)
+    if self._ForcePropertyMember(html_name):
+      self._members_emitter.Emit('\n  // Using property as subclass shadows.');
+      self._AddAttributeUsingProperties(attribute, html_name, read_only)
+      return
+
     if super_attribute:
-      if read_only:
+      if read_only or self._SafeToIgnoreShadowingMember(html_name):
         if attribute.type.id == super_attribute.type.id:
           # Compatible attribute, use the superclass property.  This works
           # because JavaScript will do its own dynamic dispatch.
@@ -908,6 +932,16 @@
       self._AddAttributeUsingProperties(attribute, html_name, read_only)
       return
 
+    # If the attribute is shadowed incompatibly in a subclass then we also
+    # can't just generate it as a field. In particular, this happens with
+    # DomMatrixReadOnly and its subclass DomMatrix. Force the superclass
+    # to generate getters. Hardcoding the known problem classes for now.
+    # TODO(alanknight): Fix this more generally.
+    if (self._interface.id == 'DOMMatrixReadOnly' or self._interface.id == 'DOMPointReadOnly'
+       or self._interface.id == 'DOMRectReadOnly'):
+        self._AddAttributeUsingProperties(attribute, html_name, read_only)
+        return
+
     # If the type has a conversion we need a getter or setter to contain the
     # conversion code.
     if (self._OutputConversion(attribute.type.id, attribute.id) or
@@ -1147,6 +1181,14 @@
     member_name = '%s.%s' % (self._interface.doc_js_name, member_name)
     return member_name in _js_custom_members
 
+  def _ForcePropertyMember(self, member_name):
+    member_name = '%s.%s' % (self._interface.doc_js_name, member_name)
+    return member_name in _force_property_members
+
+  def _SafeToIgnoreShadowingMember(self, member_name):
+    member_name = '%s.%s' % (self._interface.doc_js_name, member_name)
+    return member_name in _safe_to_ignore_shadowing_members
+
   def _RenamingAnnotation(self, idl_name, member_name):
     if member_name != idl_name:
       return  "@JSName('%s')\n  " % idl_name
diff --git a/tools/dom/src/AttributeMap.dart b/tools/dom/src/AttributeMap.dart
index c212a23..f72e2c3 100644
--- a/tools/dom/src/AttributeMap.dart
+++ b/tools/dom/src/AttributeMap.dart
@@ -13,7 +13,7 @@
     other.forEach((k, v) { this[k] = v; });
   }
 
-  bool containsValue(String value) {
+  bool containsValue(Object value) {
     for (var v in this.values) {
       if (value == v) {
         return true;
@@ -45,10 +45,11 @@
   Iterable<String> get keys {
     // TODO: generate a lazy collection instead.
     var attributes = _element._attributes;
-    var keys = new List<String>();
+    var keys = <String>[];
     for (int i = 0, len = attributes.length; i < len; i++) {
-      if (_matches(attributes[i])) {
-        keys.add(attributes[i].name);
+      _Attr attr = attributes[i];
+      if (_matches(attr)) {
+        keys.add(attr.name);
       }
     }
     return keys;
@@ -57,10 +58,11 @@
   Iterable<String> get values {
     // TODO: generate a lazy collection instead.
     var attributes = _element._attributes;
-    var values = new List<String>();
+    var values = <String>[];
     for (int i = 0, len = attributes.length; i < len; i++) {
-      if (_matches(attributes[i])) {
-        values.add(attributes[i].value);
+      _Attr attr = attributes[i];
+      if (_matches(attr)) {
+        values.add(attr.value);
       }
     }
     return values;
@@ -91,11 +93,11 @@
 
   _ElementAttributeMap(Element element): super(element);
 
-  bool containsKey(String key) {
+  bool containsKey(Object key) {
     return _element._hasAttribute(key);
   }
 
-  String operator [](String key) {
+  String operator [](Object key) {
     return _element.getAttribute(key);
   }
 
@@ -103,7 +105,7 @@
     _element.setAttribute(key, value);
   }
 
-  String remove(String key) {
+  String remove(Object key) {
     String value = _element.getAttribute(key);
     _element._removeAttribute(key);
     return value;
@@ -128,11 +130,11 @@
 
   _NamespacedAttributeMap(Element element, this._namespace): super(element);
 
-  bool containsKey(String key) {
+  bool containsKey(Object key) {
     return _element._hasAttributeNS(_namespace, key);
   }
 
-  String operator [](String key) {
+  String operator [](Object key) {
     return _element.getAttributeNS(_namespace, key);
   }
 
@@ -140,7 +142,7 @@
     _element.setAttributeNS(_namespace, key, value);
   }
 
-  String remove(String key) {
+  String remove(Object key) {
     String value = this[key];
     _element._removeAttributeNS(_namespace, key);
     return value;
@@ -174,11 +176,11 @@
   }
 
   // TODO: Use lazy iterator when it is available on Map.
-  bool containsValue(String value) => values.any((v) => v == value);
+  bool containsValue(Object value) => values.any((v) => v == value);
 
-  bool containsKey(String key) => _attributes.containsKey(_attr(key));
+  bool containsKey(Object key) => _attributes.containsKey(_attr(key));
 
-  String operator [](String key) => _attributes[_attr(key)];
+  String operator [](Object key) => _attributes[_attr(key)];
 
   void operator []=(String key, String value) {
     _attributes[_attr(key)] = value;
@@ -187,7 +189,7 @@
   String putIfAbsent(String key, String ifAbsent()) =>
     _attributes.putIfAbsent(_attr(key), ifAbsent);
 
-  String remove(String key) => _attributes.remove(_attr(key));
+  String remove(Object key) => _attributes.remove(_attr(key));
 
   void clear() {
     // Needs to operate on a snapshot since we are mutating the collection.
@@ -205,7 +207,7 @@
   }
 
   Iterable<String> get keys {
-    final keys = new List<String>();
+    final keys = <String>[];
     _attributes.forEach((String key, String value) {
       if (_matches(key)) {
         keys.add(_strip(key));
@@ -215,7 +217,7 @@
   }
 
   Iterable<String> get values {
-    final values = new List<String>();
+    final values = <String>[];
     _attributes.forEach((String key, String value) {
       if (_matches(key)) {
         values.add(value);
diff --git a/tools/dom/src/CrossFrameTypes.dart b/tools/dom/src/CrossFrameTypes.dart
index a923377..40af92e 100644
--- a/tools/dom/src/CrossFrameTypes.dart
+++ b/tools/dom/src/CrossFrameTypes.dart
@@ -139,7 +139,7 @@
    * * [Cross-document messaging](https://html.spec.whatwg.org/multipage/comms.html#web-messaging)
    *   from WHATWG.
    */
-  void postMessage(var message, String targetOrigin, [List messagePorts]);
+  void postMessage(var message, String targetOrigin, [List<MessagePort> messagePorts]);
 }
 
 abstract class LocationBase {
diff --git a/tools/dom/src/CssClassSet.dart b/tools/dom/src/CssClassSet.dart
index 8224b77..d2334a7 100644
--- a/tools/dom/src/CssClassSet.dart
+++ b/tools/dom/src/CssClassSet.dart
@@ -41,7 +41,7 @@
    * [value] must be a valid 'token' representing a single class, i.e. a
    * non-empty string containing no whitespace.
    */
-  bool contains(String value);
+  bool contains(Object value);
 
   /**
    * Add the class [value] to element.
@@ -93,7 +93,7 @@
    * Each element of [iterable] must be a valid 'token' representing a single
    * class, i.e. a non-empty string containing no whitespace.
    */
-  void removeAll(Iterable<String> iterable);
+  void removeAll(Iterable<Object> iterable);
 
   /**
    * Toggles all classes specified in [iterable] on element.
diff --git a/tools/dom/src/CssRectangle.dart b/tools/dom/src/CssRectangle.dart
index 440bebe..656f853 100644
--- a/tools/dom/src/CssRectangle.dart
+++ b/tools/dom/src/CssRectangle.dart
@@ -10,7 +10,7 @@
  */
 class _ContentCssRect extends CssRect {
 
-  _ContentCssRect(element) : super(element);
+  _ContentCssRect(Element element) : super(element);
 
   num get height => _element.offsetHeight +
       _addOrSubtractToBoxModel(_HEIGHT, _CONTENT);
@@ -31,9 +31,11 @@
     if (newHeight is Dimension) {
       if (newHeight.value < 0) newHeight = new Dimension.px(0);
       _element.style.height = newHeight.toString();
-    } else {
+    } else if (newHeight is num) {
       if (newHeight < 0) newHeight = 0;
       _element.style.height = '${newHeight}px';
+    } else {
+      throw new ArgumentError("newHeight is not a Dimension or num");
     }
   }
 
@@ -49,9 +51,11 @@
     if (newWidth is Dimension) {
       if (newWidth.value < 0) newWidth = new Dimension.px(0);
       _element.style.width = newWidth.toString();
-    } else {
+    } else if (newWidth is num) {
       if (newWidth < 0) newWidth = 0;
       _element.style.width = '${newWidth}px';
+    } else {
+      throw new ArgumentError("newWidth is not a Dimension or num");
     }
   }
 
@@ -68,7 +72,7 @@
 class _ContentCssListRect extends _ContentCssRect {
   List<Element> _elementList;
 
-  _ContentCssListRect(elementList) : super(elementList.first) {
+  _ContentCssListRect(List<Element> elementList) : super(elementList.first) {
     _elementList = elementList;
   }
 
@@ -157,10 +161,10 @@
  * animation frame is discouraged. See also:
  * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
  */
-abstract class CssRect extends MutableRectangle<num> {
+abstract class CssRect implements Rectangle<num> {
   Element _element;
 
-  CssRect(this._element) : super(0, 0, 0, 0);
+  CssRect(this._element);
 
   num get left;
 
@@ -253,6 +257,102 @@
     }
     return val;
   }
+
+  // TODO(jacobr): these methods are duplicated from _RectangleBase in dart:math
+  // Ideally we would provide a RectangleMixin class that provides this implementation.
+  // In an ideal world we would exp
+  /** The x-coordinate of the right edge. */
+  num get right => left + width;
+  /** The y-coordinate of the bottom edge. */
+  num get bottom => top + height;
+
+  String toString() {
+    return 'Rectangle ($left, $top) $width x $height';
+  }
+
+  bool operator ==(other) {
+    if (other is !Rectangle) return false;
+    return left == other.left && top == other.top && right == other.right &&
+        bottom == other.bottom;
+  }
+
+  int get hashCode => _JenkinsSmiHash.hash4(left.hashCode, top.hashCode,
+      right.hashCode, bottom.hashCode);
+
+  /**
+   * Computes the intersection of `this` and [other].
+   *
+   * The intersection of two axis-aligned rectangles, if any, is always another
+   * axis-aligned rectangle.
+   *
+   * Returns the intersection of this and `other`, or `null` if they don't
+   * intersect.
+   */
+  Rectangle<num> intersection(Rectangle<num> other) {
+    var x0 = max(left, other.left);
+    var x1 = min(left + width, other.left + other.width);
+
+    if (x0 <= x1) {
+      var y0 = max(top, other.top);
+      var y1 = min(top + height, other.top + other.height);
+
+      if (y0 <= y1) {
+        return new Rectangle<num>(x0, y0, x1 - x0, y1 - y0);
+      }
+    }
+    return null;
+  }
+
+
+  /**
+   * Returns true if `this` intersects [other].
+   */
+  bool intersects(Rectangle<num> other) {
+    return (left <= other.left + other.width &&
+        other.left <= left + width &&
+        top <= other.top + other.height &&
+        other.top <= top + height);
+  }
+
+  /**
+   * Returns a new rectangle which completely contains `this` and [other].
+   */
+  Rectangle<num> boundingBox(Rectangle<num> other) {
+    var right = max(this.left + this.width, other.left + other.width);
+    var bottom = max(this.top + this.height, other.top + other.height);
+
+    var left = min(this.left, other.left);
+    var top = min(this.top, other.top);
+
+    return new Rectangle<num>(left, top, right - left, bottom - top);
+  }
+
+  /**
+   * Tests whether `this` entirely contains [another].
+   */
+  bool containsRectangle(Rectangle<num> another) {
+    return left <= another.left &&
+           left + width >= another.left + another.width &&
+           top <= another.top &&
+           top + height >= another.top + another.height;
+  }
+
+  /**
+   * Tests whether [another] is inside or along the edges of `this`.
+   */
+  bool containsPoint(Point<num> another) {
+    return another.x >= left &&
+           another.x <= left + width &&
+           another.y >= top &&
+           another.y <= top + height;
+  }
+
+  Point<num> get topLeft => new Point<num>(this.left, this.top);
+  Point<num> get topRight => new Point<num>(this.left + this.width, this.top);
+  Point<num> get bottomRight => new Point<num>(this.left + this.width,
+      this.top + this.height);
+  Point<num> get bottomLeft => new Point<num>(this.left,
+      this.top + this.height);
 }
 
 final _HEIGHT = ['top', 'bottom'];
diff --git a/tools/dom/src/EventStreamProvider.dart b/tools/dom/src/EventStreamProvider.dart
index 3b41f51..76bed57 100644
--- a/tools/dom/src/EventStreamProvider.dart
+++ b/tools/dom/src/EventStreamProvider.dart
@@ -34,7 +34,7 @@
    * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
    */
   Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
-    new _EventStream(e, _eventType, useCapture);
+    new _EventStream<T>(e, _eventType, useCapture);
 
   /**
    * Gets an [ElementEventStream] for this event type, on the specified element.
@@ -58,7 +58,7 @@
    * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
    */
   ElementStream<T> forElement(Element e, {bool useCapture: false}) {
-    return new _ElementEventStreamImpl(e, _eventType, useCapture);
+    return new _ElementEventStreamImpl<T>(e, _eventType, useCapture);
   }
 
   /**
@@ -129,8 +129,8 @@
   _EventStream(this._target, this._eventType, this._useCapture);
 
   // DOM events are inherently multi-subscribers.
-  Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription),
-                               void onCancel(StreamSubscription subscription)})
+  Stream<T> asBroadcastStream({void onListen(StreamSubscription<T> subscription),
+                               void onCancel(StreamSubscription<T> subscription)})
       => this;
   bool get isBroadcast => true;
 
@@ -144,6 +144,11 @@
   }
 }
 
+bool _matchesWithAncestors(Event event, String selector) {
+  var target = event.target;
+  return target is Element ? target.matchesWithAncestors(selector) : false;
+}
+
 /**
  * Adapter for exposing DOM Element events as streams, while also allowing
  * event delegation.
@@ -154,7 +159,7 @@
       super(target, eventType, useCapture);
 
   Stream<T> matches(String selector) => this.where(
-      (event) => event.target.matchesWithAncestors(selector)).map((e) {
+      (event) => _matchesWithAncestors(event, selector)).map((e) {
         e._selector = selector;
         return e;
       });
@@ -178,7 +183,7 @@
       this._targetList, this._eventType, this._useCapture);
 
   Stream<T> matches(String selector) => this.where(
-      (event) => event.target.matchesWithAncestors(selector)).map((e) {
+      (event) => _matchesWithAncestors(event, selector)).map((e) {
         e._selector = selector;
         return e;
       });
@@ -188,37 +193,46 @@
       { Function onError,
         void onDone(),
         bool cancelOnError}) {
-    var pool = new _StreamPool.broadcast();
+    var pool = new _StreamPool<T>.broadcast();
     for (var target in _targetList) {
-      pool.add(new _EventStream(target, _eventType, _useCapture));
+      pool.add(new _EventStream<T>(target, _eventType, _useCapture));
     }
     return pool.stream.listen(onData, onError: onError, onDone: onDone,
           cancelOnError: cancelOnError);
   }
 
   StreamSubscription<T> capture(void onData(T event)) {
-    var pool = new _StreamPool.broadcast();
+    var pool = new _StreamPool<T>.broadcast();
     for (var target in _targetList) {
-      pool.add(new _EventStream(target, _eventType, true));
+      pool.add(new _EventStream<T>(target, _eventType, true));
     }
     return pool.stream.listen(onData);
   }
 
-  Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription),
-                               void onCancel(StreamSubscription subscription)})
+  Stream<T> asBroadcastStream({void onListen(StreamSubscription<T> subscription),
+                               void onCancel(StreamSubscription<T> subscription)})
       => this;
   bool get isBroadcast => true;
 }
 
+// We would like this to just be EventListener<T> but that typdef cannot
+// use generics until dartbug/26276 is fixed.
+typedef _EventListener<T extends Event>(T event);
+
 class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
   int _pauseCount = 0;
   EventTarget _target;
   final String _eventType;
-  var _onData;
+  EventListener _onData;
   final bool _useCapture;
 
-  _EventStreamSubscription(this._target, this._eventType, onData,
-      this._useCapture) : _onData = _wrapZone(onData) {
+  // TODO(jacobr): for full strong mode correctness we should write
+  // _onData = onData == null ? null : _wrapZone/*<Event, dynamic>*/((e) => onData(e as T))
+  // but that breaks 114 co19 tests as well as multiple html tests as it is reasonable
+  // to pass the wrong type of event object to an event listener as part of a
+  // test.
+  _EventStreamSubscription(this._target, this._eventType, void onData(T event),
+      this._useCapture) : _onData = _wrapZone/*<Event, dynamic>*/(onData) {
     _tryResume();
   }
 
@@ -240,8 +254,7 @@
     }
     // Remove current event listener.
     _unlisten();
-
-    _onData = _wrapZone(handleData);
+    _onData = _wrapZone/*<Event, dynamic>*/(handleData);
     _tryResume();
   }
 
@@ -320,8 +333,8 @@
         onDone: onDone, cancelOnError: cancelOnError);
   }
 
-  Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription),
-                               void onCancel(StreamSubscription subscription)})
+  Stream<T> asBroadcastStream({void onListen(StreamSubscription<T> subscription),
+                               void onCancel(StreamSubscription<T> subscription)})
       => _streamController.stream;
 
   bool get isBroadcast => true;
@@ -412,16 +425,16 @@
   const _CustomEventStreamProvider(this._eventTypeGetter);
 
   Stream<T> forTarget(EventTarget e, {bool useCapture: false}) {
-    return new _EventStream(e, _eventTypeGetter(e), useCapture);
+    return new _EventStream<T>(e, _eventTypeGetter(e), useCapture);
   }
 
   ElementStream<T> forElement(Element e, {bool useCapture: false}) {
-    return new _ElementEventStreamImpl(e, _eventTypeGetter(e), useCapture);
+    return new _ElementEventStreamImpl<T>(e, _eventTypeGetter(e), useCapture);
   }
 
   ElementStream<T> _forElementList(ElementList e,
       {bool useCapture: false}) {
-    return new _ElementListEventStreamImpl(e, _eventTypeGetter(e), useCapture);
+    return new _ElementListEventStreamImpl<T>(e, _eventTypeGetter(e), useCapture);
   }
 
   String getEventType(EventTarget target) {
diff --git a/tools/dom/src/KeyboardEventStream.dart b/tools/dom/src/KeyboardEventStream.dart
index 520ac87..39c5cfc 100644
--- a/tools/dom/src/KeyboardEventStream.dart
+++ b/tools/dom/src/KeyboardEventStream.dart
@@ -16,7 +16,7 @@
    * The set of keys that have been pressed down without seeing their
    * corresponding keyup event.
    */
-  final List<KeyboardEvent> _keyDownList = <KeyboardEvent>[];
+  final List<KeyEvent> _keyDownList = <KeyEvent>[];
 
   /** The type of KeyEvent we are tracking (keyup, keydown, keypress). */
   final String _type;
@@ -75,8 +75,9 @@
    * General constructor, performs basic initialization for our improved
    * KeyboardEvent controller.
    */
-  _KeyboardEventHandler(this._type): super(_EVENT_TYPE),
-      _stream = new _CustomKeyEventStreamImpl('event'), _target = null;
+  _KeyboardEventHandler(this._type):
+      _stream = new _CustomKeyEventStreamImpl('event'), _target = null,
+      super(_EVENT_TYPE);
 
   /**
    * Hook up all event listeners under the covers so we can estimate keycodes
diff --git a/tools/dom/src/NodeValidatorBuilder.dart b/tools/dom/src/NodeValidatorBuilder.dart
index 24f079b..bcf807c 100644
--- a/tools/dom/src/NodeValidatorBuilder.dart
+++ b/tools/dom/src/NodeValidatorBuilder.dart
@@ -4,7 +4,6 @@
 
 part of dart.dom.html;
 
-
 /**
  * Class which helps construct standard node validation policies.
  *
@@ -22,11 +21,9 @@
  * appropriate.
  */
 class NodeValidatorBuilder implements NodeValidator {
-
   final List<NodeValidator> _validators = <NodeValidator>[];
 
-  NodeValidatorBuilder() {
-  }
+  NodeValidatorBuilder() {}
 
   /**
    * Creates a new NodeValidatorBuilder which accepts common constructs.
@@ -155,29 +152,17 @@
       {UriPolicy uriPolicy,
       Iterable<String> attributes,
       Iterable<String> uriAttributes}) {
-
     var tagNameUpper = tagName.toUpperCase();
-    var attrs;
-    if (attributes != null) {
-      attrs =
-          attributes.map((name) => '$tagNameUpper::${name.toLowerCase()}');
-    }
-    var uriAttrs;
-    if (uriAttributes != null) {
-      uriAttrs =
-          uriAttributes.map((name) => '$tagNameUpper::${name.toLowerCase()}');
-    }
+    var attrs = attributes
+        ?.map /*<String>*/ ((name) => '$tagNameUpper::${name.toLowerCase()}');
+    var uriAttrs = uriAttributes
+        ?.map /*<String>*/ ((name) => '$tagNameUpper::${name.toLowerCase()}');
     if (uriPolicy == null) {
       uriPolicy = new UriPolicy();
     }
 
     add(new _CustomElementNodeValidator(
-        uriPolicy,
-        [tagNameUpper],
-        attrs,
-        uriAttrs,
-        false,
-        true));
+        uriPolicy, [tagNameUpper], attrs, uriAttrs, false, true));
   }
 
   /**
@@ -192,37 +177,26 @@
       {UriPolicy uriPolicy,
       Iterable<String> attributes,
       Iterable<String> uriAttributes}) {
-
     var baseNameUpper = baseName.toUpperCase();
     var tagNameUpper = tagName.toUpperCase();
-    var attrs;
-    if (attributes != null) {
-      attrs =
-          attributes.map((name) => '$baseNameUpper::${name.toLowerCase()}');
-    }
-    var uriAttrs;
-    if (uriAttributes != null) {
-      uriAttrs =
-          uriAttributes.map((name) => '$baseNameUpper::${name.toLowerCase()}');
-    }
+    var attrs = attributes
+        ?.map /*<String>*/ ((name) => '$baseNameUpper::${name.toLowerCase()}');
+    var uriAttrs = uriAttributes
+        ?.map /*<String>*/ ((name) => '$baseNameUpper::${name.toLowerCase()}');
     if (uriPolicy == null) {
       uriPolicy = new UriPolicy();
     }
 
-    add(new _CustomElementNodeValidator(
-        uriPolicy,
-        [tagNameUpper, baseNameUpper],
-        attrs,
-        uriAttrs,
-        true,
-        false));
+    add(new _CustomElementNodeValidator(uriPolicy,
+        [tagNameUpper, baseNameUpper], attrs, uriAttrs, true, false));
   }
 
-  void allowElement(String tagName, {UriPolicy uriPolicy,
-    Iterable<String> attributes,
-    Iterable<String> uriAttributes}) {
-
-    allowCustomElement(tagName, uriPolicy: uriPolicy,
+  void allowElement(String tagName,
+      {UriPolicy uriPolicy,
+      Iterable<String> attributes,
+      Iterable<String> uriAttributes}) {
+    allowCustomElement(tagName,
+        uriPolicy: uriPolicy,
         attributes: attributes,
         uriAttributes: uriAttributes);
   }
@@ -253,8 +227,8 @@
   }
 
   bool allowsAttribute(Element element, String attributeName, String value) {
-    return _validators.any(
-        (v) => v.allowsAttribute(element, attributeName, value));
+    return _validators
+        .any((v) => v.allowsAttribute(element, attributeName, value));
   }
 }
 
@@ -265,76 +239,70 @@
   final UriPolicy uriPolicy;
 
   factory _SimpleNodeValidator.allowNavigation(UriPolicy uriPolicy) {
-    return new _SimpleNodeValidator(uriPolicy,
-      allowedElements: const [
-        'A',
-        'FORM'],
-      allowedAttributes: const [
-        'A::accesskey',
-        'A::coords',
-        'A::hreflang',
-        'A::name',
-        'A::shape',
-        'A::tabindex',
-        'A::target',
-        'A::type',
-        'FORM::accept',
-        'FORM::autocomplete',
-        'FORM::enctype',
-        'FORM::method',
-        'FORM::name',
-        'FORM::novalidate',
-        'FORM::target',
-      ],
-      allowedUriAttributes: const [
-        'A::href',
-        'FORM::action',
-      ]);
+    return new _SimpleNodeValidator(uriPolicy, allowedElements: const [
+      'A',
+      'FORM'
+    ], allowedAttributes: const [
+      'A::accesskey',
+      'A::coords',
+      'A::hreflang',
+      'A::name',
+      'A::shape',
+      'A::tabindex',
+      'A::target',
+      'A::type',
+      'FORM::accept',
+      'FORM::autocomplete',
+      'FORM::enctype',
+      'FORM::method',
+      'FORM::name',
+      'FORM::novalidate',
+      'FORM::target',
+    ], allowedUriAttributes: const [
+      'A::href',
+      'FORM::action',
+    ]);
   }
 
   factory _SimpleNodeValidator.allowImages(UriPolicy uriPolicy) {
-    return new _SimpleNodeValidator(uriPolicy,
-      allowedElements: const [
-        'IMG'
-      ],
-      allowedAttributes: const [
-        'IMG::align',
-        'IMG::alt',
-        'IMG::border',
-        'IMG::height',
-        'IMG::hspace',
-        'IMG::ismap',
-        'IMG::name',
-        'IMG::usemap',
-        'IMG::vspace',
-        'IMG::width',
-      ],
-      allowedUriAttributes: const [
-        'IMG::src',
-      ]);
+    return new _SimpleNodeValidator(uriPolicy, allowedElements: const [
+      'IMG'
+    ], allowedAttributes: const [
+      'IMG::align',
+      'IMG::alt',
+      'IMG::border',
+      'IMG::height',
+      'IMG::hspace',
+      'IMG::ismap',
+      'IMG::name',
+      'IMG::usemap',
+      'IMG::vspace',
+      'IMG::width',
+    ], allowedUriAttributes: const [
+      'IMG::src',
+    ]);
   }
 
   factory _SimpleNodeValidator.allowTextElements() {
-    return new _SimpleNodeValidator(null,
-      allowedElements: const [
-        'B',
-        'BLOCKQUOTE',
-        'BR',
-        'EM',
-        'H1',
-        'H2',
-        'H3',
-        'H4',
-        'H5',
-        'H6',
-        'HR',
-        'I',
-        'LI',
-        'OL',
-        'P',
-        'SPAN',
-        'UL',
-      ]);
+    return new _SimpleNodeValidator(null, allowedElements: const [
+      'B',
+      'BLOCKQUOTE',
+      'BR',
+      'EM',
+      'H1',
+      'H2',
+      'H3',
+      'H4',
+      'H5',
+      'H6',
+      'HR',
+      'I',
+      'LI',
+      'OL',
+      'P',
+      'SPAN',
+      'UL',
+    ]);
   }
 
   /**
@@ -343,15 +311,16 @@
    * lowercase attribute name. For example `'IMG:src'`.
    */
   _SimpleNodeValidator(this.uriPolicy,
-      {Iterable<String> allowedElements, Iterable<String> allowedAttributes,
-        Iterable<String> allowedUriAttributes}) {
+      {Iterable<String> allowedElements,
+      Iterable<String> allowedAttributes,
+      Iterable<String> allowedUriAttributes}) {
     this.allowedElements.addAll(allowedElements ?? const []);
     allowedAttributes = allowedAttributes ?? const [];
     allowedUriAttributes = allowedUriAttributes ?? const [];
-    var legalAttributes = allowedAttributes.where(
-        (x) => !_Html5NodeValidator._uriAttributes.contains(x));
-    var extraUriAttributes = allowedAttributes.where(
-        (x) => _Html5NodeValidator._uriAttributes.contains(x));
+    var legalAttributes = allowedAttributes
+        .where((x) => !_Html5NodeValidator._uriAttributes.contains(x));
+    var extraUriAttributes = allowedAttributes
+        .where((x) => _Html5NodeValidator._uriAttributes.contains(x));
     this.allowedAttributes.addAll(legalAttributes);
     this.allowedUriAttributes.addAll(allowedUriAttributes);
     this.allowedUriAttributes.addAll(extraUriAttributes);
@@ -384,19 +353,19 @@
   final bool allowTypeExtension;
   final bool allowCustomTag;
 
-  _CustomElementNodeValidator(UriPolicy uriPolicy,
+  _CustomElementNodeValidator(
+      UriPolicy uriPolicy,
       Iterable<String> allowedElements,
       Iterable<String> allowedAttributes,
       Iterable<String> allowedUriAttributes,
       bool allowTypeExtension,
-      bool allowCustomTag):
-
-      super(uriPolicy,
-          allowedElements: allowedElements,
-          allowedAttributes: allowedAttributes,
-          allowedUriAttributes: allowedUriAttributes),
-      this.allowTypeExtension = allowTypeExtension == true,
-      this.allowCustomTag = allowCustomTag == true;
+      bool allowCustomTag)
+      : this.allowTypeExtension = allowTypeExtension == true,
+        this.allowCustomTag = allowCustomTag == true,
+        super(uriPolicy,
+            allowedElements: allowedElements,
+            allowedAttributes: allowedAttributes,
+            allowedUriAttributes: allowedUriAttributes);
 
   bool allowsElement(Element element) {
     if (allowTypeExtension) {
@@ -406,12 +375,14 @@
             allowedElements.contains(Element._safeTagName(element));
       }
     }
-    return allowCustomTag && allowedElements.contains(Element._safeTagName(element));
+    return allowCustomTag &&
+        allowedElements.contains(Element._safeTagName(element));
   }
 
   bool allowsAttribute(Element element, String attributeName, String value) {
-   if (allowsElement(element)) {
-      if (allowTypeExtension && attributeName == 'is' &&
+    if (allowsElement(element)) {
+      if (allowTypeExtension &&
+          attributeName == 'is' &&
           allowedElements.contains(value.toUpperCase())) {
         return true;
       }
@@ -422,19 +393,22 @@
 }
 
 class _TemplatingNodeValidator extends _SimpleNodeValidator {
-  static const _TEMPLATE_ATTRS =
-      const <String>['bind', 'if', 'ref', 'repeat', 'syntax'];
+  static const _TEMPLATE_ATTRS = const <String>[
+    'bind',
+    'if',
+    'ref',
+    'repeat',
+    'syntax'
+  ];
 
   final Set<String> _templateAttrs;
 
-  _TemplatingNodeValidator():
-      super(null,
-          allowedElements: [
-            'TEMPLATE'
-          ],
-          allowedAttributes: _TEMPLATE_ATTRS.map((attr) => 'TEMPLATE::$attr')),
-      _templateAttrs = new Set<String>.from(_TEMPLATE_ATTRS) {
-  }
+  _TemplatingNodeValidator()
+      : _templateAttrs = new Set<String>.from(_TEMPLATE_ATTRS),
+        super(null,
+            allowedElements: ['TEMPLATE'],
+            allowedAttributes:
+                _TEMPLATE_ATTRS.map((attr) => 'TEMPLATE::$attr')) {}
 
   bool allowsAttribute(Element element, String attributeName, String value) {
     if (super.allowsAttribute(element, attributeName, value)) {
@@ -445,14 +419,13 @@
       return true;
     }
 
-    if (element.attributes['template'] == "" ) {
+    if (element.attributes['template'] == "") {
       return _templateAttrs.contains(attributeName);
     }
     return false;
   }
 }
 
-
 class _SvgNodeValidator implements NodeValidator {
   bool allowsElement(Element element) {
     if (element is svg.ScriptElement) {
@@ -462,7 +435,8 @@
     // foreignobject tag as SvgElement. We don't want foreignobject contents
     // anyway, so just remove the whole tree outright. And we can't rely
     // on IE recognizing the SvgForeignObject type, so go by tagName. Bug 23144
-    if (element is svg.SvgElement && Element._safeTagName(element) == 'foreignObject') {
+    if (element is svg.SvgElement &&
+        Element._safeTagName(element) == 'foreignObject') {
       return false;
     }
     if (element is svg.SvgElement) {
diff --git a/tools/dom/src/WrappedList.dart b/tools/dom/src/WrappedList.dart
index fd3ca95..c06e8dc 100644
--- a/tools/dom/src/WrappedList.dart
+++ b/tools/dom/src/WrappedList.dart
@@ -10,7 +10,7 @@
  */
 class _WrappedList<E extends Node> extends ListBase<E>
     implements NodeListWrapper {
-  final List _list;
+  final List<Node> _list;
 
   _WrappedList(this._list);
 
@@ -30,13 +30,13 @@
 
   // List APIs
 
-  E operator [](int index) => _list[index];
+  E operator [](int index) => _downcast/*<Node, E>*/(_list[index]);
 
   void operator []=(int index, E value) { _list[index] = value; }
 
   set length(int newLength) { _list.length = newLength; }
 
-  void sort([int compare(E a, E b)]) { _list.sort(compare); }
+  void sort([int compare(E a, E b)]) { _list.sort((Node a, Node b) => compare(_downcast/*<Node, E>*/(a), _downcast/*<Node, E>*/(b))); }
 
   int indexOf(Object element, [int start = 0]) => _list.indexOf(element, start);
 
@@ -44,7 +44,7 @@
 
   void insert(int index, E element) => _list.insert(index, element);
 
-  E removeAt(int index) => _list.removeAt(index);
+  E removeAt(int index) => _downcast/*<Node, E>*/(_list.removeAt(index));
 
   void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
     _list.setRange(start, end, iterable, skipCount);
@@ -66,8 +66,8 @@
 /**
  * Iterator wrapper for _WrappedList.
  */
-class _WrappedIterator<E> implements Iterator<E> {
-  Iterator _iterator;
+class _WrappedIterator<E extends Node> implements Iterator<E> {
+  Iterator<Node> _iterator;
 
   _WrappedIterator(this._iterator);
 
@@ -75,5 +75,8 @@
     return _iterator.moveNext();
   }
 
-  E get current => _iterator.current;
+  E get current => _downcast/*<Node, E>*/(_iterator.current);
 }
+
+// ignore: STRONG_MODE_DOWN_CAST_COMPOSITE
+/*=To*/ _downcast/*<From, To extends From>*/(dynamic /*=From*/ x) => x;
diff --git a/tools/dom/src/dart2js_CssClassSet.dart b/tools/dom/src/dart2js_CssClassSet.dart
index 8d483b3..087685f 100644
--- a/tools/dom/src/dart2js_CssClassSet.dart
+++ b/tools/dom/src/dart2js_CssClassSet.dart
@@ -120,11 +120,11 @@
     _addAll(_element, iterable);
   }
 
-  void removeAll(Iterable<String> iterable) {
+  void removeAll(Iterable<Object> iterable) {
     _removeAll(_element, iterable);
   }
 
-  void retainAll(Iterable<String> iterable) {
+  void retainAll(Iterable<Object> iterable) {
     _removeWhere(_element, iterable.toSet().contains, false);
   }
 
diff --git a/tools/dom/src/dart2js_DOMImplementation.dart b/tools/dom/src/dart2js_DOMImplementation.dart
index 24e6a6c..81e9d6d 100644
--- a/tools/dom/src/dart2js_DOMImplementation.dart
+++ b/tools/dom/src/dart2js_DOMImplementation.dart
@@ -57,7 +57,7 @@
   Events get on => throw new UnsupportedError(
     'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
-  void _addEventListener([String type, EventListener listener, bool useCapture])
+  void _addEventListener(String type, EventListener listener, [bool useCapture])
       => throw new UnsupportedError(
     'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
@@ -68,8 +68,8 @@
   bool dispatchEvent(Event event) => throw new UnsupportedError(
     'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
-  void _removeEventListener([String type, EventListener listener,
-      bool useCapture]) => throw new UnsupportedError(
+  void _removeEventListener(String type, EventListener listener,
+      [bool useCapture]) => throw new UnsupportedError(
     'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
   void removeEventListener(String type, EventListener listener,
diff --git a/tools/dom/src/dart2js_WrappedEvent.dart b/tools/dom/src/dart2js_WrappedEvent.dart
index 3f8789f..8508b3e 100644
--- a/tools/dom/src/dart2js_WrappedEvent.dart
+++ b/tools/dom/src/dart2js_WrappedEvent.dart
@@ -59,8 +59,8 @@
       throw new UnsupportedError('Cannot call matchingTarget if this Event did'
           ' not arise as a result of event delegation.');
     }
-    var currentTarget = this.currentTarget;
-    var target = this.target;
+    Element currentTarget = this.currentTarget;
+    Element target = this.target;
     var matchedTarget;
     do {
       if (target.matches(_selector)) return target;
diff --git a/tools/dom/src/shared_html.dart b/tools/dom/src/shared_html.dart
index b6c9c62c..27fa2b7 100644
--- a/tools/dom/src/shared_html.dart
+++ b/tools/dom/src/shared_html.dart
@@ -4,17 +4,25 @@
 
 part of dart.dom.html;
 
-_wrapZone(callback(arg)) {
+// TODO(jacobr): remove these typedefs when dart:async supports generic types.
+typedef R _wrapZoneCallback<A, R>(A a);
+typedef R _wrapZoneBinaryCallback<A, B, R>(A a, B b);
+
+_wrapZoneCallback/*<A, R>*/ _wrapZone/*<A, R>*/(_wrapZoneCallback/*<A, R>*/ callback) {
   // For performance reasons avoid wrapping if we are in the root zone.
   if (Zone.current == Zone.ROOT) return callback;
   if (callback == null) return null;
-  return Zone.current.bindUnaryCallback(callback, runGuarded: true);
+  // TODO(jacobr): we cast to _wrapZoneCallback/*<A, R>*/ to hack around missing
+  // generic method support in zones.
+  return Zone.current.bindUnaryCallback(callback, runGuarded: true) as _wrapZoneCallback/*<A, R>*/;
 }
 
-_wrapBinaryZone(callback(arg1, arg2)) {
+_wrapZoneBinaryCallback/*<A, B, R>*/ _wrapBinaryZone/*<A, B, R>*/(_wrapZoneBinaryCallback/*<A, B, R>*/ callback) {
   if (Zone.current == Zone.ROOT) return callback;
   if (callback == null) return null;
-  return Zone.current.bindBinaryCallback(callback, runGuarded: true);
+  // We cast to _wrapZoneBinaryCallback/*<A, B, R>*/ to hack around missing
+  // generic method support in zones.
+  return Zone.current.bindBinaryCallback(callback, runGuarded: true) as _wrapZoneBinaryCallback/*<A, B, R>*/;
 }
 
 /**
diff --git a/tools/dom/templates/html/dart2js/impl_KeyboardEvent.darttemplate b/tools/dom/templates/html/dart2js/impl_KeyboardEvent.darttemplate
index bbd6aeb..0cea803 100644
--- a/tools/dom/templates/html/dart2js/impl_KeyboardEvent.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_KeyboardEvent.darttemplate
@@ -14,15 +14,15 @@
  */
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
 
-  /** 
-   * Programmatically create a KeyboardEvent. 
+  /**
+   * Programmatically create a KeyboardEvent.
    *
    * Due to browser differences, keyCode, charCode, or keyIdentifier values
    * cannot be specified in this base level constructor. This constructor
    * enables the user to programmatically create and dispatch a [KeyboardEvent],
    * but it will not contain any particular key content. For programmatically
    * creating keyboard events with specific key value contents, see the custom
-   * Event [KeyEvent]. 
+   * Event [KeyEvent].
    */
   factory $CLASSNAME(String type,
       {Window view, bool canBubble: true, bool cancelable: true,
@@ -31,7 +31,7 @@
     if (view == null) {
       view = window;
     }
-    final e = document._createEvent("KeyboardEvent");
+    KeyboardEvent e = document._createEvent("KeyboardEvent");
     e._initKeyboardEvent(type, canBubble, cancelable, view, "",
         keyLocation, ctrlKey, altKey, shiftKey, metaKey);
     return e;
diff --git a/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate b/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate
index 5d5d23a..8077fb0 100644
--- a/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate
@@ -14,7 +14,7 @@
     if (view == null) {
       view = window;
     }
-    var event = document._createEvent('MouseEvent');
+    MouseEvent event = document._createEvent('MouseEvent');
     event._initMouseEvent(type, canBubble, cancelable, view, detail,
         screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey,
         button, relatedTarget);
@@ -29,9 +29,9 @@
   @DomName('MouseEvent.movementX')
   @DomName('MouseEvent.movementY')
   @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @SupportedBrowser(SupportedBrowser.FIREFOX)
   @Experimental()
-  Point get movement => new Point(_webkitMovementX, _webkitMovementY);
+  Point get movement => new Point(_movementX, _movementY);
 
   /**
    * The coordinates of the mouse pointer in target node coordinates.
diff --git a/tools/dom/templates/html/dartium/impl_MouseEvent.darttemplate b/tools/dom/templates/html/dartium/impl_MouseEvent.darttemplate
index c4dc511..1b2bbc8 100644
--- a/tools/dom/templates/html/dartium/impl_MouseEvent.darttemplate
+++ b/tools/dom/templates/html/dartium/impl_MouseEvent.darttemplate
@@ -48,9 +48,9 @@
   @DomName('MouseEvent.movementX')
   @DomName('MouseEvent.movementY')
   @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @SupportedBrowser(SupportedBrowser.FIREFOX)
   @Experimental()
-  Point get movement => new Point(_webkitMovementX, _webkitMovementY);
+  Point get movement => new Point(_movementX, _movementY);
 
   /**
    * The coordinates of the mouse pointer in target node coordinates.
diff --git a/tools/dom/templates/html/impl/impl_CompositionEvent.darttemplate b/tools/dom/templates/html/impl/impl_CompositionEvent.darttemplate
index 83b13b2..5b3d391 100644
--- a/tools/dom/templates/html/impl/impl_CompositionEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_CompositionEvent.darttemplate
@@ -13,7 +13,7 @@
     if (view == null) {
       view = window;
     }
-    var e = document._createEvent("CompositionEvent");
+    CompositionEvent e = document._createEvent("CompositionEvent");
 
 $if DART2JS
     if (Device.isFirefox) {
diff --git a/tools/dom/templates/html/impl/impl_DeviceOrientationEvent.darttemplate b/tools/dom/templates/html/impl/impl_DeviceOrientationEvent.darttemplate
index 6f452c9..6b4a4f8 100644
--- a/tools/dom/templates/html/impl/impl_DeviceOrientationEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_DeviceOrientationEvent.darttemplate
@@ -9,7 +9,7 @@
   factory $CLASSNAME(String type,
       {bool canBubble: true, bool cancelable: true, num alpha: 0, num beta: 0,
       num gamma: 0, bool absolute: false}) {
-    var e = document._createEvent("DeviceOrientationEvent");
+    DeviceOrientationEvent e = document._createEvent("DeviceOrientationEvent");
     e._initDeviceOrientationEvent(type, canBubble, cancelable, alpha, beta,
         gamma, absolute);
     return e;
diff --git a/tools/dom/templates/html/impl/impl_Document.darttemplate b/tools/dom/templates/html/impl/impl_Document.darttemplate
index 9dae6c7..7c8a124 100644
--- a/tools/dom/templates/html/impl/impl_Document.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Document.darttemplate
@@ -25,9 +25,8 @@
    * For details about CSS selector syntax, see the
    * [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
    */
-  ElementList<Element> querySelectorAll(String selectors) {
-    return new _FrozenElementList._wrap(_querySelectorAll(selectors));
-  }
+  ElementList<Element /*=T*/> querySelectorAll/*<T extends Element>*/(String selectors) =>
+    new _FrozenElementList/*<T>*/._wrap(_querySelectorAll(selectors));
 
   /**
    * Alias for [querySelector]. Note this function is deprecated because its
@@ -45,7 +44,7 @@
   @deprecated
   @Experimental()
   @DomName('Document.querySelectorAll')
-  ElementList<Element> queryAll(String relativeSelectors) =>
+  ElementList<Element /*=T*/> queryAll/*<T extends Element>*/(String relativeSelectors) =>
       querySelectorAll(relativeSelectors);
 
   /// Checks if [registerElement] is supported on the current platform.
@@ -115,4 +114,17 @@
       => JS('TreeWalker', '#.createTreeWalker(#, #, #, false)',
           this, root, whatToShow, filter);
 $endif
+
+  @DomName('Document.visibilityState')
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.FIREFOX)
+  @SupportedBrowser(SupportedBrowser.IE, '10')
+  @Experimental()
+$if DART2JS
+  String get visibilityState => JS('String',
+    '(#.visibilityState || #.mozVisibilityState || #.msVisibilityState ||'
+      '#.webkitVisibilityState)', this, this, this, this);
+$else
+  String get visibilityState => _visibilityState;
+$endif
 }
diff --git a/tools/dom/templates/html/impl/impl_DocumentFragment.darttemplate b/tools/dom/templates/html/impl/impl_DocumentFragment.darttemplate
index dd4d70b..6627f0b 100644
--- a/tools/dom/templates/html/impl/impl_DocumentFragment.darttemplate
+++ b/tools/dom/templates/html/impl/impl_DocumentFragment.darttemplate
@@ -40,7 +40,7 @@
 
   set children(List<Element> value) {
     // Copy list first since we don't want liveness during iteration.
-    List copy = new List.from(value);
+    var copy = value.toList();
     var children = this.children;
     children.clear();
     children.addAll(copy);
@@ -57,8 +57,9 @@
    * For details about CSS selector syntax, see the
    * [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
    */
-  ElementList<Element> querySelectorAll(String selectors) =>
-    new _FrozenElementList._wrap(_querySelectorAll(selectors));
+  ElementList<Element /*=T*/> querySelectorAll/*<T extends Element>*/(String selectors) =>
+    new _FrozenElementList/*<T>*/._wrap(_querySelectorAll(selectors));
+
 
   String get innerHtml {
     final e = new Element.tag("div");
@@ -115,8 +116,7 @@
   @deprecated
   @Experimental()
   @DomName('DocumentFragment.querySelectorAll')
-  ElementList<Element> queryAll(String relativeSelectors) {
-    return querySelectorAll(relativeSelectors);
-  }
+  ElementList<Element /*=T*/> queryAll/*<T extends Element>*/(String relativeSelectors) =>
+    querySelectorAll(relativeSelectors);
 $!MEMBERS
 }
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 399e90d..c9ef54a 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -71,7 +71,7 @@
     _filter(test, true);
   }
 
-  void _filter(bool test(var element), bool retainMatching) {
+  void _filter(bool test(Element element), bool retainMatching) {
     var removed;
     if (retainMatching) {
       removed = _element.children.where((e) => !test(e));
@@ -264,8 +264,8 @@
 // declared to return `ElementList`.  This provides all the static analysis
 // benefit so there is no need for this class have a constrained type parameter.
 //
-class _FrozenElementList extends ListBase
-    implements ElementList, NodeListWrapper {
+class _FrozenElementList<E extends Element> extends ListBase<E>
+    implements ElementList<E>, NodeListWrapper {
   final List<Node> _nodeList;
 
 $if JSINTEROP
@@ -280,9 +280,9 @@
 
   int get length => _nodeList.length;
 
-  Element operator [](int index) => _nodeList[index];
+  E operator [](int index) => _downcast/*<Node, E>*/(_nodeList[index]);
 
-  void operator []=(int index, Element value) {
+  void operator []=(int index, E value) {
     throw new UnsupportedError('Cannot modify list');
   }
 
@@ -290,7 +290,7 @@
     throw new UnsupportedError('Cannot modify list');
   }
 
-  void sort([Comparator<Element> compare]) {
+  void sort([Comparator<E> compare]) {
     throw new UnsupportedError('Cannot sort list');
   }
 
@@ -298,11 +298,11 @@
     throw new UnsupportedError('Cannot shuffle list');
   }
 
-  Element get first => _nodeList.first;
+  E get first => _downcast/*<Node, E>*/(_nodeList.first);
 
-  Element get last => _nodeList.last;
+  E get last => _downcast/*<Node, E>*/(_nodeList.last);
 
-  Element get single => _nodeList.single;
+  E get single => _downcast/*<Node, E>*/(_nodeList.single);
 
   CssClassSet get classes => new _MultiElementCssClassSet(this);
 
@@ -316,7 +316,7 @@
     //
     // as the code below converts the Iterable[value] to a string multiple
     // times.  Maybe compute the string and set className here.
-    _nodeList.forEach((e) => e.classes = value);
+    forEach((e) => e.classes = value);
   }
 
   CssRect get contentEdge => new _ContentCssListRect(this);
@@ -593,7 +593,7 @@
 
   set children(List<Element> value) {
     // Copy list first since we don't want liveness during iteration.
-    List copy = new List.from(value);
+    var copy = value.toList();
     var children = this.children;
     children.clear();
     children.addAll(copy);
@@ -611,8 +611,8 @@
    * [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
    */
   @DomName('Element.querySelectorAll')
-  ElementList<Element> querySelectorAll(String selectors) =>
-    new _FrozenElementList._wrap(_querySelectorAll(selectors));
+  ElementList<Element /*=T*/> querySelectorAll/*<T extends Element>*/(String selectors) =>
+    new _FrozenElementList/*<T>*/._wrap(_querySelectorAll(selectors));
 
   /**
    * Alias for [querySelector]. Note this function is deprecated because its
@@ -630,7 +630,7 @@
   @deprecated
   @DomName('Element.querySelectorAll')
   @Experimental()
-  ElementList<Element> queryAll(String relativeSelectors) =>
+  ElementList<Element /*=T*/> queryAll/*<T extends Element>*/(String relativeSelectors) =>
       querySelectorAll(relativeSelectors);
 
   /**
@@ -828,19 +828,18 @@
       throw new ArgumentError("The frames parameter should be a List of Maps "
           "with frame information");
     }
-    var convertedFrames = frames;
-    if (convertedFrames is Iterable) {
+    var convertedFrames;
+    if (frames is Iterable) {
 $if DART2JS
       convertedFrames = frames.map(convertDartToNative_Dictionary).toList();
 $else
       convertedFrames = convertDartToNative_List(
           frames.map(convertDartToNative_Dictionary).toList());
 $endif
+    } else {
+      convertedFrames = frames;
     }
-    var convertedTiming = timing;
-    if (convertedTiming is Map) {
-      convertedTiming = convertDartToNative_Dictionary(convertedTiming);
-    }
+    var convertedTiming = timing is Map ? convertDartToNative_Dictionary(timing) : timing;
     return convertedTiming == null
       ? _animate(convertedFrames)
       : _animate(convertedFrames, convertedTiming);
@@ -1333,7 +1332,7 @@
 
       // Workaround for Safari bug. Was also previously Chrome bug 229142
       // - URIs are not resolved in new doc.
-      var base = _parseDocument.createElement('base');
+      BaseElement base = _parseDocument.createElement('base');
       base.href = document.baseUri;
       _parseDocument.head.append(base);
     }
diff --git a/tools/dom/templates/html/impl/impl_Event.darttemplate b/tools/dom/templates/html/impl/impl_Event.darttemplate
index e4c6e4e..9ff5f48 100644
--- a/tools/dom/templates/html/impl/impl_Event.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Event.darttemplate
@@ -33,7 +33,7 @@
     e._initEvent(name, canBubble, cancelable);
     return e;
   }
-  
+
   /** The CSS selector involved with event delegation. */
   String _selector;
 
@@ -47,8 +47,8 @@
       throw new UnsupportedError('Cannot call matchingTarget if this Event did'
           ' not arise as a result of event delegation.');
     }
-    var currentTarget = this.currentTarget;
-    var target = this.target;
+    Element currentTarget = this.currentTarget;
+    Element target = this.target;
     var matchedTarget;
     do {
       if (target.matches(_selector)) return target;
diff --git a/tools/dom/templates/html/impl/impl_EventTarget.darttemplate b/tools/dom/templates/html/impl/impl_EventTarget.darttemplate
index 61092fd..c6d74ef 100644
--- a/tools/dom/templates/html/impl/impl_EventTarget.darttemplate
+++ b/tools/dom/templates/html/impl/impl_EventTarget.darttemplate
@@ -52,26 +52,24 @@
 }
 
 class ElementEvents extends Events {
-  /* Raw event target. */
-  final Element _ptr;
   static final webkitEvents = {
-    'animationend' : 'webkitAnimationEnd', 
-    'animationiteration' : 'webkitAnimationIteration', 
-    'animationstart' : 'webkitAnimationStart', 
-    'fullscreenchange' : 'webkitfullscreenchange', 
+    'animationend' : 'webkitAnimationEnd',
+    'animationiteration' : 'webkitAnimationIteration',
+    'animationstart' : 'webkitAnimationStart',
+    'fullscreenchange' : 'webkitfullscreenchange',
     'fullscreenerror' : 'webkitfullscreenerror',
-    'keyadded' : 'webkitkeyadded', 
-    'keyerror' : 'webkitkeyerror', 
-    'keymessage' : 'webkitkeymessage', 
-    'needkey' : 'webkitneedkey', 
-    'pointerlockchange' : 'webkitpointerlockchange', 
-    'pointerlockerror' : 'webkitpointerlockerror', 
-    'resourcetimingbufferfull' : 'webkitresourcetimingbufferfull', 
+    'keyadded' : 'webkitkeyadded',
+    'keyerror' : 'webkitkeyerror',
+    'keymessage' : 'webkitkeymessage',
+    'needkey' : 'webkitneedkey',
+    'pointerlockchange' : 'webkitpointerlockchange',
+    'pointerlockerror' : 'webkitpointerlockerror',
+    'resourcetimingbufferfull' : 'webkitresourcetimingbufferfull',
     'transitionend': 'webkitTransitionEnd',
     'speechchange' : 'webkitSpeechChange'
   };
 
-  ElementEvents(Element ptr) : this._ptr = ptr, super(ptr);
+  ElementEvents(Element ptr) : super(ptr);
 
   Stream operator [](String type) {
     if (webkitEvents.keys.contains(type.toLowerCase())) {
diff --git a/tools/dom/templates/html/impl/impl_Geolocation.darttemplate b/tools/dom/templates/html/impl/impl_Geolocation.darttemplate
index 5518815..e1c84ac 100644
--- a/tools/dom/templates/html/impl/impl_Geolocation.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Geolocation.darttemplate
@@ -52,7 +52,10 @@
     }
 
     int watchId;
-    var controller;
+    // TODO(jacobr): it seems like a bug that we have to specifiy the static
+    // type here for controller.stream to have the right type.
+    // dartbug.com/26278
+    StreamController<Geoposition> controller;
     controller = new StreamController<Geoposition>(sync: true,
       onListen: () {
         assert(watchId == null);
diff --git a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
index 1264edc..4a95f9a 100644
--- a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
@@ -127,65 +127,6 @@
     _webkitExitFullscreen();
   }
 
-  /**
-   * Returns the element, if any, that is currently displayed in fullscreen.
-   *
-   * Returns null if there is currently no fullscreen element. You can use
-   * this to determine if the page is in fullscreen mode.
-   *
-   *     myVideo = new VideoElement();
-   *     if (document.fullscreenElement == null) {
-   *       myVideo.requestFullscreen();
-   *       print(document.fullscreenElement == myVideo); // true
-   *     }
-   *
-   * ## Other resources
-   *
-   * * [Using the fullscreen
-   *   API](http://docs.webplatform.org/wiki/tutorials/using_the_full-screen_api)
-   *   from WebPlatform.org.
-   * * [Fullscreen specification](http://www.w3.org/TR/fullscreen/) from W3C.
-   */
-  @DomName('Document.webkitFullscreenElement')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  Element get fullscreenElement => _webkitFullscreenElement;
-
-  /**
-   * Returns true if this document can display elements in fullscreen mode.
-   *
-   * ## Other resources
-   *
-   * * [Using the fullscreen
-   *   API](http://docs.webplatform.org/wiki/tutorials/using_the_full-screen_api)
-   *   from WebPlatform.org.
-   * * [Fullscreen specification](http://www.w3.org/TR/fullscreen/) from W3C.
-   */
-  @DomName('Document.webkitFullscreenEnabled')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  bool get fullscreenEnabled => _webkitFullscreenEnabled;
-
-  @DomName('Document.webkitHidden')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  bool get hidden => _webkitHidden;
-
-  @DomName('Document.visibilityState')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.FIREFOX)
-  @SupportedBrowser(SupportedBrowser.IE, '10')
-  @Experimental()
-$if DART2JS
-  String get visibilityState => JS('String',
-    '(#.visibilityState || #.mozVisibilityState || #.msVisibilityState ||'
-      '#.webkitVisibilityState)', this, this, this, this);
-$else
-  String get visibilityState => _webkitVisibilityState;
-$endif
 $if DARTIUM
 
   /**
diff --git a/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
index 4919649..e6ad32f 100644
--- a/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
@@ -28,7 +28,7 @@
     ButtonInputElement {
 
   factory InputElement({String type}) {
-    var e = document.createElement("input");
+    InputElement e = document.createElement("input");
     if (type != null) {
       try {
         // IE throws an exception for unknown types.
diff --git a/tools/dom/templates/html/impl/impl_HTMLSelectElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLSelectElement.darttemplate
index 25510dc..396ffcd 100644
--- a/tools/dom/templates/html/impl/impl_HTMLSelectElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLSelectElement.darttemplate
@@ -10,8 +10,7 @@
   // Override default options, since IE returns SelectElement itself and it
   // does not operate as a List.
   List<OptionElement> get options {
-    var options = this.querySelectorAll('option').where(
-        (e) => e is OptionElement).toList();
+    var options = new List<OptionElement>.from(this.querySelectorAll('option'));
     return new UnmodifiableListView(options);
   }
 
diff --git a/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate b/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
index 6218e29..b82020f 100644
--- a/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
@@ -49,14 +49,14 @@
 
   @DomName('IDBFactory.deleteDatabase')
   Future<IdbFactory> deleteDatabase(String name,
-      {void onBlocked(Event)}) {
+      {void onBlocked(Event e)}) {
     try {
       var request = _deleteDatabase(name);
 
       if (onBlocked != null) {
         request.onBlocked.listen(onBlocked);
       }
-      var completer = new Completer.sync();
+      var completer = new Completer<IdbFactory>.sync();
       request.onSuccess.listen((e) {
         completer.complete(this);
       });
@@ -100,12 +100,13 @@
  * Ties a request to a completer, so the completer is completed when it succeeds
  * and errors out when the request errors.
  */
-Future _completeRequest(Request request) {
-  var completer = new Completer.sync();
+Future/*<T>*/ _completeRequest/*<T>*/(Request request) {
+  var completer = new Completer/*<T>*/.sync();
   // TODO: make sure that completer.complete is synchronous as transactions
   // may be committed if the result is not processed immediately.
   request.onSuccess.listen((e) {
-    completer.complete(request.result);
+    var result = _cast/*<T>*/(request.result);
+    completer.complete(result);
   });
   request.onError.listen(completer.completeError);
   return completer.future;
diff --git a/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate b/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
index 1363056..4c74806 100644
--- a/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
@@ -137,18 +137,18 @@
   /**
    * Helper for iterating over cursors in a request.
    */
-  static Stream<Cursor> _cursorStreamFromResult(Request request,
+  static Stream/*<T>*/ _cursorStreamFromResult/*<T extends Cursor>*/(Request request,
       bool autoAdvance) {
     // TODO: need to guarantee that the controller provides the values
     // immediately as waiting until the next tick will cause the transaction to
     // close.
-    var controller = new StreamController(sync: true);
+    var controller = new StreamController/*<T>*/(sync: true);
 
     //TODO: Report stacktrace once issue 4061 is resolved.
     request.onError.listen(controller.addError);
 
     request.onSuccess.listen((e) {
-      Cursor cursor = request.result;
+      var cursor = _cast/*<T>*/(request.result);
       if (cursor == null) {
         controller.close();
       } else {
@@ -161,3 +161,6 @@
     return controller.stream;
   }
 }
+
+// ignore: STRONG_MODE_DOWN_CAST_COMPOSITE
+/*=To*/ _cast/*<To>*/(dynamic x) => x;
diff --git a/tools/dom/templates/html/impl/impl_MessageEvent.darttemplate b/tools/dom/templates/html/impl/impl_MessageEvent.darttemplate
index 1b13a76..3018eb1 100644
--- a/tools/dom/templates/html/impl/impl_MessageEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_MessageEvent.darttemplate
@@ -10,7 +10,7 @@
   factory $CLASSNAME(String type,
       {bool canBubble: false, bool cancelable: false, Object data,
       String origin, String lastEventId,
-      Window source, List messagePorts}) {
+      Window source, List<MessagePort> messagePorts}) {
     if (source == null) {
       source = window;
     }
@@ -22,7 +22,7 @@
           messagePorts);
     }
 $endif
-    var event = document._createEvent("MessageEvent");
+    MessageEvent event = document._createEvent("MessageEvent");
     event._initMessageEvent(type, canBubble, cancelable, data, origin,
         lastEventId, source, messagePorts);
     return event;
diff --git a/tools/dom/templates/html/impl/impl_MutationEvent.darttemplate b/tools/dom/templates/html/impl/impl_MutationEvent.darttemplate
deleted file mode 100644
index c4a30c6..0000000
--- a/tools/dom/templates/html/impl/impl_MutationEvent.darttemplate
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of $LIBRARYNAME;
-
-$(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
-  factory $CLASSNAME(String type,
-      {bool canBubble: false, bool cancelable: false, Node relatedNode,
-      String prevValue, String newValue, String attrName, int attrChange: 0}) {
-
-    var event = document._createEvent('MutationEvent');
-    event._initMutationEvent(type, canBubble, cancelable, relatedNode,
-        prevValue, newValue, attrName, attrChange);
-    return event;
-  }
-$!MEMBERS
-}
diff --git a/tools/dom/templates/html/impl/impl_Node.darttemplate b/tools/dom/templates/html/impl/impl_Node.darttemplate
index 4362733..27c8e49 100644
--- a/tools/dom/templates/html/impl/impl_Node.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Node.darttemplate
@@ -213,7 +213,7 @@
   set nodes(Iterable<Node> value) {
     // Copy list first since we don't want liveness during iteration.
     // TODO(jacobr): there is a better way to do this.
-    List copy = new List.from(value);
+    var copy = value.toList();
     text = '';
     for (Node node in copy) {
       append(node);
diff --git a/tools/dom/templates/html/impl/impl_Storage.darttemplate b/tools/dom/templates/html/impl/impl_Storage.darttemplate
index ff99d70..609355e 100644
--- a/tools/dom/templates/html/impl/impl_Storage.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Storage.darttemplate
@@ -37,11 +37,11 @@
   }
 
   // TODO(nweiz): update this when maps support lazy iteration
-  bool containsValue(String value) => values.any((e) => e == value);
+  bool containsValue(Object value) => values.any((e) => e == value);
 
-  bool containsKey(String key) => _getItem(key) != null;
+  bool containsKey(Object key) => _getItem(key) != null;
 
-  String operator [](String key) => _getItem(key);
+  String operator [](Object key) => _getItem(key);
 
   void operator []=(String key, String value) { _setItem(key, value); }
 
@@ -50,7 +50,7 @@
     return this[key];
   }
 
-  String remove(String key) {
+  String remove(Object key) {
     final value = this[key];
     _removeItem(key);
     return value;
@@ -68,13 +68,13 @@
   }
 
   Iterable<String> get keys {
-    final keys = [];
+    final keys = <String>[];
     forEach((k, v) => keys.add(k));
     return keys;
   }
 
   Iterable<String> get values {
-    final values = [];
+    final values = <String>[];
     forEach((k, v) => values.add(v));
     return values;
   }
diff --git a/tools/dom/templates/html/impl/impl_StorageEvent.darttemplate b/tools/dom/templates/html/impl/impl_StorageEvent.darttemplate
index 9d546b3..551e2c7 100644
--- a/tools/dom/templates/html/impl/impl_StorageEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_StorageEvent.darttemplate
@@ -11,7 +11,7 @@
     {bool canBubble: false, bool cancelable: false, String key, String oldValue,
     String newValue, String url, Storage storageArea}) {
 
-    var e = document._createEvent("StorageEvent");
+    StorageEvent e = document._createEvent("StorageEvent");
     e._initStorageEvent(type, canBubble, cancelable, key, oldValue,
         newValue, url, storageArea);
     return e;
diff --git a/tools/dom/templates/html/impl/impl_TextEvent.darttemplate b/tools/dom/templates/html/impl/impl_TextEvent.darttemplate
index e12cc8b..148c718 100644
--- a/tools/dom/templates/html/impl/impl_TextEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_TextEvent.darttemplate
@@ -12,7 +12,7 @@
     if (view == null) {
       view = window;
     }
-    var e = document._createEvent("TextEvent");
+    TextEvent e = document._createEvent("TextEvent");
     e._initTextEvent(type, canBubble, cancelable, view, data);
     return e;
   }
diff --git a/tools/dom/templates/html/impl/impl_TouchEvent.darttemplate b/tools/dom/templates/html/impl/impl_TouchEvent.darttemplate
index 3ee2462..3fa5e27 100644
--- a/tools/dom/templates/html/impl/impl_TouchEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_TouchEvent.darttemplate
@@ -15,7 +15,7 @@
     if (view == null) {
       view = window;
     }
-    var e = document._createEvent("TouchEvent");
+    TouchEvent e = document._createEvent("TouchEvent");
     e._initTouchEvent(touches, targetTouches, changedTouches, type, view,
         screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey);
     return e;
diff --git a/tools/dom/templates/html/impl/impl_UIEvent.darttemplate b/tools/dom/templates/html/impl/impl_UIEvent.darttemplate
index 5894720..405d06d 100644
--- a/tools/dom/templates/html/impl/impl_UIEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_UIEvent.darttemplate
@@ -19,7 +19,7 @@
     if (view == null) {
       view = window;
     }
-    final e = document._createEvent("UIEvent");
+    UIEvent e = document._createEvent("UIEvent");
     e._initUIEvent(type, canBubble, cancelable, view, detail);
     return e;
   }
diff --git a/tools/dom/templates/html/impl/impl_Window.darttemplate b/tools/dom/templates/html/impl/impl_Window.darttemplate
index 521fd00..c9f8279 100644
--- a/tools/dom/templates/html/impl/impl_Window.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Window.darttemplate
@@ -115,7 +115,7 @@
   @DomName('Window.requestAnimationFrame')
   int requestAnimationFrame(FrameRequestCallback callback) {
     _ensureRequestAnimationFrame();
-    return _requestAnimationFrame(_wrapZone(callback));
+    return _requestAnimationFrame(_wrapZone/*<num, dynamic>*/(callback));
   }
 
   /**
@@ -341,12 +341,11 @@
   Stream<BeforeUnloadEvent> forTarget(EventTarget e, {bool useCapture: false}) {
     var stream = new _EventStream(e, _eventType, useCapture);
 $if DART2JS
-    var controller = new StreamController(sync: true);
+    var controller = new StreamController<BeforeUnloadEvent>(sync: true);
 
     stream.listen((event) {
       var wrapped = new _BeforeUnloadEvent(event);
       controller.add(wrapped);
-      return wrapped.returnValue;
     });
 
     return controller.stream;
diff --git a/tools/gyp/configurations.gypi b/tools/gyp/configurations.gypi
index 6a4b796..e5ab11a 100644
--- a/tools/gyp/configurations.gypi
+++ b/tools/gyp/configurations.gypi
@@ -26,6 +26,8 @@
       ['"<(target_arch)"=="simarm64"', { 'dart_target_arch': 'SIMARM64', }],
       ['"<(target_arch)"=="mips"', { 'dart_target_arch': 'MIPS', }],
       ['"<(target_arch)"=="simmips"', { 'dart_target_arch': 'SIMMIPS', }],
+      ['"<(target_arch)"=="simdbc"', { 'dart_target_arch': 'SIMDBC', }],
+      ['"<(target_arch)"=="simdbc64"', { 'dart_target_arch': 'SIMDBC64', }],
       [ 'OS=="linux"', { 'dart_target_os': 'Linux', } ],
       [ 'OS=="mac"', { 'dart_target_os': 'Macos', } ],
       [ 'OS=="win"', { 'dart_target_os': 'Win', } ],
@@ -132,6 +134,14 @@
         ],
       },
 
+      'Dart_simdbc_Base': {
+        'abstract': 1,
+        'defines': [
+          'TARGET_ARCH_DBC',
+          'USING_SIMULATOR',
+        ]
+      },
+
       'Dart_Debug': {
         'abstract': 1,
       },
@@ -356,6 +366,47 @@
         ],
       },
 
+      'DebugSIMDBC': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_simdbc_Base', 'Dart_Debug',
+          'Dart_<(dart_target_os)_Base',
+          'Dart_<(dart_target_os)_simdbc_Base',
+          'Dart_<(dart_target_os)_Debug',
+        ],
+        'defines': [
+          'DEBUG',
+        ],
+      },
+
+      'ReleaseSIMDBC': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_simdbc_Base', 'Dart_Release',
+          'Dart_<(dart_target_os)_Base',
+          'Dart_<(dart_target_os)_simdbc_Base',
+          'Dart_<(dart_target_os)_Release',
+        ],
+      },
+
+      'DebugSIMDBC64': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_simdbc_Base', 'Dart_Debug',
+          'Dart_<(dart_target_os)_Base',
+          'Dart_<(dart_target_os)_simdbc64_Base',
+          'Dart_<(dart_target_os)_Debug',
+        ],
+        'defines': [
+          'DEBUG',
+        ],
+      },
+
+      'ReleaseSIMDBC64': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_simdbc_Base', 'Dart_Release',
+          'Dart_<(dart_target_os)_Base',
+          'Dart_<(dart_target_os)_simdbc64_Base',
+          'Dart_<(dart_target_os)_Release',
+        ],
+      },
 
       # ARM and MIPS hardware configurations are only for Linux and Android.
       'DebugXARM': {
@@ -741,6 +792,52 @@
         ],
       },
 
+      'DebugAndroidSIMDBC': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_simdbc_Base', 'Dart_Debug',
+          'Dart_Android_Base',
+          # Default SIMDBC on Android targets arm.
+          'Dart_Android_arm_Base',
+          'Dart_Android_Debug',
+        ],
+        'defines': [
+          'DEBUG',
+        ],
+      },
+
+      'ReleaseAndroidSIMDBC': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_simdbc_Base', 'Dart_Release',
+          'Dart_Android_Base',
+          # Default SIMDBC on Android targets arm.
+          'Dart_Android_arm_Base',
+          'Dart_Android_Release',
+        ],
+      },
+
+      'DebugAndroidSIMDBC64': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_simdbc_Base', 'Dart_Debug',
+          'Dart_Android_Base',
+          # Default SIMDBC on Android targets arm64.
+          'Dart_Android_arm64_Base',
+          'Dart_Android_Debug',
+        ],
+        'defines': [
+          'DEBUG',
+        ],
+      },
+
+      'ReleaseAndroidSIMDBC64': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_simdbc_Base', 'Dart_Release',
+          'Dart_Android_Base',
+          # Default SIMDBC on Android targets arm64.
+          'Dart_Android_arm64_Base',
+          'Dart_Android_Release',
+        ],
+      },
+
       # These targets assume that target_arch is passed in explicitly
       # by the containing project (e.g., chromium).
       'Debug': {
diff --git a/tools/gyp/configurations_make.gypi b/tools/gyp/configurations_make.gypi
index 98d28fa..05292bf 100644
--- a/tools/gyp/configurations_make.gypi
+++ b/tools/gyp/configurations_make.gypi
@@ -113,6 +113,18 @@
         ],
       },
 
+      'Dart_Linux_simdbc_Base': {
+        'abstract': 1,
+        'cflags': [ '-O3', '-m32', '-msse2', '-mfpmath=sse' ],
+        'ldflags': [ '-m32', ],
+      },
+
+      'Dart_Linux_simdbc64_Base': {
+        'abstract': 1,
+        'cflags': [ '-O3', '-m64', '-msse2', '-mfpmath=sse' ],
+        'ldflags': [ '-m64', ],
+      },
+
       # ARM cross-build
       'Dart_Linux_xarm_Base': {
         'abstract': 1,
diff --git a/tools/gyp/configurations_msvs.gypi b/tools/gyp/configurations_msvs.gypi
index 3650127..adcc1d4 100644
--- a/tools/gyp/configurations_msvs.gypi
+++ b/tools/gyp/configurations_msvs.gypi
@@ -36,6 +36,12 @@
       'Dart_Win_simmips_Base': {
         'abstract': 1,
       },
+      'Dart_Win_simdbc_Base': {
+        'abstract': 1,
+      },
+      'Dart_Win_simdbc64_Base': {
+        'abstract': 1,
+      },
       'Dart_Win_Debug': {
         'abstract': 1,
         'msvs_settings': {
diff --git a/tools/gyp/configurations_xcode.gypi b/tools/gyp/configurations_xcode.gypi
index 367f8f2..e9a68f6 100644
--- a/tools/gyp/configurations_xcode.gypi
+++ b/tools/gyp/configurations_xcode.gypi
@@ -77,6 +77,12 @@
       'Dart_Macos_simmips_Base': {
         'abstract': 1,
       },
+      'Dart_Macos_simdbc_Base': {
+        'abstract': 1,
+      },
+      'Dart_Macos_simdbc64_Base': {
+        'abstract': 1,
+      },
       'Dart_Macos_Debug': {
         'abstract': 1,
         'xcode_settings': {
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 147cd99..161252a 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -52,6 +52,7 @@
     bool useSdk = configuration['use_sdk'];
     bool isCsp = configuration['csp'];
     bool useCps = configuration['cps_ir'];
+    bool useBlobs = configuration['use_blobs'];
 
     switch (compiler) {
       case 'dart2analyzer':
@@ -77,7 +78,8 @@
         return new PrecompilerCompilerConfiguration(
             isDebug: isDebug,
             isChecked: isChecked,
-            arch: configuration['arch']);
+            arch: configuration['arch'],
+            useBlobs: useBlobs);
       case 'none':
         return new NoneCompilerConfiguration(
             isDebug: isDebug,
@@ -299,10 +301,12 @@
 
 class PrecompilerCompilerConfiguration extends CompilerConfiguration {
   final String arch;
+  final bool useBlobs;
 
-  PrecompilerCompilerConfiguration({bool isDebug, bool isChecked, String arch})
+  PrecompilerCompilerConfiguration({bool isDebug, bool isChecked, String arch, bool useBlobs})
       : super._subclass(isDebug: isDebug, isChecked: isChecked),
-        arch = arch;
+        arch = arch,
+        useBlobs = useBlobs;
 
   int computeTimeoutMultiplier() {
     int multiplier = 2;
@@ -317,14 +321,16 @@
       CommandBuilder commandBuilder,
       List arguments,
       Map<String, String> environmentOverrides) {
-    return new CommandArtifact(<Command>[
-      this.computeCompilationCommand(tempDir, buildDir, CommandBuilder.instance,
-          arguments, environmentOverrides),
-      this.computeAssembleCommand(tempDir, buildDir, CommandBuilder.instance,
-          arguments, environmentOverrides),
-      this.computeRemoveAssemblyCommand(tempDir, buildDir,
-          CommandBuilder.instance, arguments, environmentOverrides)
-    ], '$tempDir', 'application/dart-precompiled');
+    var commands = new List<Command>();
+    commands.add(this.computeCompilationCommand(tempDir, buildDir, CommandBuilder.instance,
+          arguments, environmentOverrides));
+    if (!useBlobs) {
+      commands.add(this.computeAssembleCommand(tempDir, buildDir, CommandBuilder.instance,
+          arguments, environmentOverrides));
+      commands.add(this.computeRemoveAssemblyCommand(tempDir, buildDir,
+          CommandBuilder.instance, arguments, environmentOverrides));
+    }
+    return new CommandArtifact(commands, '$tempDir', 'application/dart-precompiled');
   }
 
   CompilationCommand computeCompilationCommand(
@@ -336,6 +342,9 @@
     var exec = "$buildDir/dart_bootstrap";
     var args = new List();
     args.add("--gen-precompiled-snapshot=$tempDir");
+    if (useBlobs) {
+      args.add("--use_blobs");
+    }
     args.addAll(arguments);
 
     return commandBuilder.getCompilationCommand('precompiler', tempDir, !useSdk,
diff --git a/tools/testing/dart/runtime_configuration.dart b/tools/testing/dart/runtime_configuration.dart
index 8766322..7191342 100644
--- a/tools/testing/dart/runtime_configuration.dart
+++ b/tools/testing/dart/runtime_configuration.dart
@@ -19,6 +19,8 @@
   // [RuntimeConfiguration] in [configuration] there.
   factory RuntimeConfiguration(Map configuration) {
     String runtime = configuration['runtime'];
+    bool useBlobs = configuration['use_blobs'];
+
     switch (runtime) {
       case 'ContentShellOnAndroid':
       case 'DartiumOnAndroid':
@@ -52,7 +54,7 @@
         return new DartProductRuntimeConfiguration();
 
       case 'dart_precompiled':
-        return new DartPrecompiledRuntimeConfiguration();
+        return new DartPrecompiledRuntimeConfiguration(useBlobs: useBlobs);
 
       case 'drt':
         return new DrtRuntimeConfiguration();
@@ -171,6 +173,8 @@
       case 'simmips':
       case 'mips':
       case 'simarm64':
+      case 'simdbc':
+      case 'simdbc64':
         multiplier *= 4;
         break;
     }
@@ -235,13 +239,16 @@
     augmentedArgs.addAll(arguments);
 
     return <Command>[
-      commandBuilder.getVmCommand(suite.dartVmProductBinaryFileName,
+      commandBuilder.getVmCommand(suite.dartVmBinaryFileName,
           augmentedArgs, environmentOverrides)
     ];
   }
 }
 
 class DartPrecompiledRuntimeConfiguration extends DartVmRuntimeConfiguration {
+  final bool useBlobs;
+  DartPrecompiledRuntimeConfiguration({bool useBlobs}) : useBlobs = useBlobs;
+
   List<Command> computeRuntimeCommands(
       TestSuite suite,
       CommandBuilder commandBuilder,
@@ -256,6 +263,9 @@
 
     var augmentedArgs = new List();
     augmentedArgs.add("--run-precompiled-snapshot=${artifact.filename}");
+    if (useBlobs) {
+      augmentedArgs.add("--use_blobs");
+    }
     augmentedArgs.addAll(arguments);
 
     return <Command>[
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index 9cbd3c2..d4849a4 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -148,7 +148,9 @@
             'simarmv6',
             'simarmv5te',
             'simarm64',
-            'simmips'
+            'simmips',
+            'simdbc',
+            'simdbc64',
           ],
           'x64'),
       new _TestOptionSpecification(
@@ -184,6 +186,9 @@
           'noopt', 'Run an in-place precompilation', ['--noopt'], [], false,
           type: 'bool'),
       new _TestOptionSpecification(
+          'use_blobs', 'Use mmap instead of shared libraries for precompilation', ['--use-blobs'], [], false,
+          type: 'bool'),
+      new _TestOptionSpecification(
           'timeout', 'Timeout in seconds', ['-t', '--timeout'], [], -1,
           type: 'int'),
       new _TestOptionSpecification(
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index d288da8..dbab65e 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -234,21 +234,6 @@
     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');
diff --git a/tools/utils.py b/tools/utils.py
index 6965a1c..02fe8ef 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -240,6 +240,8 @@
   'simarmv5te': 'ia32',
   'simmips': 'ia32',
   'simarm64': 'ia32',
+  'simdbc': 'ia32',
+  'simdbc64': 'ia32',
 }
 
 ARCH_GUESS = GuessArchitecture()