Version 1.16.0-dev.2.0

Merge commit '3b2a695d71057f3a538f79f48a96f6bdca2474bb' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 863e8d6..10c8136 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,15 @@
     for (int n in <String>["a", "b"]) { ... }
     ```
 
+### Tool Changes
+
+* Pub
+  * `pub serve` now provides caching headers that should improve the performance
+    of requesting large files multiple times.
+
+  * Both `pub get` and `pub upgrade` now have a `--no-precompile` flag that
+    disables precompilation of executables and transformed dependencies.
+
 ## 1.15.0 - 2016-03-09
 
 ### Core library changes
diff --git a/DEPS b/DEPS
index 9ed1e3a..8e35a96 100644
--- a/DEPS
+++ b/DEPS
@@ -21,14 +21,18 @@
   "github_mirror":
       "https://chromium.googlesource.com/external/github.com/dart-lang/%s.git",
 
+  # Only use this temporarily while waiting for a mirror for a new package.
+  "github_dartlang": "https://github.com/dart-lang/%s.git",
+
   "gyp_rev": "@6ee91ad8659871916f9aa840d42e1513befdf638",
   "co19_rev": "@3ed795ea02e022ef19c77cf1b6095b7c8f5584d0",
   "chromium_git": "https://chromium.googlesource.com",
 
   # Revisions of /third_party/* dependencies.
-  "args_tag": "@0.13.0",
-  "async_tag": "@1.4.0",
+  "args_tag": "@0.13.4",
+  "async_tag": "@1.9.0",
   "barback_tag" : "@0.15.2+7",
+  "boolean_selector_tag" : "@1.0.0",
   "boringssl_rev" : "@daeafc22c66ad48f6b32fc8d3362eb9ba31b774e",
   "charcode_tag": "@1.1.0",
   "chrome_rev" : "@19997",
@@ -41,7 +45,7 @@
   "dartdoc_tag" : "@v0.9.0",
   "dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
   "dart_style_tag": "@0.2.4",
-  "dev_compiler_rev": "@0.1.9",
+  "dev_compiler_rev": "@0c5dd2d1e999c421d978a478e267aac6279e087a",
   "glob_rev": "@704cf75e4f26b417505c5c611bdaacd8808467dd",
   "html_tag" : "@0.12.1+1",
   "http_tag" : "@0.11.3+3",
@@ -51,7 +55,7 @@
   "idl_parser_rev": "@7fbe68cab90c38147dee4f48c30ad0d496c17915",
   "intl_rev": "@a8b480b9c436f6c0ec16730804c914bdb4e30d53",
   "jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
-  "json_rpc_2_tag": "@1.1.1",
+  "json_rpc_2_tag": "@2.0.0",
   "linter_rev": "@a60289545b34ab1f047a0a3f0673a4c5abde0eaf",
   "logging_rev": "@85d83e002670545e9039ad3985f0018ab640e597",
   "markdown_rev": "@4aaadf3d940bb172e1f6285af4d2b1710d309982",
@@ -67,31 +71,34 @@
   "ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
   "plugin_tag": "@0.1.0",
   "pool_tag": "@1.2.1",
-  "pub_rev": "@bd5c77abcb609d95340632b96344b59035e70376",
+  "pub_rev": "@c1405b945c6d818c8cfe78334e8d4b11fd913103",
   "pub_cache_tag": "@v0.1.0",
   "pub_semver_tag": "@1.2.1",
   "quiver_tag": "@0.21.4",
   "resource_rev":"@a49101ba2deb29c728acba6fb86000a8f730f4b1",
   "root_certificates_rev": "@c3a41df63afacec62fcb8135196177e35fe72f71",
-  "scheduled_test_tag": "@0.12.4+2",
-  "shelf_tag": "@0.6.4+3",
+  "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_web_socket_tag": "@0.0.1+4",
+  "shelf_web_socket_tag": "@0.2.0",
   "source_map_stack_trace_tag": "@1.0.4",
   "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.6+1",
+  "test_tag": "@0.12.12",
   "test_reflective_loader_tag": "@0.0.3",
+  "typed_data_tag": "@1.1.2",
   "utf_rev": "@1f55027068759e2d52f2c12de6a57cce5f3c5ee6",
   "usage_rev": "@b5080dac0d26a5609b266f8fdb0d053bc4c1c638",
   "watcher_tag": "@0.9.7",
   "when_tag": "@0.2.0+2",
   "which_tag": "@0.1.3+1",
   "web_components_rev": "@0e636b534d9b12c9e96f841e6679398e91a986ec",
+  "web_socket_channel_tag": "@1.0.0",
   "WebCore_rev": "@a86fe28efadcfc781f836037a80f27e22a5dad17",
   "yaml_tag": "@2.1.5",
   "zlib_rev": "@c3d0a6190f2f8c924a05ab6cc97b8f975bddd33f",
@@ -142,6 +149,9 @@
       (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/boolean_selector":
+      (Var("github_dartlang") % "boolean_selector") +
+      Var("boolean_selector_tag"),
   Var("dart_root") + "/third_party/pkg/charcode":
       (Var("github_mirror") % "charcode") + Var("charcode_tag"),
   Var("dart_root") + "/third_party/pkg/cli_util":
@@ -247,6 +257,9 @@
       Var("source_map_stack_trace_tag"),
   Var("dart_root") + "/third_party/pkg/stack_trace":
       (Var("github_mirror") % "stack_trace") + Var("stack_trace_tag"),
+  Var("dart_root") + "/third_party/pkg/stream_channel":
+      (Var("github_dartlang") % "stream_channel") +
+      Var("stream_channel_tag"),
   Var("dart_root") + "/third_party/pkg/string_scanner":
       (Var("github_mirror") % "string_scanner") +
       Var("string_scanner_tag"),
@@ -258,6 +271,8 @@
   Var("dart_root") + "/third_party/pkg/test_reflective_loader":
       (Var("github_mirror") % "test_reflective_loader") +
       Var("test_reflective_loader_tag"),
+  Var("dart_root") + "/third_party/pkg/typed_data":
+      (Var("github_dartlang") % "typed_data") + Var("typed_data_tag"),
   Var("dart_root") + "/third_party/pkg/usage":
       (Var("github_mirror") % "usage") + Var("usage_rev"),
   Var("dart_root") + "/third_party/pkg/utf":
@@ -267,6 +282,9 @@
   Var("dart_root") + "/third_party/pkg/web_components":
       (Var("github_mirror") % "web-components") +
       Var("web_components_rev"),
+  Var("dart_root") + "/third_party/pkg/web_socket_channel":
+      (Var("github_dartlang") % "web_socket_channel") +
+      Var("web_socket_channel_tag"),
   Var("dart_root") + "/third_party/pkg/when":
       (Var("github_mirror") % "when") + Var("when_tag"),
   Var("dart_root") + "/third_party/pkg/which":
diff --git a/create_sdk.gyp b/create_sdk.gyp
index b13adda..83ddc47 100644
--- a/create_sdk.gyp
+++ b/create_sdk.gyp
@@ -15,6 +15,7 @@
         'utils/dartdoc/dartdoc.gyp:dartdoc',
         'utils/analysis_server/analysis_server.gyp:analysis_server',
         'utils/dartanalyzer/dartanalyzer.gyp:dartanalyzer',
+        'utils/dartdevc/dartdevc.gyp:dartdevc',
       ],
       'actions': [
         {
@@ -38,6 +39,7 @@
             '<(SHARED_INTERMEDIATE_DIR)/utils_wrapper.dart.snapshot',
             '<(SHARED_INTERMEDIATE_DIR)/pub.dart.snapshot',
             '<(SHARED_INTERMEDIATE_DIR)/dartanalyzer.dart.snapshot',
+            '<(SHARED_INTERMEDIATE_DIR)/dartdevc.dart.snapshot',
             '<(SHARED_INTERMEDIATE_DIR)/dartfmt.dart.snapshot',
             '<(SHARED_INTERMEDIATE_DIR)/analysis_server.dart.snapshot',
             '<(SHARED_INTERMEDIATE_DIR)/dartdoc.dart.snapshot',
diff --git a/dart.gyp b/dart.gyp
index 9ac4105..b8d3e43f 100644
--- a/dart.gyp
+++ b/dart.gyp
@@ -12,6 +12,7 @@
         'create_sdk',
         'dart2js',
         'dartanalyzer',
+        'dartdevc',
         'packages',
         'runtime',
         'samples',
@@ -58,6 +59,13 @@
       ],
     },
     {
+      'target_name': 'dartdevc',
+      'type': 'none',
+      'dependencies': [
+        'utils/dartdevc/dartdevc.gyp:dartdevc',
+      ],
+    },
+    {
       'target_name': 'dartfmt',
       'type': 'none',
       'dependencies': [
diff --git a/pkg/analysis_server/lib/src/computer/computer_hover.dart b/pkg/analysis_server/lib/src/computer/computer_hover.dart
index 19ae943..33b5941 100644
--- a/pkg/analysis_server/lib/src/computer/computer_hover.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_hover.dart
@@ -10,6 +10,7 @@
 import 'package:analysis_server/src/utilities/documentation.dart';
 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/dart/ast/utilities.dart';
 
 /**
@@ -76,10 +77,26 @@
       // parameter
       hover.parameter = _safeToString(expression.bestParameterElement);
       // types
-      if (element == null || element is VariableElement) {
-        hover.staticType = _safeToString(expression.staticType);
+      {
+        AstNode parent = expression.parent;
+        DartType staticType = null;
+        DartType propagatedType = expression.propagatedType;
+        if (element == null || element is VariableElement) {
+          staticType = expression.staticType;
+        }
+        if (parent is MethodInvocation && parent.methodName == expression) {
+          staticType = parent.staticInvokeType;
+          propagatedType = parent.propagatedInvokeType;
+          if (staticType != null && staticType.isDynamic) {
+            staticType = null;
+          }
+          if (propagatedType != null && propagatedType.isDynamic) {
+            propagatedType = null;
+          }
+        }
+        hover.staticType = _safeToString(staticType);
+        hover.propagatedType = _safeToString(propagatedType);
       }
-      hover.propagatedType = _safeToString(expression.propagatedType);
       // done
       return hover;
     }
diff --git a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
index e978eb4..7a7a870 100644
--- a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
@@ -127,21 +127,21 @@
     }
     computer._addRegionForNode(node.constructorName, element);
     // arguments
-    _safelyVisit(node.arguments);
+    node.arguments?.accept(this);
   }
 
   @override
   visitAssignmentExpression(AssignmentExpression node) {
-    _safelyVisit(node.leftHandSide);
+    node.leftHandSide?.accept(this);
     computer._addRegionForToken(node.operator, node.bestElement);
-    _safelyVisit(node.rightHandSide);
+    node.rightHandSide?.accept(this);
   }
 
   @override
   visitBinaryExpression(BinaryExpression node) {
-    _safelyVisit(node.leftOperand);
+    node.leftOperand?.accept(this);
     computer._addRegionForToken(node.operator, node.bestElement);
-    _safelyVisit(node.rightOperand);
+    node.rightOperand?.accept(this);
   }
 
   @override
@@ -255,7 +255,7 @@
     computer._addRegionForToken(node.thisKeyword, element);
     computer._addRegionForNode(node.constructorName, element);
     // process arguments
-    _safelyVisit(node.argumentList);
+    node.argumentList?.accept(this);
   }
 
   @override
@@ -277,7 +277,7 @@
     computer._addRegionForToken(node.superKeyword, element);
     computer._addRegionForNode(node.constructorName, element);
     // process arguments
-    _safelyVisit(node.argumentList);
+    node.argumentList?.accept(this);
   }
 
   void _addConstructorName(AstNode parent, ConstructorName node) {
@@ -324,10 +324,4 @@
       }
     }
   }
-
-  void _safelyVisit(AstNode node) {
-    if (node != null) {
-      node.accept(this);
-    }
-  }
 }
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 7db68b6..c053754 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -375,6 +375,22 @@
 
     _initIncrementalLogger(results[INCREMENTAL_RESOLUTION_LOG]);
 
+    //
+    // Process all of the plugins so that extensions are registered.
+    //
+    ServerPlugin serverPlugin = new ServerPlugin();
+    List<Plugin> plugins = <Plugin>[];
+    plugins.addAll(AnalysisEngine.instance.requiredPlugins);
+    plugins.add(AnalysisEngine.instance.commandLinePlugin);
+    plugins.add(AnalysisEngine.instance.optionsPlugin);
+    plugins.add(serverPlugin);
+    plugins.add(linterPlugin);
+    plugins.add(linterServerPlugin);
+    plugins.add(dartCompletionPlugin);
+    plugins.addAll(_userDefinedPlugins);
+    ExtensionManager manager = new ExtensionManager();
+    manager.processPlugins(plugins);
+
     JavaFile defaultSdkDirectory;
     if (results[SDK_OPTION] != null) {
       defaultSdkDirectory = new JavaFile(results[SDK_OPTION]);
@@ -383,8 +399,12 @@
       // Use DirectoryBasedDartSdk.defaultSdkDirectory, which will make a guess.
       defaultSdkDirectory = DirectoryBasedDartSdk.defaultSdkDirectory;
     }
-    SdkCreator defaultSdkCreator =
-        () => new DirectoryBasedDartSdk(defaultSdkDirectory);
+    SdkCreator defaultSdkCreator = () {
+      DirectoryBasedDartSdk sdk =
+          new DirectoryBasedDartSdk(defaultSdkDirectory);
+      sdk.useSummary = true;
+      return sdk;
+    };
     // TODO(brianwilkerson) It would be nice to avoid creating an SDK that
     // cannot be re-used, but the SDK is needed to create a package map provider
     // in the case where we need to run `pub` in order to get the package map.
@@ -408,22 +428,6 @@
         results[CLIENT_VERSION], AnalysisServer.VERSION, defaultSdk.sdkVersion);
     AnalysisEngine.instance.instrumentationService = service;
     //
-    // Process all of the plugins so that extensions are registered.
-    //
-    ServerPlugin serverPlugin = new ServerPlugin();
-    List<Plugin> plugins = <Plugin>[];
-    plugins.addAll(AnalysisEngine.instance.requiredPlugins);
-    plugins.add(AnalysisEngine.instance.commandLinePlugin);
-    plugins.add(AnalysisEngine.instance.optionsPlugin);
-    plugins.add(serverPlugin);
-    plugins.add(linterPlugin);
-    plugins.add(linterServerPlugin);
-    plugins.add(dartCompletionPlugin);
-    plugins.addAll(_userDefinedPlugins);
-
-    ExtensionManager manager = new ExtensionManager();
-    manager.processPlugins(plugins);
-    //
     // Create the sockets and start listening for requests.
     //
     socketServer = new SocketServer(
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 6071fae..1a1352f 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
@@ -79,6 +79,44 @@
 }
 
 /**
+ * Determine if the completion target is in the middle or beginning of the list
+ * of named parameters and is not preceded by a comma. This method assumes that
+ * _isAppendingToArgList has been called and is false.
+ */
+bool _isInsertingToArgListWithNoSynthetic(DartCompletionRequest request) {
+  AstNode node = request.target.containingNode;
+  if (node is ArgumentList) {
+    var entity = request.target.entity;
+    return entity is NamedExpression;
+  }
+  return false;
+}
+
+/**
+ * Determine if the completion target is in the middle or beginning of the list
+ * of named parameters and is preceded by a comma. This method assumes that
+ * _isAppendingToArgList and _isInsertingToArgListWithNoSynthetic have been
+ * called and both return false.
+ */
+bool _isInsertingToArgListWithSynthetic(DartCompletionRequest request) {
+  AstNode node = request.target.containingNode;
+  if (node is ArgumentList) {
+    var entity = request.target.entity;
+    if (entity is SimpleIdentifier) {
+      int argIndex = request.target.argIndex;
+      // if the next argument is a NamedExpression, then we are in the named
+      // parameter list, guard first against end of list
+      if (node.arguments.length == argIndex + 1 ||
+          node.arguments.getRange(argIndex + 1, argIndex + 2).first
+          is NamedExpression) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+/**
  * Determine if the completion target is the label for a named argument.
  */
 bool _isEditingNamedArgLabel(DartCompletionRequest request) {
@@ -87,7 +125,7 @@
     var entity = request.target.entity;
     if (entity is NamedExpression) {
       int offset = request.offset;
-      if (entity.offset <= offset && offset < entity.end) {
+      if (entity.offset < offset && offset < entity.end) {
         return true;
       }
     }
@@ -219,23 +257,29 @@
     // suggestions.add(suggestion);
   }
 
-  void _addDefaultParamSuggestions(Iterable<ParameterElement> parameters) {
+  void _addDefaultParamSuggestions(Iterable<ParameterElement> parameters,
+      [bool appendComma = false]) {
     Iterable<String> namedArgs = _namedArgs(request);
     for (ParameterElement param in parameters) {
       if (param.parameterKind == ParameterKind.NAMED) {
-        _addNamedParameterSuggestion(request, namedArgs, param.name);
+        _addNamedParameterSuggestion(
+            request, namedArgs, param.name, appendComma);
       }
     }
   }
 
-  void _addNamedParameterSuggestion(
-      DartCompletionRequest request, List<String> namedArgs, String name) {
+  void _addNamedParameterSuggestion(DartCompletionRequest request,
+      List<String> namedArgs, String name, bool appendComma) {
     if (name != null && name.length > 0 && !namedArgs.contains(name)) {
+      String completion = '$name: ';
+      if (appendComma) {
+        completion += ',';
+      }
       suggestions.add(new CompletionSuggestion(
           CompletionSuggestionKind.NAMED_ARGUMENT,
           DART_RELEVANCE_NAMED_PARAMETER,
-          '$name: ',
-          name.length + 2,
+          completion,
+          completion.length,
           0,
           false,
           false));
@@ -253,10 +297,19 @@
       _addArgListSuggestion(requiredParam);
       return;
     }
+    // TODO (jwren) _isAppendingToArgList can be split into two cases (with and
+    // without preceded), then _isAppendingToArgList,
+    // _isInsertingToArgListWithNoSynthetic and
+    // _isInsertingToArgListWithSynthetic could be formatted into a single
+    // method which returns some enum with 5+ cases.
     if (_isEditingNamedArgLabel(request) || _isAppendingToArgList(request)) {
       if (requiredCount == 0 || requiredCount < _argCount(request)) {
         _addDefaultParamSuggestions(parameters);
       }
+    } else if (_isInsertingToArgListWithNoSynthetic(request)) {
+      _addDefaultParamSuggestions(parameters, true);
+    } else if (_isInsertingToArgListWithSynthetic(request)) {
+      _addDefaultParamSuggestions(parameters);
     }
   }
 }
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 dbf0da7..6c3a1e6 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -1494,6 +1494,10 @@
         String libraryUri = sdkLibrary.shortName;
         Source librarySource =
             sdkSourceFactory.resolveUri(unitSource, libraryUri);
+        // maybe already imported
+        if (alreadyImportedWithPrefix.contains(librarySource)) {
+          continue;
+        }
         // prepare LibraryElement
         LibraryElement libraryElement =
             context.getResult(librarySource, LIBRARY_ELEMENT1);
@@ -1523,7 +1527,7 @@
         if (librarySource.isInSystemLibrary) {
           continue;
         }
-        // maybe already imported with a prefix
+        // maybe already imported
         if (alreadyImportedWithPrefix.contains(librarySource)) {
           continue;
         }
diff --git a/pkg/analysis_server/lib/src/status/get_handler.dart b/pkg/analysis_server/lib/src/status/get_handler.dart
index c466669..47cbcbd 100644
--- a/pkg/analysis_server/lib/src/status/get_handler.dart
+++ b/pkg/analysis_server/lib/src/status/get_handler.dart
@@ -1289,6 +1289,36 @@
         buffer.write('</table></p>');
       }
     }
+    void writeOptions(StringBuffer buffer, AnalysisOptionsImpl options) {
+      if (options == null) {
+        buffer.write('<p>No option information available.</p>');
+        return;
+      }
+      buffer.write('<p>');
+      _writeOption(
+          buffer, 'Analyze functon bodies', options.analyzeFunctionBodies);
+      _writeOption(buffer, 'Cache size', options.cacheSize);
+      _writeOption(buffer, 'Enable async support', options.enableAsync);
+      _writeOption(
+          buffer, 'Enable generic methods', options.enableGenericMethods);
+      _writeOption(
+          buffer, 'Enable strict call checks', options.enableStrictCallChecks);
+      _writeOption(buffer, 'Enable super mixins', options.enableSuperMixins);
+      _writeOption(buffer, 'Generate dart2js hints', options.dart2jsHint);
+      _writeOption(buffer, 'Generate errors in implicit files',
+          options.generateImplicitErrors);
+      _writeOption(
+          buffer, 'Generate errors in SDK files', options.generateSdkErrors);
+      _writeOption(buffer, 'Generate hints', options.hint);
+      _writeOption(buffer, 'Incremental resolution', options.incremental);
+      _writeOption(buffer, 'Incremental resolution with API changes',
+          options.incrementalApi);
+      _writeOption(buffer, 'Preserve comments', options.preserveComments);
+      _writeOption(buffer, 'Strong mode', options.strongMode);
+      _writeOption(buffer, 'Strong mode hints', options.strongModeHints,
+          last: true);
+      buffer.write('</p>');
+    }
 
     _writeResponse(request, (StringBuffer buffer) {
       _writePage(
@@ -1296,53 +1326,37 @@
           (StringBuffer buffer) {
         buffer.write('<h3>Configuration</h3>');
 
-        _writeTwoColumns(buffer, (StringBuffer buffer) {
-          AnalysisOptionsImpl options = context.analysisOptions;
-          buffer.write('<p><b>Options</b></p>');
-          buffer.write('<p>');
-          _writeOption(
-              buffer, 'Analyze functon bodies', options.analyzeFunctionBodies);
-          _writeOption(buffer, 'Cache size', options.cacheSize);
-          _writeOption(buffer, 'Enable async support', options.enableAsync);
-          _writeOption(
-              buffer, 'Enable generic methods', options.enableGenericMethods);
-          _writeOption(buffer, 'Enable strict call checks',
-              options.enableStrictCallChecks);
-          _writeOption(
-              buffer, 'Enable super mixins', options.enableSuperMixins);
-          _writeOption(buffer, 'Generate dart2js hints', options.dart2jsHint);
-          _writeOption(buffer, 'Generate errors in implicit files',
-              options.generateImplicitErrors);
-          _writeOption(buffer, 'Generate errors in SDK files',
-              options.generateSdkErrors);
-          _writeOption(buffer, 'Generate hints', options.hint);
-          _writeOption(buffer, 'Incremental resolution', options.incremental);
-          _writeOption(buffer, 'Incremental resolution with API changes',
-              options.incrementalApi);
-          _writeOption(buffer, 'Preserve comments', options.preserveComments);
-          _writeOption(buffer, 'Strong mode', options.strongMode);
-          _writeOption(buffer, 'Strong mode hints', options.strongModeHints,
-              last: true);
-          buffer.write('</p>');
-        }, (StringBuffer buffer) {
-          List<Linter> lints =
-              context.getConfigurationData(CONFIGURED_LINTS_KEY);
-          buffer.write('<p><b>Lints</b></p>');
-          if (lints.isEmpty) {
-            buffer.write('<p>none</p>');
-          } else {
-            for (Linter lint in lints) {
-              buffer.write('<p>');
-              buffer.write(lint.runtimeType);
-              buffer.write('</p>');
+        _writeColumns(buffer, <HtmlGenerator>[
+          (StringBuffer buffer) {
+            buffer.write('<p><b>Context Options</b></p>');
+            writeOptions(buffer, context.analysisOptions);
+          },
+          (StringBuffer buffer) {
+            buffer.write('<p><b>SDK Context Options</b></p>');
+            writeOptions(buffer,
+                context?.sourceFactory?.dartSdk?.context?.analysisOptions);
+          },
+          (StringBuffer buffer) {
+            List<Linter> lints =
+                context.getConfigurationData(CONFIGURED_LINTS_KEY);
+            buffer.write('<p><b>Lints</b></p>');
+            if (lints.isEmpty) {
+              buffer.write('<p>none</p>');
+            } else {
+              for (Linter lint in lints) {
+                buffer.write('<p>');
+                buffer.write(lint.runtimeType);
+                buffer.write('</p>');
+              }
             }
-          }
 
-          List<ErrorProcessor> errorProcessors =
-              context.getConfigurationData(CONFIGURED_ERROR_PROCESSORS);
-          int processorCount = errorProcessors?.length ?? 0;
-          buffer.write('<p><b>Error Processor count</b>: $processorCount</p>');
-        });
+            List<ErrorProcessor> errorProcessors =
+                context.getConfigurationData(CONFIGURED_ERROR_PROCESSORS);
+            int processorCount = errorProcessors?.length ?? 0;
+            buffer
+                .write('<p><b>Error Processor count</b>: $processorCount</p>');
+          }
+        ]);
 
         SourceFactory sourceFactory = context.sourceFactory;
         if (sourceFactory is SourceFactoryImpl) {
@@ -1666,6 +1680,23 @@
   }
 
   /**
+   * Write multiple columns of information to the given [buffer], where the list
+   * of [columns] functions are used to generate the content of those columns.
+   */
+  void _writeColumns(StringBuffer buffer, List<HtmlGenerator> columns) {
+    buffer
+        .write('<table class="column"><tr class="column"><td class="column">');
+    int count = columns.length;
+    for (int i = 0; i < count; i++) {
+      if (i > 0) {
+        buffer.write('</td><td class="column">');
+      }
+      columns[i](buffer);
+    }
+    buffer.write('</td></tr></table>');
+  }
+
+  /**
    * Write performance information about a specific completion request
    * to the given [buffer] object.
    */
diff --git a/pkg/analysis_server/test/analysis/get_hover_test.dart b/pkg/analysis_server/test/analysis/get_hover_test.dart
index 672e9f2..9d5436b 100644
--- a/pkg/analysis_server/test/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/analysis/get_hover_test.dart
@@ -259,7 +259,7 @@
     expect(hover.elementDescription, 'mmm(int a, String b) → List<String>');
     expect(hover.elementKind, 'method');
     // types
-    expect(hover.staticType, isNull);
+    expect(hover.staticType, '(int, String) → List<String>');
     expect(hover.propagatedType, isNull);
     // no parameter
     expect(hover.parameter, isNull);
diff --git a/pkg/analysis_server/test/integration/analysis/get_hover_test.dart b/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
index 076ae9d..7ed2989 100644
--- a/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
@@ -173,13 +173,14 @@
           isLocal: true,
           docRegexp: 'Documentation for func',
           parameterRegexps: ['.*']));
-      tests.add(checkHover('add(', 3, ['List', 'add'], 'method', null,
+      tests.add(checkHover(
+          'add(', 3, ['List', 'add'], 'method', ['dynamic', 'void'],
           isCore: true, docRegexp: '.*'));
       tests.add(checkHover(
           'localVar)', 8, ['num', 'localVar'], 'local variable', ['num'],
           isLocal: true, parameterRegexps: ['.*'], propagatedType: 'int'));
       tests.add(checkHover(
-          'func(35', 4, ['func', 'int', 'param'], 'function', null,
+          'func(35', 4, ['func', 'int', 'param'], 'function', ['int', 'void'],
           docRegexp: 'Documentation for func'));
       tests.add(checkHover('35', 2, null, null, ['int'],
           isLiteral: true, parameterRegexps: ['int', 'param']));
diff --git a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
index 0a14ef1..e7f4fea 100644
--- a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
@@ -79,6 +79,20 @@
   /**
    * Assert that the specified suggestions are the only suggestions.
    */
+  void assertSuggestions(List<String> suggestions) {
+    List<CompletionSuggestion> expected = new List<CompletionSuggestion>();
+    for (String suggestion in suggestions) {
+      expected.add(assertSuggest('$suggestion',
+          csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
+          relevance: DART_RELEVANCE_NAMED_PARAMETER));
+    }
+    assertNoOtherSuggestions(expected);
+  }
+
+  /**
+   * Assert that the specified named argument suggestions are the only
+   * suggestions.
+   */
   void assertSuggestArguments({List<String> namedArguments}) {
     List<CompletionSuggestion> expected = new List<CompletionSuggestion>();
     for (String name in namedArguments) {
@@ -94,19 +108,108 @@
     return new ArgListContributor();
   }
 
+  test_Annotation_local_constructor_named_param_negative() async {
+    addTestSource('''
+class A { const A(int one, int two, int three, {int four, String five:
+  'defaultValue'}); }
+@A(1, ^, 3) main() { }''');
+    await computeSuggestions();
+    assertNoSuggestions();
+  }
+
   test_Annotation_local_constructor_named_param() async {
     addTestSource('''
-class A { A({int one, String two: 'defaultValue'}) { } }
+class A { const A({int one, String two: 'defaultValue'}); }
 @A(^) main() { }''');
     await computeSuggestions();
     assertSuggestArguments(namedArguments: ['one', 'two']);
   }
 
+  test_Annotation_local_constructor_named_param_2() async {
+    addTestSource('''
+class A { const A({int one, String two: 'defaultValue'}); }
+@A(^ two: '2') main() { }''');
+    await computeSuggestions();
+    assertSuggestions(['one: ,']);
+  }
+
+  test_Annotation_local_constructor_named_param_3() async {
+    addTestSource('''
+class A { const A({int one, String two: 'defaultValue'}); }
+@A(^two: '2') main() { }''');
+    await computeSuggestions();
+    assertSuggestions(['one: ,']);
+  }
+
+  test_Annotation_local_constructor_named_param_4() async {
+    addTestSource('''
+class A { const A({int one, String two: 'defaultValue'}); }
+@A(^, two: '2') main() { }''');
+    await computeSuggestions();
+    assertSuggestArguments(namedArguments: ['one']);
+  }
+
+  test_Annotation_local_constructor_named_param_5() async {
+    addTestSource('''
+class A { const A({int one, String two: 'defaultValue'}); }
+@A(^ , two: '2') main() { }''');
+    await computeSuggestions();
+    assertSuggestArguments(namedArguments: ['one']);
+  }
+
+  test_Annotation_local_constructor_named_param_6() async {
+    addTestSource('''
+class A { const A(int zero, {int one, String two: 'defaultValue'}); }
+@A(0, ^, two: '2') main() { }''');
+    await computeSuggestions();
+    assertSuggestArguments(namedArguments: ['one']);
+  }
+
+  test_Annotation_local_constructor_named_param_7() async {
+    addTestSource('''
+class A { const A(int zero, {int one, String two: 'defaultValue'}); }
+@A(0, ^ two: '2') main() { }''');
+    await computeSuggestions();
+    assertSuggestions(['one: ,']);
+  }
+
+  test_Annotation_local_constructor_named_param_8() async {
+    addTestSource('''
+class A { const A(int zero, {int one, String two: 'defaultValue'}); }
+@A(0, ^two: '2') main() { }''');
+    await computeSuggestions();
+    assertSuggestions(['one: ,']);
+  }
+
+  fail_test_Annotation_local_constructor_named_param_9() async {
+    addTestSource('''
+class A { const A({int one, String two: 'defaultValue'}); }
+@A(two: '2'^) main() { }''');
+    await computeSuggestions();
+    assertSuggestions([', one: ']);
+  }
+
+  fail_test_Annotation_local_constructor_named_param_10() async {
+    addTestSource('''
+class A { const A({int one, String two: 'defaultValue'}); }
+@A(two: '2' ^) main() { }''');
+    await computeSuggestions();
+    assertSuggestions([', one: ']);
+  }
+
+  test_Annotation_local_constructor_named_param_11() async {
+    addTestSource('''
+class A { const A({int one, String two: 'defaultValue'}); }
+@A(two: '2', ^) main() { }''');
+    await computeSuggestions();
+    assertSuggestArguments(namedArguments: ['one']);
+  }
+
   test_Annotation_imported_constructor_named_param() async {
     addSource(
         '/libA.dart',
         '''
-library libA; class A { A({int one, String two: 'defaultValue'}) { } }''');
+library libA; class A { const A({int one, String two: 'defaultValue'}); }''');
     addTestSource('import "/libA.dart"; @A(^) main() { }');
     await computeSuggestions();
     assertSuggestArguments(namedArguments: ['one', 'two']);
@@ -120,7 +223,7 @@
 
   test_ArgumentList_imported_constructor_named_param() async {
     //
-    addSource('/libA.dart', 'library libA; class A{A({int one}){}}');
+    addSource('/libA.dart', 'library libA; class A{A({int one}); }');
     addTestSource('import "/libA.dart"; main() { new A(^);}');
     await computeSuggestions();
     assertSuggestArguments(namedArguments: ['one']);
@@ -128,7 +231,7 @@
 
   test_ArgumentList_imported_constructor_named_param2() async {
     //
-    addSource('/libA.dart', 'library libA; class A{A.foo({int one}){}}');
+    addSource('/libA.dart', 'library libA; class A{A.foo({int one}); }');
     addTestSource('import "/libA.dart"; main() { new A.foo(^);}');
     await computeSuggestions();
     assertSuggestArguments(namedArguments: ['one']);
@@ -317,7 +420,7 @@
     //
     addTestSource('main() { int.parse("16", ^r: 16);}');
     await computeSuggestions();
-    assertSuggestArguments(namedArguments: ['radix', 'onError']);
+    assertSuggestions(['radix: ,', 'onError: ,']);
   }
 
   test_ArgumentList_imported_function_named_param_label3() async {
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index b059279..d793539 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -3460,7 +3460,35 @@
 ''');
   }
 
-  test_importLibraryShow() async {
+  test_importLibraryShow_project() async {
+    testFile = '/project/bin/test.dart';
+    addSource(
+        '/project/bin/lib.dart',
+        '''
+class A {}
+class B {}
+''');
+    resolveTestUnit('''
+import 'lib.dart' show A;
+main() {
+  A a;
+  B b;
+}
+''');
+    performAllAnalysisTasks();
+    await assertNoFix(DartFixKind.IMPORT_LIBRARY_PROJECT);
+    await assertHasFix(
+        DartFixKind.IMPORT_LIBRARY_SHOW,
+        '''
+import 'lib.dart' show A, B;
+main() {
+  A a;
+  B b;
+}
+''');
+  }
+
+  test_importLibraryShow_sdk() async {
     resolveTestUnit('''
 import 'dart:async' show Stream;
 main() {
@@ -3468,6 +3496,7 @@
   Future f = null;
 }
 ''');
+    await assertNoFix(DartFixKind.IMPORT_LIBRARY_SDK);
     await assertHasFix(
         DartFixKind.IMPORT_LIBRARY_SHOW,
         '''
diff --git a/pkg/analysis_server/test/services/correction/sort_members_test.dart b/pkg/analysis_server/test/services/correction/sort_members_test.dart
index b32f502..bcc9c0c 100644
--- a/pkg/analysis_server/test/services/correction/sort_members_test.dart
+++ b/pkg/analysis_server/test/services/correction/sort_members_test.dart
@@ -83,6 +83,22 @@
 ''');
   }
 
+  void test_classMembers_external_constructorMethod() {
+    _parseTestUnit(r'''
+class Chart {
+  external Pie();
+  external Chart();
+}
+''');
+    // validate change
+    _assertSort(r'''
+class Chart {
+  external Chart();
+  external Pie();
+}
+''');
+  }
+
   void test_classMembers_field() {
     _parseTestUnit(r'''
 class A {
diff --git a/pkg/analyzer/lib/context/declared_variables.dart b/pkg/analyzer/lib/context/declared_variables.dart
new file mode 100644
index 0000000..9a0322c
--- /dev/null
+++ b/pkg/analyzer/lib/context/declared_variables.dart
@@ -0,0 +1,88 @@
+// 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.context.declared_variables;
+
+import 'dart:collection';
+
+import 'package:analyzer/dart/constant/value.dart';
+import 'package:analyzer/src/dart/constant/value.dart';
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
+
+/**
+ * An object used to provide access to the values of variables that have been
+ * defined on the command line using the `-D` option.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class DeclaredVariables {
+  /**
+   * A table mapping the names of declared variables to their values.
+   */
+  HashMap<String, String> _declaredVariables = new HashMap<String, String>();
+
+  /**
+   * Define a variable with the given [name] to have the given [value].
+   */
+  void define(String name, String value) {
+    _declaredVariables[name] = value;
+  }
+
+  /**
+   * Return the value of the variable with the given [name] interpreted as a
+   * 'boolean' value. If the variable is not defined (or [name] is `null`), a
+   * DartObject representing "unknown" is returned. If the value cannot be
+   * parsed as a boolean, a DartObject representing 'null' is returned. The
+   * [typeProvider] is the type provider used to find the type 'bool'.
+   */
+  DartObject getBool(TypeProvider typeProvider, String name) {
+    String value = _declaredVariables[name];
+    if (value == null) {
+      return new DartObjectImpl(typeProvider.boolType, BoolState.UNKNOWN_VALUE);
+    }
+    if (value == "true") {
+      return new DartObjectImpl(typeProvider.boolType, BoolState.TRUE_STATE);
+    } else if (value == "false") {
+      return new DartObjectImpl(typeProvider.boolType, BoolState.FALSE_STATE);
+    }
+    return new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE);
+  }
+
+  /**
+   * Return the value of the variable with the given [name] interpreted as an
+   * integer value. If the variable is not defined (or [name] is `null`), a
+   * DartObject representing "unknown" is returned. If the value cannot be
+   * parsed as an integer, a DartObject representing 'null' is returned.
+   */
+  DartObject getInt(TypeProvider typeProvider, String name) {
+    String value = _declaredVariables[name];
+    if (value == null) {
+      return new DartObjectImpl(typeProvider.intType, IntState.UNKNOWN_VALUE);
+    }
+    int bigInteger;
+    try {
+      bigInteger = int.parse(value);
+    } on FormatException {
+      return new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE);
+    }
+    return new DartObjectImpl(typeProvider.intType, new IntState(bigInteger));
+  }
+
+  /**
+   * Return the value of the variable with the given [name] interpreted as a
+   * String value, or `null` if the variable is not defined. Return the value of
+   * the variable with the given name interpreted as a String value. If the
+   * variable is not defined (or [name] is `null`), a DartObject representing
+   * "unknown" is returned. The [typeProvider] is the type provider used to find
+   * the type 'String'.
+   */
+  DartObject getString(TypeProvider typeProvider, String name) {
+    String value = _declaredVariables[name];
+    if (value == null) {
+      return new DartObjectImpl(
+          typeProvider.stringType, StringState.UNKNOWN_VALUE);
+    }
+    return new DartObjectImpl(typeProvider.stringType, new StringState(value));
+  }
+}
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index d0680c4..e53a204 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -536,7 +536,7 @@
    * (either AST nodes or tokens) that make up the contents of this node,
    * including doc comments but excluding other comments.
    */
-  Iterable/*<AstNode | Token>*/ get childEntities;
+  Iterable /* AstNode | Token */ get childEntities;
 
   /**
    * Return the offset of the character immediately following the last character
@@ -591,7 +591,7 @@
    * Use the given [visitor] to visit this node. Return the value returned by
    * the visitor as a result of visiting this node.
    */
-  dynamic /* =E */ accept/*<E>*/(AstVisitor/*<E>*/ visitor);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor);
 
   /**
    * Return the most immediate ancestor of this node for which the [predicate]
@@ -5899,7 +5899,8 @@
    * are added to the list will have their parent set to the given [owner]. The
    * list will initially be populated with the given [elements].
    */
-  factory NodeList(AstNode owner, [List<E> elements]) = NodeListImpl;
+  factory NodeList(AstNode owner, [List<E> elements]) =>
+      new NodeListImpl<E>(owner as AstNodeImpl, elements);
 
   /**
    * Return the first token included in this node list's source range, or `null`
diff --git a/pkg/analyzer/lib/dart/constant/value.dart b/pkg/analyzer/lib/dart/constant/value.dart
new file mode 100644
index 0000000..e268345
--- /dev/null
+++ b/pkg/analyzer/lib/dart/constant/value.dart
@@ -0,0 +1,159 @@
+// 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.
+
+/**
+ * The interface used to access the result of constant evaluation.
+ *
+ * Because the analyzer does not have any of the code under analysis loaded, it
+ * does not do real evaluation. Instead it performs a symbolic computation and
+ * presents those results through this interface.
+ *
+ * Instances of these constant values are accessed through the
+ * [element model](../element/element.dart).
+ */
+library analyzer.dart.constant.value;
+
+import 'package:analyzer/dart/element/type.dart';
+
+/**
+ * A representation of the value of a compile-time constant expression.
+ *
+ * Note that, unlike the mirrors system, the object being represented does *not*
+ * exist. This interface allows static analysis tools to determine something
+ * about the state of the object that would exist if the code that creates the
+ * object were executed, but none of the code being analyzed is actually
+ * executed.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class DartObject {
+  /**
+   * Return `true` if the value of the object being represented is known.
+   *
+   * This method will return `false` if
+   * * the value being represented is the value of a declared variable (a
+   *   variable whose value is provided at run-time using a `-D` command-line
+   *   option), or
+   * * the value is a function.
+   *
+   * The result of this method does not imply anything about the state of
+   * object representations returned by the method [getField], those that are
+   * elements of the list returned by [toListValue], or the keys or values in
+   * the map returned by [toMapValue]. For example, a representation of a list
+   * can return `true` even if one or more of the elements of that list would
+   * return `false`.
+   */
+  bool get hasKnownValue;
+
+  /**
+   * Return `true` if the object being represented represents the value 'null'.
+   */
+  bool get isNull;
+
+  /**
+   * Return a representation of the type of the object being represented.
+   *
+   * For values resulting from the invocation of a 'const' constructor, this
+   * will be a representation of the run-time type of the object.
+   *
+   * For values resulting from a literal expression, this will be a
+   * representation of the static type of the value -- `int` for integer
+   * literals, `List` for list literals, etc. -- even when the static type is an
+   * abstract type (such as `List`) and hence will never be the run-time type of
+   * the represented object.
+   *
+   * For values resulting from any other kind of expression, this will be a
+   * representation of the result of evaluating the expression.
+   *
+   * Return `null` if the expression cannot be evaluated, either because it is
+   * not a valid constant expression or because one or more of the values used
+   * in the expression does not have a known value.
+   *
+   * This method can return a representation of the type, even if this object
+   * would return `false` from [hasKnownValue].
+   */
+  ParameterizedType get type;
+
+  /**
+   * Return a representation of the value of the field with the given [name].
+   *
+   * Return `null` if either the object being represented does not have a field
+   * with the given name or if the implementation of the class of the object is
+   * invalid, making it impossible to determine that value of the field.
+   *
+   * Note that, unlike the mirrors API, this method does *not* invoke a getter;
+   * it simply returns a representation of the known state of a field.
+   */
+  DartObject getField(String name);
+
+  /**
+   * Return a boolean corresponding to the value of the object being
+   * represented, or `null` if
+   * * this object is not of type 'bool',
+   * * the value of the object being represented is not known, or
+   * * the value of the object being represented is `null`.
+   */
+  bool toBoolValue();
+
+  /**
+   * Return a double corresponding to the value of the object being represented,
+   * or `null`
+   * if
+   * * this object is not of type 'double',
+   * * the value of the object being represented is not known, or
+   * * the value of the object being represented is `null`.
+   */
+  double toDoubleValue();
+
+  /**
+   * Return an integer corresponding to the value of the object being
+   * represented, or `null` if
+   * * this object is not of type 'int',
+   * * the value of the object being represented is not known, or
+   * * the value of the object being represented is `null`.
+   */
+  int toIntValue();
+
+  /**
+   * Return a list corresponding to the value of the object being represented,
+   * or `null` if
+   * * this object is not of type 'List', or
+   * * the value of the object being represented is `null`.
+   */
+  List<DartObject> toListValue();
+
+  /**
+   * Return a map corresponding to the value of the object being represented, or
+   * `null` if
+   * * this object is not of type 'Map', or
+   * * the value of the object being represented is `null`.
+   */
+  Map<DartObject, DartObject> toMapValue();
+
+  /**
+   * Return a string corresponding to the value of the object being represented,
+   * or `null` if
+   * * this object is not of type 'String',
+   * * the value of the object being represented is not known, or
+   * * the value of the object being represented is `null`.
+   */
+  String toStringValue();
+
+  /**
+   * Return a string corresponding to the value of the object being represented,
+   * or `null` if
+   * * this object is not of type 'Symbol', or
+   * * the value of the object being represented is `null`.
+   * (We return the string
+   */
+  String toSymbolValue();
+
+  /**
+   * Return the representation of the type corresponding to the value of the
+   * object being represented, or `null` if
+   * * this object is not of type 'Type', or
+   * * the value of the object being represented is `null`.
+   */
+  DartType toTypeValue();
+}
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 17e2f54..385849f 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -37,8 +37,8 @@
 library analyzer.dart.element.element;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/constant/value.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/generated/constant.dart' show DartObject;
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
@@ -808,18 +808,18 @@
   bool get isDeprecated;
 
   /**
-   * Return `true` if this annotation marks the associated method as being
-   * expected to override an inherited method.
-   */
-  bool get isOverride;
-
-  /**
    * Return `true` if this annotation marks the associated member as requiring
    * overriding methods to call super.
    */
   bool get isMustCallSuper;
 
   /**
+   * Return `true` if this annotation marks the associated method as being
+   * expected to override an inherited method.
+   */
+  bool get isOverride;
+
+  /**
    * Return `true` if this annotation marks the associated member as being
    * protected.
    */
@@ -1330,12 +1330,6 @@
   static const List<LibraryElement> EMPTY_LIST = const <LibraryElement>[];
 
   /**
-   * Return a list containing the strongly connected component in the
-   * import/export graph in which the current library resides.
-   */
-  List<LibraryElement> get libraryCycle;
-
-  /**
    * Return the compilation unit that defines this library.
    */
   CompilationUnitElement get definingCompilationUnit;
@@ -1417,6 +1411,12 @@
   bool get isInSdk;
 
   /**
+   * Return a list containing the strongly connected component in the
+   * import/export graph in which the current library resides.
+   */
+  List<LibraryElement> get libraryCycle;
+
+  /**
    * Return the element representing the synthetic function `loadLibrary` that
    * is implicitly defined for this library if the library is imported using a
    * deferred import.
diff --git a/pkg/analyzer/lib/file_system/file_system.dart b/pkg/analyzer/lib/file_system/file_system.dart
index c9b3e96..ba2bf4b 100644
--- a/pkg/analyzer/lib/file_system/file_system.dart
+++ b/pkg/analyzer/lib/file_system/file_system.dart
@@ -32,10 +32,33 @@
   Source createSource([Uri uri]);
 
   /**
+   * Synchronously read the entire file contents as a list of bytes.
+   * Throws a [FileSystemException] if the operation fails.
+   */
+  List<int> readAsBytesSync();
+
+  /**
    * Synchronously read the entire file contents as a [String].
    * Throws [FileSystemException] if the file does not exist.
    */
   String readAsStringSync();
+
+  /**
+   * Synchronously rename this file.
+   * Return a [File] instance for the renamed file.
+   *
+   * If [newPath] identifies an existing file, that file is replaced.
+   * If [newPath] identifies an existing resource the operation might fail and
+   * an exception is thrown.
+   */
+  File renameSync(String newPath);
+
+  /**
+   * Synchronously write a list of bytes to the file.
+   *
+   * Throws a [FileSystemException] if the operation fails.
+   */
+  void writeAsBytesSync(List<int> bytes);
 }
 
 /**
@@ -63,7 +86,7 @@
 
   /**
    * If the path [path] is a relative path, convert it to an absolute path
-   * by interpreting it relative to this folder.  If it is already an aboslute
+   * by interpreting it relative to this folder.  If it is already an absolute
    * path, then don't change it.
    *
    * However, regardless of whether [path] is relative or absolute, normalize
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index fd26eb1..22d1b81 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -23,6 +23,7 @@
   final Map<String, _MemoryResource> _pathToResource =
       new HashMap<String, _MemoryResource>();
   final Map<String, String> _pathToContent = new HashMap<String, String>();
+  final Map<String, List<int>> _pathToBytes = new HashMap<String, List<int>>();
   final Map<String, int> _pathToTimestamp = new HashMap<String, int>();
   final Map<String, List<StreamController<WatchEvent>>> _pathToWatchers =
       new HashMap<String, List<StreamController<WatchEvent>>>();
@@ -116,16 +117,18 @@
 
   File newFile(String path, String content, [int stamp]) {
     path = pathContext.normalize(path);
-    _MemoryResource folder = _pathToResource[pathContext.dirname(path)];
-    if (folder == null) {
-      newFolder(pathContext.dirname(path));
-    } else if (folder is! Folder) {
-      throw new ArgumentError('Cannot create file ($path) as child of file');
-    }
-    _MemoryFile file = new _MemoryFile(this, path);
-    _pathToResource[path] = file;
+    _MemoryFile file = _newFile(path);
     _pathToContent[path] = content;
-    _pathToTimestamp[path] = stamp != null ? stamp : nextStamp++;
+    _pathToTimestamp[path] = stamp ?? nextStamp++;
+    _notifyWatchers(path, ChangeType.ADD);
+    return file;
+  }
+
+  File newFileWithBytes(String path, List<int> bytes, [int stamp]) {
+    path = pathContext.normalize(path);
+    _MemoryFile file = _newFile(path);
+    _pathToBytes[path] = bytes;
+    _pathToTimestamp[path] = stamp ?? nextStamp++;
     _notifyWatchers(path, ChangeType.ADD);
     return file;
   }
@@ -156,6 +159,29 @@
     }
   }
 
+  _MemoryFile renameFileSync(_MemoryFile file, String newPath) {
+    String path = file.path;
+    if (newPath == path) {
+      return file;
+    }
+    _MemoryResource existingNewResource = _pathToResource[newPath];
+    if (existingNewResource is _MemoryFolder) {
+      throw new FileSystemException(
+          path, 'Could not be renamed: $newPath is a folder.');
+    }
+    _MemoryFile newFile = _newFile(newPath);
+    _pathToResource.remove(path);
+    _pathToContent[newPath] = _pathToContent.remove(path);
+    _pathToBytes[newPath] = _pathToBytes.remove(path);
+    _pathToTimestamp[newPath] = _pathToTimestamp.remove(path);
+    if (existingNewResource != null) {
+      _notifyWatchers(newPath, ChangeType.REMOVE);
+    }
+    _notifyWatchers(path, ChangeType.REMOVE);
+    _notifyWatchers(newPath, ChangeType.ADD);
+    return newFile;
+  }
+
   File updateFile(String path, String content, [int stamp]) {
     path = pathContext.normalize(path);
     newFolder(pathContext.dirname(path));
@@ -183,6 +209,22 @@
     }
   }
 
+  /**
+   * Create a new [_MemoryFile] without any content.
+   */
+  _MemoryFile _newFile(String path) {
+    String folderPath = pathContext.dirname(path);
+    _MemoryResource folder = _pathToResource[folderPath];
+    if (folder == null) {
+      newFolder(folderPath);
+    } else if (folder is! Folder) {
+      throw new ArgumentError('Cannot create file ($path) as child of file');
+    }
+    _MemoryFile file = new _MemoryFile(this, path);
+    _pathToResource[path] = file;
+    return file;
+  }
+
   void _notifyWatchers(String path, ChangeType changeType) {
     _pathToWatchers.forEach((String watcherPath,
         List<StreamController<WatchEvent>> streamControllers) {
@@ -194,6 +236,14 @@
       }
     });
   }
+
+  void _setFileBytes(_MemoryFile file, List<int> bytes) {
+    String path = file.path;
+    _pathToResource[path] = file;
+    _pathToBytes[path] = bytes;
+    _pathToTimestamp[path] = nextStamp++;
+    _notifyWatchers(path, ChangeType.MODIFY);
+  }
 }
 
 /**
@@ -236,9 +286,24 @@
   }
 
   @override
+  List<int> readAsBytesSync() {
+    throw new FileSystemException(path, 'File could not be read');
+  }
+
+  @override
   String readAsStringSync() {
     throw new FileSystemException(path, 'File could not be read');
   }
+
+  @override
+  Resource renameSync(String newPath) {
+    throw new FileSystemException(path, 'File could not be renamed');
+  }
+
+  @override
+  void writeAsBytesSync(List<int> bytes) {
+    throw new FileSystemException(path, 'File could not be written');
+  }
 }
 
 /**
@@ -282,6 +347,15 @@
   }
 
   @override
+  List<int> readAsBytesSync() {
+    List<int> bytes = _provider._pathToBytes[path];
+    if (bytes == null) {
+      throw new FileSystemException(path, 'File "$path" is not binary.');
+    }
+    return bytes;
+  }
+
+  @override
   String readAsStringSync() {
     String content = _provider._pathToContent[path];
     if (content == null) {
@@ -289,6 +363,16 @@
     }
     return content;
   }
+
+  @override
+  File renameSync(String newPath) {
+    return _provider.renameFileSync(this, newPath);
+  }
+
+  @override
+  void writeAsBytesSync(List<int> bytes) {
+    _provider._setFileBytes(this, bytes);
+  }
 }
 
 /**
diff --git a/pkg/analyzer/lib/file_system/physical_file_system.dart b/pkg/analyzer/lib/file_system/physical_file_system.dart
index cdfa9a6..66125a6 100644
--- a/pkg/analyzer/lib/file_system/physical_file_system.dart
+++ b/pkg/analyzer/lib/file_system/physical_file_system.dart
@@ -19,8 +19,8 @@
  * A `dart:io` based implementation of [ResourceProvider].
  */
 class PhysicalResourceProvider implements ResourceProvider {
-  static final NORMALIZE_EOL_ALWAYS = (String string) =>
-      string.replaceAll(new RegExp('\r\n?'), '\n');
+  static final NORMALIZE_EOL_ALWAYS =
+      (String string) => string.replaceAll(new RegExp('\r\n?'), '\n');
 
   static final PhysicalResourceProvider INSTANCE =
       new PhysicalResourceProvider(null);
@@ -112,6 +112,16 @@
   }
 
   @override
+  List<int> readAsBytesSync() {
+    try {
+      io.File file = _entry as io.File;
+      return file.readAsBytesSync();
+    } on io.FileSystemException catch (exception) {
+      throw new FileSystemException(exception.path, exception.message);
+    }
+  }
+
+  @override
   String readAsStringSync() {
     try {
       io.File file = _entry as io.File;
@@ -120,6 +130,27 @@
       throw new FileSystemException(exception.path, exception.message);
     }
   }
+
+  @override
+  void writeAsBytesSync(List<int> bytes) {
+    try {
+      io.File file = _entry as io.File;
+      file.writeAsBytesSync(bytes);
+    } on io.FileSystemException catch (exception) {
+      throw new FileSystemException(exception.path, exception.message);
+    }
+  }
+
+  @override
+  Resource renameSync(String newPath) {
+    try {
+      io.File file = _entry as io.File;
+      io.File newFile = file.renameSync(newPath);
+      return new _PhysicalFile(newFile);
+    } on io.FileSystemException catch (exception) {
+      throw new FileSystemException(exception.path, exception.message);
+    }
+  }
 }
 
 /**
diff --git a/pkg/analyzer/lib/source/analysis_options_provider.dart b/pkg/analyzer/lib/source/analysis_options_provider.dart
index c53bbad..b96ba5c 100644
--- a/pkg/analyzer/lib/source/analysis_options_provider.dart
+++ b/pkg/analyzer/lib/source/analysis_options_provider.dart
@@ -68,7 +68,7 @@
         if (v != null && v is! YamlNode) {
           throw new OptionsFormatException(
               'Bad options file format (expected Node value, '
-                  'got ${v.runtimeType}: `${v.toString()}`)',
+              'got ${v.runtimeType}: `${v.toString()}`)',
               doc.span);
         }
         options[key] = v;
@@ -91,7 +91,7 @@
   ///
   Map<String, YamlNode> merge(
           Map<String, YamlNode> defaults, Map<String, YamlNode> overrides) =>
-      new Merger().merge(defaults, overrides);
+      new Merger().merge(defaults, overrides) as Map<String, YamlNode>;
 
   /// Read the contents of [file] as a string.
   /// Returns null if file does not exist.
diff --git a/pkg/analyzer/lib/source/error_processor.dart b/pkg/analyzer/lib/source/error_processor.dart
index 6b69cb7..ddd0679 100644
--- a/pkg/analyzer/lib/source/error_processor.dart
+++ b/pkg/analyzer/lib/source/error_processor.dart
@@ -10,6 +10,13 @@
 import 'package:analyzer/src/task/options.dart';
 import 'package:yaml/yaml.dart';
 
+/// String identifiers mapped to associated severities.
+const Map<String, ErrorSeverity> severityMap = const {
+  'error': ErrorSeverity.ERROR,
+  'info': ErrorSeverity.INFO,
+  'warning': ErrorSeverity.WARNING
+};
+
 /// Error processor configuration derived from analysis (or embedder) options.
 class ErrorConfig {
   /// The processors in this config.
@@ -57,13 +64,6 @@
   ErrorSeverity _toSeverity(String severity) => severityMap[severity];
 }
 
-/// String identifiers mapped to associated severities.
-const Map<String, ErrorSeverity> severityMap = const {
-  'error': ErrorSeverity.ERROR,
-  'info': ErrorSeverity.INFO,
-  'warning': ErrorSeverity.WARNING
-};
-
 /// Process errors by filtering or changing associated [ErrorSeverity].
 class ErrorProcessor {
   /// The code name of the associated error.
@@ -94,20 +94,18 @@
       return null;
     }
 
-    // By default, the error is not processed.
-    ErrorProcessor processor;
+    // Let the user configure how specific errors are processed.
+    List<ErrorProcessor> processors =
+        context.getConfigurationData(CONFIGURED_ERROR_PROCESSORS)
+        as List<ErrorProcessor>;
 
     // Give strong mode a chance to upgrade it.
     if (context.analysisOptions.strongMode) {
-      processor = _StrongModeTypeErrorProcessor.instance;
+      processors = processors.toList();
+      processors.add(_StrongModeTypeErrorProcessor.instance);
     }
-
-    // Let the user configure how specific errors are processed.
-    List<ErrorProcessor> processors =
-        context.getConfigurationData(CONFIGURED_ERROR_PROCESSORS);
-
     return processors.firstWhere((ErrorProcessor p) => p.appliesTo(error),
-        orElse: () => processor);
+        orElse: () => null);
   }
 }
 
diff --git a/pkg/analyzer/lib/source/sdk_ext.dart b/pkg/analyzer/lib/source/sdk_ext.dart
index fc7155a..126d3b6 100644
--- a/pkg/analyzer/lib/source/sdk_ext.dart
+++ b/pkg/analyzer/lib/source/sdk_ext.dart
@@ -155,7 +155,7 @@
   /// Read the contents of [libDir]/[SDK_EXT_NAME] as a string.
   /// Returns null if the file doesn't exist.
   String _readDotSdkExt(Folder libDir) {
-    var file = libDir.getChild(SDK_EXT_NAME);
+    File file = libDir.getChild(SDK_EXT_NAME);
     try {
       return file.readAsStringSync();
     } on FileSystemException {
diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart
index de913f3..98e0451 100644
--- a/pkg/analyzer/lib/src/context/cache.dart
+++ b/pkg/analyzer/lib/src/context/cache.dart
@@ -405,7 +405,7 @@
     if (_partition != null) {
       _partition.resultAccessed(target, descriptor);
     }
-    return data.value;
+    return data.value as Object/*=V*/;
   }
 
   /**
@@ -565,7 +565,8 @@
     // Ask the delta to validate.
     DeltaResult deltaResult = null;
     if (delta != null) {
-      deltaResult = delta.validate(_partition.context, target, descriptor);
+      deltaResult = delta.validate(
+          _partition.context, target, descriptor, thisData.value);
       if (deltaResult == DeltaResult.STOP) {
         return;
       }
@@ -1056,10 +1057,10 @@
 
   /**
    * Check whether this delta affects the result described by the given
-   * [descriptor] and [target].
+   * [descriptor] and [target]. The current [value] of the result is provided.
    */
   DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
-      ResultDescriptor descriptor) {
+      ResultDescriptor descriptor, Object value) {
     return DeltaResult.INVALIDATE;
   }
 }
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 2c4ef43..90d5ffc 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -288,6 +288,7 @@
     this._options.enableConditionalDirectives =
         options.enableConditionalDirectives;
     this._options.enableSuperMixins = options.enableSuperMixins;
+    this._options.enableTiming = options.enableTiming;
     this._options.hint = options.hint;
     this._options.incremental = options.incremental;
     this._options.incrementalApi = options.incrementalApi;
@@ -1019,8 +1020,9 @@
   }
 
   @override
-  Object getResult(AnalysisTarget target, ResultDescriptor result) {
-    return _cache.getValue(target, result);
+  Object/*=V*/ getResult/*<V>*/(
+      AnalysisTarget target, ResultDescriptor/*<V>*/ result) {
+    return _cache.getValue(target, result) as Object/*=V*/;
   }
 
   @override
@@ -2009,7 +2011,7 @@
       return new CancelableFuture.error(new AnalysisNotScheduledError());
     }
     CacheEntry entry = _context.getCacheEntry(_target);
-    PendingFuture pendingFuture =
+    PendingFuture<T> pendingFuture =
         new PendingFuture<T>(_context, _target, (CacheEntry entry) {
       CacheState state = entry.getState(_descriptor);
       if (state == CacheState.ERROR) {
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index d2e09de..3f398ac 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -59,7 +59,8 @@
   NodeList<StringLiteral> get strings => _strings;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitAdjacentStrings(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitAdjacentStrings(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -155,7 +156,7 @@
   @override
   void visitChildren(AstVisitor visitor) {
     if (_commentIsBeforeAnnotations()) {
-      _safelyVisitChild(_comment, visitor);
+      _comment?.accept(visitor);
       _metadata.accept(visitor);
     } else {
       for (AstNode child in sortedCommentAndAnnotations) {
@@ -305,13 +306,14 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitAnnotation(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitAnnotation(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_constructorName, visitor);
-    _safelyVisitChild(_arguments, visitor);
+    _name?.accept(visitor);
+    _constructorName?.accept(visitor);
+    _arguments?.accept(visitor);
   }
 }
 
@@ -409,7 +411,8 @@
   Token get endToken => rightParenthesis;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitArgumentList(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitArgumentList(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -531,12 +534,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitAsExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitAsExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
-    _safelyVisitChild(_type, visitor);
+    _expression?.accept(visitor);
+    _type?.accept(visitor);
   }
 }
 
@@ -636,12 +640,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitAssertStatement(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitAssertStatement(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_condition, visitor);
-    _safelyVisitChild(message, visitor);
+    _condition?.accept(visitor);
+    message?.accept(visitor);
   }
 }
 
@@ -823,12 +828,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitAssignmentExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitAssignmentExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_leftHandSide, visitor);
-    _safelyVisitChild(_rightHandSide, visitor);
+    _leftHandSide?.accept(visitor);
+    _rightHandSide?.accept(visitor);
   }
 }
 
@@ -941,15 +947,6 @@
     }
     return child;
   }
-
-  /**
-   * If the given [child] is not `null`, use the given [visitor] to visit it.
-   */
-  void _safelyVisitChild(AstNode child, AstVisitor visitor) {
-    if (child != null) {
-      child.accept(visitor);
-    }
-  }
 }
 
 /**
@@ -1004,11 +1001,12 @@
   int get precedence => 0;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitAwaitExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitAwaitExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
+    _expression?.accept(visitor);
   }
 }
 
@@ -1134,12 +1132,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitBinaryExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitBinaryExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_leftOperand, visitor);
-    _safelyVisitChild(_rightOperand, visitor);
+    _leftOperand?.accept(visitor);
+    _rightOperand?.accept(visitor);
   }
 }
 
@@ -1213,11 +1212,12 @@
   bool get isSynchronous => keyword == null || keyword.lexeme != Parser.ASYNC;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitBlockFunctionBody(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitBlockFunctionBody(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_block, visitor);
+    _block?.accept(visitor);
   }
 }
 
@@ -1268,7 +1268,8 @@
   NodeList<Statement> get statements => _statements;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitBlock(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitBlock(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -1313,7 +1314,8 @@
   bool get isSynthetic => literal.isSynthetic;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitBooleanLiteral(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitBooleanLiteral(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -1385,11 +1387,12 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitBreakStatement(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitBreakStatement(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_label, visitor);
+    _label?.accept(visitor);
   }
 }
 
@@ -1456,11 +1459,12 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitCascadeExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitCascadeExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_target, visitor);
+    _target?.accept(visitor);
     _cascadeSections.accept(visitor);
   }
 }
@@ -1610,14 +1614,15 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitCatchClause(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitCatchClause(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_exceptionType, visitor);
-    _safelyVisitChild(_exceptionParameter, visitor);
-    _safelyVisitChild(_stackTraceParameter, visitor);
-    _safelyVisitChild(_body, visitor);
+    _exceptionType?.accept(visitor);
+    _exceptionParameter?.accept(visitor);
+    _stackTraceParameter?.accept(visitor);
+    _body?.accept(visitor);
   }
 }
 
@@ -1830,7 +1835,8 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitClassDeclaration(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitClassDeclaration(this);
 
   @override
   ConstructorDeclaration getConstructor(String name) {
@@ -1884,12 +1890,12 @@
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_typeParameters, visitor);
-    _safelyVisitChild(_extendsClause, visitor);
-    _safelyVisitChild(_withClause, visitor);
-    _safelyVisitChild(_implementsClause, visitor);
-    _safelyVisitChild(_nativeClause, visitor);
+    _name?.accept(visitor);
+    _typeParameters?.accept(visitor);
+    _extendsClause?.accept(visitor);
+    _withClause?.accept(visitor);
+    _implementsClause?.accept(visitor);
+    _nativeClause?.accept(visitor);
     members.accept(visitor);
   }
 }
@@ -2039,16 +2045,17 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitClassTypeAlias(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitClassTypeAlias(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_typeParameters, visitor);
-    _safelyVisitChild(_superclass, visitor);
-    _safelyVisitChild(_withClause, visitor);
-    _safelyVisitChild(_implementsClause, visitor);
+    _name?.accept(visitor);
+    _typeParameters?.accept(visitor);
+    _superclass?.accept(visitor);
+    _withClause?.accept(visitor);
+    _implementsClause?.accept(visitor);
   }
 }
 
@@ -2145,7 +2152,8 @@
   NodeList<CommentReference> get references => _references;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitComment(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitComment(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -2226,11 +2234,12 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitCommentReference(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitCommentReference(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_identifier, visitor);
+    _identifier?.accept(visitor);
   }
 }
 
@@ -2411,11 +2420,12 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitCompilationUnit(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitCompilationUnit(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_scriptTag, visitor);
+    _scriptTag?.accept(visitor);
     if (_directivesAreBeforeDeclarations) {
       _directives.accept(visitor);
       _declarations.accept(visitor);
@@ -2537,13 +2547,14 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitConditionalExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitConditionalExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_condition, visitor);
-    _safelyVisitChild(_thenExpression, visitor);
-    _safelyVisitChild(_elseExpression, visitor);
+    _condition?.accept(visitor);
+    _thenExpression?.accept(visitor);
+    _elseExpression?.accept(visitor);
   }
 }
 
@@ -2626,13 +2637,14 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitConfiguration(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitConfiguration(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_value, visitor);
-    _safelyVisitChild(_libraryUri, visitor);
+    _name?.accept(visitor);
+    _value?.accept(visitor);
+    _libraryUri?.accept(visitor);
   }
 }
 
@@ -2853,17 +2865,18 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitConstructorDeclaration(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitConstructorDeclaration(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_returnType, visitor);
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_parameters, visitor);
+    _returnType?.accept(visitor);
+    _name?.accept(visitor);
+    _parameters?.accept(visitor);
     _initializers.accept(visitor);
-    _safelyVisitChild(_redirectedConstructor, visitor);
-    _safelyVisitChild(_body, visitor);
+    _redirectedConstructor?.accept(visitor);
+    _body?.accept(visitor);
   }
 }
 
@@ -2951,12 +2964,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitConstructorFieldInitializer(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitConstructorFieldInitializer(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_fieldName, visitor);
-    _safelyVisitChild(_expression, visitor);
+    _fieldName?.accept(visitor);
+    _expression?.accept(visitor);
   }
 }
 
@@ -3045,12 +3059,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitConstructorName(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitConstructorName(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_type, visitor);
-    _safelyVisitChild(_name, visitor);
+    _type?.accept(visitor);
+    _name?.accept(visitor);
   }
 }
 
@@ -3116,11 +3131,12 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitContinueStatement(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitContinueStatement(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_label, visitor);
+    _label?.accept(visitor);
   }
 }
 
@@ -3230,13 +3246,14 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitDeclaredIdentifier(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitDeclaredIdentifier(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_type, visitor);
-    _safelyVisitChild(_identifier, visitor);
+    _type?.accept(visitor);
+    _identifier?.accept(visitor);
   }
 }
 
@@ -3331,12 +3348,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitDefaultFormalParameter(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitDefaultFormalParameter(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_parameter, visitor);
-    _safelyVisitChild(_defaultValue, visitor);
+    _parameter?.accept(visitor);
+    _defaultValue?.accept(visitor);
   }
 }
 
@@ -3461,12 +3479,13 @@
   Token get endToken => semicolon;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitDoStatement(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitDoStatement(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_body, visitor);
-    _safelyVisitChild(_condition, visitor);
+    _body?.accept(visitor);
+    _condition?.accept(visitor);
   }
 }
 
@@ -3503,7 +3522,8 @@
   Token get endToken => _components.endToken;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitDottedName(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitDottedName(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -3549,7 +3569,8 @@
   Token get endToken => literal;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitDoubleLiteral(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitDoubleLiteral(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -3588,7 +3609,8 @@
   Token get endToken => semicolon;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitEmptyFunctionBody(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitEmptyFunctionBody(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -3623,7 +3645,8 @@
   Token get endToken => semicolon;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitEmptyStatement(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitEmptyStatement(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -3675,12 +3698,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitEnumConstantDeclaration(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitEnumConstantDeclaration(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_name, visitor);
+    _name?.accept(visitor);
   }
 }
 
@@ -3756,12 +3780,13 @@
   Token get firstTokenAfterCommentAndMetadata => enumKeyword;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitEnumDeclaration(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitEnumDeclaration(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_name, visitor);
+    _name?.accept(visitor);
     _constants.accept(visitor);
   }
 }
@@ -3820,7 +3845,8 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitExportDirective(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitExportDirective(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -3910,11 +3936,12 @@
   bool get isSynchronous => keyword == null;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitExpressionFunctionBody(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitExpressionFunctionBody(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
+    _expression?.accept(visitor);
   }
 }
 
@@ -4073,11 +4100,12 @@
   bool get isSynthetic => _expression.isSynthetic && semicolon.isSynthetic;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitExpressionStatement(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitExpressionStatement(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
+    _expression?.accept(visitor);
   }
 }
 
@@ -4125,11 +4153,12 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitExtendsClause(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitExtendsClause(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_superclass, visitor);
+    _superclass?.accept(visitor);
   }
 }
 
@@ -4200,12 +4229,13 @@
   bool get isStatic => staticKeyword != null;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitFieldDeclaration(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitFieldDeclaration(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_fieldList, visitor);
+    _fieldList?.accept(visitor);
   }
 }
 
@@ -4342,15 +4372,16 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitFieldFormalParameter(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitFieldFormalParameter(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_type, visitor);
-    _safelyVisitChild(identifier, visitor);
-    _safelyVisitChild(_typeParameters, visitor);
-    _safelyVisitChild(_parameters, visitor);
+    _type?.accept(visitor);
+    identifier?.accept(visitor);
+    _typeParameters?.accept(visitor);
+    _parameters?.accept(visitor);
   }
 }
 
@@ -4503,14 +4534,15 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitForEachStatement(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitForEachStatement(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_loopVariable, visitor);
-    _safelyVisitChild(_identifier, visitor);
-    _safelyVisitChild(_iterable, visitor);
-    _safelyVisitChild(_body, visitor);
+    _loopVariable?.accept(visitor);
+    _identifier?.accept(visitor);
+    _iterable?.accept(visitor);
+    _body?.accept(visitor);
   }
 }
 
@@ -4643,7 +4675,8 @@
   NodeList<FormalParameter> get parameters => _parameters;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitFormalParameterList(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitFormalParameterList(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -4804,15 +4837,16 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitForStatement(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitForStatement(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_variableList, visitor);
-    _safelyVisitChild(_initialization, visitor);
-    _safelyVisitChild(_condition, visitor);
+    _variableList?.accept(visitor);
+    _initialization?.accept(visitor);
+    _condition?.accept(visitor);
     _updaters.accept(visitor);
-    _safelyVisitChild(_body, visitor);
+    _body?.accept(visitor);
   }
 }
 
@@ -4994,14 +5028,15 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitFunctionDeclaration(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitFunctionDeclaration(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_returnType, visitor);
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_functionExpression, visitor);
+    _returnType?.accept(visitor);
+    _name?.accept(visitor);
+    _functionExpression?.accept(visitor);
   }
 }
 
@@ -5040,11 +5075,12 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitFunctionDeclarationStatement(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitFunctionDeclarationStatement(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_functionDeclaration, visitor);
+    _functionDeclaration?.accept(visitor);
   }
 }
 
@@ -5147,13 +5183,14 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitFunctionExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitFunctionExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_typeParameters, visitor);
-    _safelyVisitChild(_parameters, visitor);
-    _safelyVisitChild(_body, visitor);
+    _typeParameters?.accept(visitor);
+    _parameters?.accept(visitor);
+    _body?.accept(visitor);
   }
 }
 
@@ -5229,13 +5266,14 @@
   int get precedence => 15;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitFunctionExpressionInvocation(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitFunctionExpressionInvocation(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_function, visitor);
-    _safelyVisitChild(_typeArguments, visitor);
-    _safelyVisitChild(_argumentList, visitor);
+    _function?.accept(visitor);
+    _typeArguments?.accept(visitor);
+    _argumentList?.accept(visitor);
   }
 }
 
@@ -5326,15 +5364,16 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitFunctionTypeAlias(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitFunctionTypeAlias(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_returnType, visitor);
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_typeParameters, visitor);
-    _safelyVisitChild(_parameters, visitor);
+    _returnType?.accept(visitor);
+    _name?.accept(visitor);
+    _typeParameters?.accept(visitor);
+    _parameters?.accept(visitor);
   }
 }
 
@@ -5428,15 +5467,16 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitFunctionTypedFormalParameter(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitFunctionTypedFormalParameter(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_returnType, visitor);
-    _safelyVisitChild(identifier, visitor);
-    _safelyVisitChild(_typeParameters, visitor);
-    _safelyVisitChild(_parameters, visitor);
+    _returnType?.accept(visitor);
+    identifier?.accept(visitor);
+    _typeParameters?.accept(visitor);
+    _parameters?.accept(visitor);
   }
 }
 
@@ -5473,7 +5513,8 @@
   NodeList<SimpleIdentifier> get hiddenNames => _hiddenNames;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitHideCombinator(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitHideCombinator(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -5613,13 +5654,14 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitIfStatement(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitIfStatement(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_condition, visitor);
-    _safelyVisitChild(_thenStatement, visitor);
-    _safelyVisitChild(_elseStatement, visitor);
+    _condition?.accept(visitor);
+    _thenStatement?.accept(visitor);
+    _elseStatement?.accept(visitor);
   }
 }
 
@@ -5664,7 +5706,8 @@
   NodeList<TypeName> get interfaces => _interfaces;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitImplementsClause(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitImplementsClause(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -5754,12 +5797,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitImportDirective(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitImportDirective(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_prefix, visitor);
+    _prefix?.accept(visitor);
     combinators.accept(visitor);
   }
 }
@@ -5946,7 +5990,8 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitIndexExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitIndexExpression(this);
 
   @override
   bool inGetterContext() {
@@ -5978,8 +6023,8 @@
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_target, visitor);
-    _safelyVisitChild(_index, visitor);
+    _target?.accept(visitor);
+    _index?.accept(visitor);
   }
 }
 
@@ -6062,12 +6107,13 @@
   int get precedence => 16;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitInstanceCreationExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitInstanceCreationExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_constructorName, visitor);
-    _safelyVisitChild(_argumentList, visitor);
+    _constructorName?.accept(visitor);
+    _argumentList?.accept(visitor);
   }
 }
 
@@ -6113,7 +6159,8 @@
   Token get endToken => literal;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitIntegerLiteral(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitIntegerLiteral(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -6194,11 +6241,12 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitInterpolationExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitInterpolationExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
+    _expression?.accept(visitor);
   }
 }
 
@@ -6251,7 +6299,8 @@
   Token get endToken => contents;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitInterpolationString(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitInterpolationString(this);
 
   @override
   void visitChildren(AstVisitor visitor) {}
@@ -6376,12 +6425,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitIsExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitIsExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
-    _safelyVisitChild(_type, visitor);
+    _expression?.accept(visitor);
+    _type?.accept(visitor);
   }
 }
 
@@ -6441,12 +6491,13 @@
   Statement get unlabeled => _statement.unlabeled;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitLabeledStatement(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitLabeledStatement(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     _labels.accept(visitor);
-    _safelyVisitChild(_statement, visitor);
+    _statement?.accept(visitor);
   }
 }
 
@@ -6493,11 +6544,12 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitLabel(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitLabel(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_label, visitor);
+    _label?.accept(visitor);
   }
 }
 
@@ -6558,12 +6610,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitLibraryDirective(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitLibraryDirective(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_name, visitor);
+    _name?.accept(visitor);
   }
 }
 
@@ -6628,7 +6681,8 @@
   Element get staticElement => null;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitLibraryIdentifier(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitLibraryIdentifier(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -6698,7 +6752,8 @@
   Token get endToken => rightBracket;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitListLiteral(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitListLiteral(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -6802,12 +6857,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitMapLiteralEntry(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitMapLiteralEntry(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_key, visitor);
-    _safelyVisitChild(_value, visitor);
+    _key?.accept(visitor);
+    _value?.accept(visitor);
   }
 }
 
@@ -6873,7 +6929,8 @@
   NodeList<MapLiteralEntry> get entries => _entries;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitMapLiteral(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitMapLiteral(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -7019,7 +7076,9 @@
 
   @override
   Token get firstTokenAfterCommentAndMetadata {
-    if (modifierKeyword != null) {
+    if (externalKeyword != null) {
+      return externalKeyword;
+    } else if (modifierKeyword != null) {
       return modifierKeyword;
     } else if (_returnType != null) {
       return _returnType.beginToken;
@@ -7089,16 +7148,17 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitMethodDeclaration(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitMethodDeclaration(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_returnType, visitor);
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_typeParameters, visitor);
-    _safelyVisitChild(_parameters, visitor);
-    _safelyVisitChild(_body, visitor);
+    _returnType?.accept(visitor);
+    _name?.accept(visitor);
+    _typeParameters?.accept(visitor);
+    _parameters?.accept(visitor);
+    _body?.accept(visitor);
   }
 }
 
@@ -7210,14 +7270,15 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitMethodInvocation(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitMethodInvocation(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_target, visitor);
-    _safelyVisitChild(_methodName, visitor);
-    _safelyVisitChild(_typeArguments, visitor);
-    _safelyVisitChild(_argumentList, visitor);
+    _target?.accept(visitor);
+    _methodName?.accept(visitor);
+    _typeArguments?.accept(visitor);
+    _argumentList?.accept(visitor);
   }
 }
 
@@ -7316,12 +7377,13 @@
   int get precedence => 0;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitNamedExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitNamedExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_expression, visitor);
+    _name?.accept(visitor);
+    _expression?.accept(visitor);
   }
 }
 
@@ -7436,11 +7498,12 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitNativeClause(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitNativeClause(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_name, visitor);
+    _name?.accept(visitor);
   }
 }
 
@@ -7501,11 +7564,12 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitNativeFunctionBody(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitNativeFunctionBody(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_stringLiteral, visitor);
+    _stringLiteral?.accept(visitor);
   }
 }
 
@@ -7729,7 +7793,7 @@
     // they often need to visit other nodes before visiting the identifier.
     //
     if (_commentIsBeforeAnnotations()) {
-      _safelyVisitChild(_comment, visitor);
+      _comment?.accept(visitor);
       _metadata.accept(visitor);
     } else {
       for (AstNode child in sortedCommentAndAnnotations) {
@@ -7777,7 +7841,8 @@
   Token get endToken => literal;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitNullLiteral(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitNullLiteral(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -7840,11 +7905,12 @@
   int get precedence => 15;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitParenthesizedExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitParenthesizedExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
+    _expression?.accept(visitor);
   }
 }
 
@@ -7893,7 +7959,8 @@
   CompilationUnitElement get uriElement => element as CompilationUnitElement;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitPartDirective(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitPartDirective(this);
 }
 
 /**
@@ -7967,12 +8034,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitPartOfDirective(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitPartOfDirective(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_libraryName, visitor);
+    _libraryName?.accept(visitor);
   }
 }
 
@@ -8084,11 +8152,12 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitPostfixExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitPostfixExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_operand, visitor);
+    _operand?.accept(visitor);
   }
 }
 
@@ -8197,12 +8266,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitPrefixedIdentifier(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitPrefixedIdentifier(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_prefix, visitor);
-    _safelyVisitChild(_identifier, visitor);
+    _prefix?.accept(visitor);
+    _identifier?.accept(visitor);
   }
 }
 
@@ -8309,11 +8379,12 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitPrefixExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitPrefixExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_operand, visitor);
+    _operand?.accept(visitor);
   }
 }
 
@@ -8409,12 +8480,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitPropertyAccess(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitPropertyAccess(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_target, visitor);
-    _safelyVisitChild(_propertyName, visitor);
+    _target?.accept(visitor);
+    _propertyName?.accept(visitor);
   }
 }
 
@@ -8497,13 +8569,13 @@
   Token get endToken => _argumentList.endToken;
 
   @override
-  accept(AstVisitor visitor) =>
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
       visitor.visitRedirectingConstructorInvocation(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_constructorName, visitor);
-    _safelyVisitChild(_argumentList, visitor);
+    _constructorName?.accept(visitor);
+    _argumentList?.accept(visitor);
   }
 }
 
@@ -8538,7 +8610,8 @@
   int get precedence => 0;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitRethrowExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitRethrowExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -8597,11 +8670,12 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitReturnStatement(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitReturnStatement(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
+    _expression?.accept(visitor);
   }
 }
 
@@ -8632,7 +8706,8 @@
   Token get endToken => scriptTag;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitScriptTag(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitScriptTag(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -8673,7 +8748,8 @@
   NodeList<SimpleIdentifier> get shownNames => _shownNames;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitShowCombinator(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitShowCombinator(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -8752,13 +8828,14 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitSimpleFormalParameter(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitSimpleFormalParameter(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_type, visitor);
-    _safelyVisitChild(identifier, visitor);
+    _type?.accept(visitor);
+    identifier?.accept(visitor);
   }
 }
 
@@ -8865,7 +8942,8 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitSimpleIdentifier(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitSimpleIdentifier(this);
 
   @override
   bool inDeclarationContext() {
@@ -9131,7 +9209,8 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitSimpleStringLiteral(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitSimpleStringLiteral(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -9241,7 +9320,8 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitStringInterpolation(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitStringInterpolation(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -9457,12 +9537,13 @@
   Token get endToken => _argumentList.endToken;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitSuperConstructorInvocation(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitSuperConstructorInvocation(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_constructorName, visitor);
-    _safelyVisitChild(_argumentList, visitor);
+    _constructorName?.accept(visitor);
+    _argumentList?.accept(visitor);
   }
 }
 
@@ -9496,7 +9577,8 @@
   int get precedence => 16;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitSuperExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitSuperExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -9543,12 +9625,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitSwitchCase(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitSwitchCase(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     labels.accept(visitor);
-    _safelyVisitChild(_expression, visitor);
+    _expression?.accept(visitor);
     statements.accept(visitor);
   }
 }
@@ -9576,7 +9659,8 @@
     ..addAll(statements);
 
   @override
-  accept(AstVisitor visitor) => visitor.visitSwitchDefault(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitSwitchDefault(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -9733,11 +9817,12 @@
   NodeList<SwitchMember> get members => _members;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitSwitchStatement(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitSwitchStatement(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
+    _expression?.accept(visitor);
     _members.accept(visitor);
   }
 }
@@ -9777,7 +9862,8 @@
   Token get endToken => components[components.length - 1];
 
   @override
-  accept(AstVisitor visitor) => visitor.visitSymbolLiteral(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitSymbolLiteral(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -9815,7 +9901,8 @@
   int get precedence => 16;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitThisExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitThisExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -9874,11 +9961,12 @@
   int get precedence => 0;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitThrowExpression(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitThrowExpression(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
+    _expression?.accept(visitor);
   }
 }
 
@@ -9934,12 +10022,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitTopLevelVariableDeclaration(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitTopLevelVariableDeclaration(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_variableList, visitor);
+    _variableList?.accept(visitor);
   }
 }
 
@@ -10035,13 +10124,14 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitTryStatement(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitTryStatement(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_body, visitor);
+    _body?.accept(visitor);
     _catchClauses.accept(visitor);
-    _safelyVisitChild(_finallyBlock, visitor);
+    _finallyBlock?.accept(visitor);
   }
 }
 
@@ -10130,7 +10220,8 @@
   Token get endToken => rightBracket;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitTypeArgumentList(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitTypeArgumentList(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -10180,7 +10271,7 @@
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_typeArguments, visitor);
+    _typeArguments?.accept(visitor);
   }
 }
 
@@ -10260,12 +10351,13 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitTypeName(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitTypeName(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_typeArguments, visitor);
+    _name?.accept(visitor);
+    _typeArguments?.accept(visitor);
   }
 }
 
@@ -10342,13 +10434,14 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitTypeParameter(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitTypeParameter(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_bound, visitor);
+    _name?.accept(visitor);
+    _bound?.accept(visitor);
   }
 }
 
@@ -10398,7 +10491,8 @@
   NodeList<TypeParameter> get typeParameters => _typeParameters;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitTypeParameterList(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitTypeParameterList(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -10480,7 +10574,7 @@
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_uri, visitor);
+    _uri?.accept(visitor);
   }
 }
 
@@ -10620,13 +10714,14 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitVariableDeclaration(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitVariableDeclaration(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_initializer, visitor);
+    _name?.accept(visitor);
+    _initializer?.accept(visitor);
   }
 }
 
@@ -10715,12 +10810,13 @@
   NodeList<VariableDeclaration> get variables => _variables;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitVariableDeclarationList(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitVariableDeclarationList(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
-    _safelyVisitChild(_type, visitor);
+    _type?.accept(visitor);
     _variables.accept(visitor);
   }
 }
@@ -10771,11 +10867,12 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitVariableDeclarationStatement(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitVariableDeclarationStatement(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_variableList, visitor);
+    _variableList?.accept(visitor);
   }
 }
 
@@ -10851,12 +10948,13 @@
   Token get endToken => _body.endToken;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitWhileStatement(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitWhileStatement(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_condition, visitor);
-    _safelyVisitChild(_body, visitor);
+    _condition?.accept(visitor);
+    _body?.accept(visitor);
   }
 }
 
@@ -10900,7 +10998,8 @@
   NodeList<TypeName> get mixinTypes => _mixinTypes;
 
   @override
-  accept(AstVisitor visitor) => visitor.visitWithClause(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitWithClause(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
@@ -10976,10 +11075,11 @@
   }
 
   @override
-  accept(AstVisitor visitor) => visitor.visitYieldStatement(this);
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+      visitor.visitYieldStatement(this);
 
   @override
   void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
+    _expression?.accept(visitor);
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 331d6d9..3628346 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -60,22 +60,23 @@
   /**
    * Return a clone of the given [node].
    */
-  AstNode cloneNode(AstNode node) {
+  AstNode/*=E*/ cloneNode/*<E extends AstNode>*/(AstNode/*=E*/ node) {
     if (node == null) {
       return null;
     }
-    return node.accept(this) as AstNode;
+    return node.accept(this) as AstNode/*=E*/;
   }
 
   /**
    * Return a list containing cloned versions of the nodes in the given list of
    * [nodes].
    */
-  List<AstNode> cloneNodeList(NodeList nodes) {
+  List<AstNode/*=E*/ > cloneNodeList/*<E extends AstNode>*/(
+      NodeList/*<E>*/ nodes) {
     int count = nodes.length;
-    List clonedNodes = new List();
+    List/*<E>*/ clonedNodes = new List/*<E>*/();
     for (int i = 0; i < count; i++) {
-      clonedNodes.add((nodes[i]).accept(this) as AstNode);
+      clonedNodes.add((nodes[i]).accept(this) as AstNode/*=E*/);
     }
     return clonedNodes;
   }
@@ -2588,6 +2589,7 @@
  * mapping the old token stream to a new token stream, and preserving resolution
  * results.
  */
+@deprecated
 class IncrementalAstCloner implements AstVisitor<AstNode> {
   /**
    * The node to be replaced during the cloning process.
@@ -3101,18 +3103,21 @@
           _mapToken(node.implementsKeyword), _cloneNodeList(node.interfaces));
 
   @override
-  ImportDirective visitImportDirective(ImportDirective node) =>
-      new ImportDirective(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.keyword),
-          _cloneNode(node.uri),
-          _cloneNodeList(node.configurations),
-          _mapToken(node.deferredKeyword),
-          _mapToken(node.asKeyword),
-          _cloneNode(node.prefix),
-          _cloneNodeList(node.combinators),
-          _mapToken(node.semicolon));
+  ImportDirective visitImportDirective(ImportDirective node) {
+    ImportDirective copy = new ImportDirective(
+        _cloneNode(node.documentationComment),
+        _cloneNodeList(node.metadata),
+        _mapToken(node.keyword),
+        _cloneNode(node.uri),
+        _cloneNodeList(node.configurations),
+        _mapToken(node.deferredKeyword),
+        _mapToken(node.asKeyword),
+        _cloneNode(node.prefix),
+        _cloneNodeList(node.combinators),
+        _mapToken(node.semicolon));
+    copy.element = node.element;
+    return copy;
+  }
 
   @override
   IndexExpression visitIndexExpression(IndexExpression node) {
@@ -3190,13 +3195,16 @@
           _cloneNodeList(node.labels), _cloneNode(node.statement));
 
   @override
-  LibraryDirective visitLibraryDirective(LibraryDirective node) =>
-      new LibraryDirective(
-          _cloneNode(node.documentationComment),
-          _cloneNodeList(node.metadata),
-          _mapToken(node.libraryKeyword),
-          _cloneNode(node.name),
-          _mapToken(node.semicolon));
+  LibraryDirective visitLibraryDirective(LibraryDirective node) {
+    LibraryDirective copy = new LibraryDirective(
+        _cloneNode(node.documentationComment),
+        _cloneNodeList(node.metadata),
+        _mapToken(node.libraryKeyword),
+        _cloneNode(node.name),
+        _mapToken(node.semicolon));
+    copy.element = node.element;
+    return copy;
+  }
 
   @override
   LibraryIdentifier visitLibraryIdentifier(LibraryIdentifier node) {
@@ -3607,19 +3615,19 @@
       _cloneNode(node.expression),
       _mapToken(node.semicolon));
 
-  AstNode _cloneNode(AstNode node) {
+  AstNode/*=E*/ _cloneNode/*<E extends AstNode>*/(AstNode/*=E*/ node) {
     if (node == null) {
       return null;
     }
     if (identical(node, _oldNode)) {
-      return _newNode;
+      return _newNode as AstNode/*=E*/;
     }
-    return node.accept(this) as AstNode;
+    return node.accept(this) as AstNode/*=E*/;
   }
 
-  List _cloneNodeList(NodeList nodes) {
-    List clonedNodes = new List();
-    for (AstNode node in nodes) {
+  List/*<E>*/ _cloneNodeList/*<E extends AstNode>*/(NodeList/*<E>*/ nodes) {
+    List/*<E>*/ clonedNodes = new List/*<E>*/();
+    for (AstNode/*=E*/ node in nodes) {
       clonedNodes.add(_cloneNode(node));
     }
     return clonedNodes;
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
new file mode 100644
index 0000000..5484bba
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -0,0 +1,2003 @@
+// 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.constant.evaluation;
+
+import 'dart:collection';
+
+import 'package:analyzer/context/declared_variables.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/constant/value.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/constant/utilities.dart';
+import 'package:analyzer/src/dart/constant/value.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/engine.dart'
+    show AnalysisEngine, RecordingErrorListener;
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_core.dart';
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
+import 'package:analyzer/src/generated/source.dart' show Source;
+import 'package:analyzer/src/generated/type_system.dart'
+    show TypeSystem, TypeSystemImpl;
+import 'package:analyzer/src/generated/utilities_collection.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart' show ParameterKind;
+import 'package:analyzer/src/task/dart.dart';
+
+/**
+ * Helper class encapsulating the methods for evaluating constants and
+ * constant instance creation expressions.
+ */
+class ConstantEvaluationEngine {
+  /**
+   * Parameter to "fromEnvironment" methods that denotes the default value.
+   */
+  static String _DEFAULT_VALUE_PARAM = "defaultValue";
+
+  /**
+   * Source of RegExp matching any public identifier.
+   * From sdk/lib/internal/symbol.dart.
+   */
+  static String _PUBLIC_IDENTIFIER_RE =
+      "(?!${ConstantValueComputer._RESERVED_WORD_RE}\\b(?!\\\$))[a-zA-Z\$][\\w\$]*";
+
+  /**
+   * RegExp that validates a non-empty non-private symbol.
+   * From sdk/lib/internal/symbol.dart.
+   */
+  static RegExp _PUBLIC_SYMBOL_PATTERN = new RegExp(
+      "^(?:${ConstantValueComputer._OPERATOR_RE}\$|$_PUBLIC_IDENTIFIER_RE(?:=?\$|[.](?!\$)))+?\$");
+
+  /**
+   * The type provider used to access the known types.
+   */
+  final TypeProvider typeProvider;
+
+  /**
+   * The type system.  This is used to guess the types of constants when their
+   * exact value is unknown.
+   */
+  final TypeSystem typeSystem;
+
+  /**
+   * The set of variables declared on the command line using '-D'.
+   */
+  final DeclaredVariables _declaredVariables;
+
+  /**
+   * Validator used to verify correct dependency analysis when running unit
+   * tests.
+   */
+  final ConstantEvaluationValidator validator;
+
+  /**
+   * Initialize a newly created [ConstantEvaluationEngine].  The [typeProvider]
+   * is used to access known types.  [_declaredVariables] is the set of
+   * variables declared on the command line using '-D'.  The [validator], if
+   * given, is used to verify correct dependency analysis when running unit
+   * tests.
+   */
+  ConstantEvaluationEngine(this.typeProvider, this._declaredVariables,
+      {ConstantEvaluationValidator validator, TypeSystem typeSystem})
+      : validator = validator != null
+            ? validator
+            : new ConstantEvaluationValidator_ForProduction(),
+        typeSystem = typeSystem != null ? typeSystem : new TypeSystemImpl();
+
+  /**
+   * Check that the arguments to a call to fromEnvironment() are correct. The
+   * [arguments] are the AST nodes of the arguments. The [argumentValues] are
+   * the values of the unnamed arguments. The [namedArgumentValues] are the
+   * values of the named arguments. The [expectedDefaultValueType] is the
+   * allowed type of the "defaultValue" parameter (if present). Note:
+   * "defaultValue" is always allowed to be null. Return `true` if the arguments
+   * are correct, `false` if there is an error.
+   */
+  bool checkFromEnvironmentArguments(
+      NodeList<Expression> arguments,
+      List<DartObjectImpl> argumentValues,
+      HashMap<String, DartObjectImpl> namedArgumentValues,
+      InterfaceType expectedDefaultValueType) {
+    int argumentCount = arguments.length;
+    if (argumentCount < 1 || argumentCount > 2) {
+      return false;
+    }
+    if (arguments[0] is NamedExpression) {
+      return false;
+    }
+    if (!identical(argumentValues[0].type, typeProvider.stringType)) {
+      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))) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Check that the arguments to a call to Symbol() are correct. The [arguments]
+   * are the AST nodes of the arguments. The [argumentValues] are the values of
+   * the unnamed arguments. The [namedArgumentValues] are the values of the
+   * named arguments. Return `true` if the arguments are correct, `false` if
+   * there is an error.
+   */
+  bool checkSymbolArguments(
+      NodeList<Expression> arguments,
+      List<DartObjectImpl> argumentValues,
+      HashMap<String, DartObjectImpl> namedArgumentValues) {
+    if (arguments.length != 1) {
+      return false;
+    }
+    if (arguments[0] is NamedExpression) {
+      return false;
+    }
+    if (!identical(argumentValues[0].type, typeProvider.stringType)) {
+      return false;
+    }
+    String name = argumentValues[0].toStringValue();
+    return isValidPublicSymbol(name);
+  }
+
+  /**
+   * Compute the constant value associated with the given [constant].
+   */
+  void computeConstantValue(ConstantEvaluationTarget constant) {
+    validator.beforeComputeValue(constant);
+    if (constant is ParameterElementImpl) {
+      Expression defaultValue = constant.constantInitializer;
+      if (defaultValue != null) {
+        RecordingErrorListener errorListener = new RecordingErrorListener();
+        ErrorReporter errorReporter =
+            new ErrorReporter(errorListener, constant.source);
+        DartObjectImpl dartObject =
+            defaultValue.accept(new ConstantVisitor(this, errorReporter));
+        constant.evaluationResult =
+            new EvaluationResultImpl(dartObject, errorListener.errors);
+      }
+    } else if (constant is VariableElementImpl) {
+      Expression constantInitializer = constant.constantInitializer;
+      if (constantInitializer != null) {
+        RecordingErrorListener errorListener = new RecordingErrorListener();
+        ErrorReporter errorReporter =
+            new ErrorReporter(errorListener, constant.source);
+        DartObjectImpl dartObject = constantInitializer
+            .accept(new ConstantVisitor(this, errorReporter));
+        // Only check the type for truly const declarations (don't check final
+        // fields with initializers, since their types may be generic.  The type
+        // of the final field will be checked later, when the constructor is
+        // invoked).
+        if (dartObject != null && constant.isConst) {
+          if (!runtimeTypeMatch(dartObject, constant.type)) {
+            errorReporter.reportErrorForElement(
+                CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
+                constant,
+                [dartObject.type, constant.type]);
+          }
+        }
+        constant.evaluationResult =
+            new EvaluationResultImpl(dartObject, errorListener.errors);
+      }
+    } else if (constant is ConstructorElement) {
+      if (constant.isConst) {
+        // No evaluation needs to be done; constructor declarations are only in
+        // the dependency graph to ensure that any constants referred to in
+        // initializer lists and parameter defaults are evaluated before
+        // invocations of the constructor.  However we do need to annotate the
+        // element as being free of constant evaluation cycles so that later
+        // code will know that it is safe to evaluate.
+        (constant as ConstructorElementImpl).isCycleFree = true;
+      }
+    } else if (constant is ElementAnnotationImpl) {
+      Annotation constNode = constant.annotationAst;
+      Element element = constant.element;
+      if (element is PropertyAccessorElement &&
+          element.variable is VariableElementImpl) {
+        // The annotation is a reference to a compile-time constant variable.
+        // Just copy the evaluation result.
+        VariableElementImpl variableElement =
+            element.variable as VariableElementImpl;
+        if (variableElement.evaluationResult != null) {
+          constant.evaluationResult = variableElement.evaluationResult;
+        } else {
+          // This could happen in the event that the annotation refers to a
+          // non-constant.  The error is detected elsewhere, so just silently
+          // ignore it here.
+          constant.evaluationResult = new EvaluationResultImpl(null);
+        }
+      } else if (element is ConstructorElementImpl &&
+          element.isConst &&
+          constNode.arguments != null) {
+        RecordingErrorListener errorListener = new RecordingErrorListener();
+        ErrorReporter errorReporter =
+            new ErrorReporter(errorListener, constant.source);
+        ConstantVisitor constantVisitor =
+            new ConstantVisitor(this, errorReporter);
+        DartObjectImpl result = evaluateConstructorCall(
+            constNode,
+            constNode.arguments.arguments,
+            element,
+            constantVisitor,
+            errorReporter);
+        constant.evaluationResult =
+            new EvaluationResultImpl(result, errorListener.errors);
+      } else {
+        // This may happen for invalid code (e.g. failing to pass arguments
+        // to an annotation which references a const constructor).  The error
+        // is detected elsewhere, so just silently ignore it here.
+        constant.evaluationResult = new EvaluationResultImpl(null);
+      }
+    } else if (constant is VariableElement) {
+      // constant is a VariableElement but not a VariableElementImpl.  This can
+      // happen sometimes in the case of invalid user code (for example, a
+      // constant expression that refers to a non-static field inside a generic
+      // class will wind up referring to a FieldMember).  The error is detected
+      // elsewhere, so just silently ignore it here.
+    } else {
+      // Should not happen.
+      assert(false);
+      AnalysisEngine.instance.logger.logError(
+          "Constant value computer trying to compute the value of a node of type ${constant.runtimeType}");
+      return;
+    }
+  }
+
+  /**
+   * Determine which constant elements need to have their values computed
+   * prior to computing the value of [constant], and report them using
+   * [callback].
+   */
+  void computeDependencies(
+      ConstantEvaluationTarget constant, ReferenceFinderCallback callback) {
+    ReferenceFinder referenceFinder = new ReferenceFinder(callback);
+    if (constant is ConstructorElement) {
+      constant = getConstructorImpl(constant);
+    }
+    if (constant is VariableElementImpl) {
+      Expression initializer = constant.constantInitializer;
+      if (initializer != null) {
+        initializer.accept(referenceFinder);
+      }
+    } else if (constant is ConstructorElementImpl) {
+      if (constant.isConst) {
+        constant.isCycleFree = false;
+        ConstructorElement redirectedConstructor =
+            getConstRedirectedConstructor(constant);
+        if (redirectedConstructor != null) {
+          ConstructorElement redirectedConstructorBase =
+              getConstructorImpl(redirectedConstructor);
+          callback(redirectedConstructorBase);
+          return;
+        } else if (constant.isFactory) {
+          // Factory constructor, but getConstRedirectedConstructor returned
+          // null.  This can happen if we're visiting one of the special external
+          // const factory constructors in the SDK, or if the code contains
+          // errors (such as delegating to a non-const constructor, or delegating
+          // to a constructor that can't be resolved).  In any of these cases,
+          // we'll evaluate calls to this constructor without having to refer to
+          // any other constants.  So we don't need to report any dependencies.
+          return;
+        }
+        bool superInvocationFound = false;
+        List<ConstructorInitializer> initializers =
+            constant.constantInitializers;
+        for (ConstructorInitializer initializer in initializers) {
+          if (initializer is SuperConstructorInvocation) {
+            superInvocationFound = true;
+          }
+          initializer.accept(referenceFinder);
+        }
+        if (!superInvocationFound) {
+          // No explicit superconstructor invocation found, so we need to
+          // manually insert a reference to the implicit superconstructor.
+          InterfaceType superclass =
+              (constant.returnType as InterfaceType).superclass;
+          if (superclass != null && !superclass.isObject) {
+            ConstructorElement unnamedConstructor =
+                getConstructorImpl(superclass.element.unnamedConstructor);
+            if (unnamedConstructor != null) {
+              callback(unnamedConstructor);
+            }
+          }
+        }
+        for (FieldElement field in constant.enclosingElement.fields) {
+          // Note: non-static const isn't allowed but we handle it anyway so
+          // that we won't be confused by incorrect code.
+          if ((field.isFinal || field.isConst) &&
+              !field.isStatic &&
+              field.initializer != null) {
+            callback(field);
+          }
+        }
+        for (ParameterElement parameterElement in constant.parameters) {
+          callback(parameterElement);
+        }
+      }
+    } else if (constant is ElementAnnotationImpl) {
+      Annotation constNode = constant.annotationAst;
+      Element element = constant.element;
+      if (element is PropertyAccessorElement &&
+          element.variable is VariableElementImpl) {
+        // The annotation is a reference to a compile-time constant variable,
+        // so it depends on the variable.
+        callback(element.variable);
+      } else if (element is ConstructorElementImpl) {
+        // The annotation is a constructor invocation, so it depends on the
+        // constructor.
+        callback(element);
+      } else {
+        // This could happen in the event of invalid code.  The error will be
+        // reported at constant evaluation time.
+      }
+      if (constNode.arguments != null) {
+        constNode.arguments.accept(referenceFinder);
+      }
+    } else if (constant is VariableElement) {
+      // constant is a VariableElement but not a VariableElementImpl.  This can
+      // happen sometimes in the case of invalid user code (for example, a
+      // constant expression that refers to a non-static field inside a generic
+      // class will wind up referring to a FieldMember).  So just don't bother
+      // computing any dependencies.
+    } else {
+      // Should not happen.
+      assert(false);
+      AnalysisEngine.instance.logger.logError(
+          "Constant value computer trying to compute the value of a node of type ${constant.runtimeType}");
+    }
+  }
+
+  /**
+   * Evaluate a call to fromEnvironment() on the bool, int, or String class. The
+   * [environmentValue] is the value fetched from the environment. The
+   * [builtInDefaultValue] is the value that should be used as the default if no
+   * "defaultValue" argument appears in [namedArgumentValues]. The
+   * [namedArgumentValues] are the values of the named parameters passed to
+   * fromEnvironment(). Return a [DartObjectImpl] object corresponding to the
+   * evaluated result.
+   */
+  DartObjectImpl computeValueFromEnvironment(
+      DartObject environmentValue,
+      DartObjectImpl builtInDefaultValue,
+      HashMap<String, DartObjectImpl> namedArgumentValues) {
+    DartObjectImpl value = environmentValue as DartObjectImpl;
+    if (value.isUnknown || value.isNull) {
+      // The name either doesn't exist in the environment or we couldn't parse
+      // the corresponding value.
+      // If the code supplied an explicit default, use it.
+      if (namedArgumentValues.containsKey(_DEFAULT_VALUE_PARAM)) {
+        value = namedArgumentValues[_DEFAULT_VALUE_PARAM];
+      } else if (value.isNull) {
+        // The code didn't supply an explicit default.
+        // The name exists in the environment but we couldn't parse the
+        // corresponding value.
+        // So use the built-in default value, because this is what the VM does.
+        value = builtInDefaultValue;
+      } else {
+        // The code didn't supply an explicit default.
+        // The name doesn't exist in the environment.
+        // The VM would use the built-in default value, but we don't want to do
+        // that for analysis because it's likely to lead to cascading errors.
+        // So just leave [value] in the unknown state.
+      }
+    }
+    return value;
+  }
+
+  DartObjectImpl evaluateConstructorCall(
+      AstNode node,
+      NodeList<Expression> arguments,
+      ConstructorElement constructor,
+      ConstantVisitor constantVisitor,
+      ErrorReporter errorReporter) {
+    if (!getConstructorImpl(constructor).isCycleFree) {
+      // It's not safe to evaluate this constructor, so bail out.
+      // TODO(paulberry): ensure that a reasonable error message is produced
+      // in this case, as well as other cases involving constant expression
+      // circularities (e.g. "compile-time constant expression depends on
+      // itself")
+      return new DartObjectImpl.validWithUnknownValue(constructor.returnType);
+    }
+    int argumentCount = arguments.length;
+    List<DartObjectImpl> argumentValues =
+        new List<DartObjectImpl>(argumentCount);
+    List<Expression> argumentNodes = new List<Expression>(argumentCount);
+    HashMap<String, DartObjectImpl> namedArgumentValues =
+        new HashMap<String, DartObjectImpl>();
+    HashMap<String, NamedExpression> namedArgumentNodes =
+        new HashMap<String, NamedExpression>();
+    for (int i = 0; i < argumentCount; i++) {
+      Expression argument = arguments[i];
+      if (argument is NamedExpression) {
+        String name = argument.name.label.name;
+        namedArgumentValues[name] =
+            constantVisitor._valueOf(argument.expression);
+        namedArgumentNodes[name] = argument;
+        argumentValues[i] = typeProvider.nullObject;
+      } else {
+        argumentValues[i] = constantVisitor._valueOf(argument);
+        argumentNodes[i] = argument;
+      }
+    }
+    constructor = followConstantRedirectionChain(constructor);
+    InterfaceType definingClass = constructor.returnType as InterfaceType;
+    if (constructor.isFactory) {
+      // We couldn't find a non-factory constructor.
+      // See if it's because we reached an external const factory constructor
+      // that we can emulate.
+      if (constructor.name == "fromEnvironment") {
+        if (!checkFromEnvironmentArguments(
+            arguments, argumentValues, namedArgumentValues, definingClass)) {
+          errorReporter.reportErrorForNode(
+              CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
+          return null;
+        }
+        String variableName =
+            argumentCount < 1 ? null : argumentValues[0].toStringValue();
+        if (identical(definingClass, typeProvider.boolType)) {
+          DartObject valueFromEnvironment;
+          valueFromEnvironment =
+              _declaredVariables.getBool(typeProvider, variableName);
+          return computeValueFromEnvironment(
+              valueFromEnvironment,
+              new DartObjectImpl(typeProvider.boolType, BoolState.FALSE_STATE),
+              namedArgumentValues);
+        } else if (identical(definingClass, typeProvider.intType)) {
+          DartObject valueFromEnvironment;
+          valueFromEnvironment =
+              _declaredVariables.getInt(typeProvider, variableName);
+          return computeValueFromEnvironment(
+              valueFromEnvironment,
+              new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE),
+              namedArgumentValues);
+        } else if (identical(definingClass, typeProvider.stringType)) {
+          DartObject valueFromEnvironment;
+          valueFromEnvironment =
+              _declaredVariables.getString(typeProvider, variableName);
+          return computeValueFromEnvironment(
+              valueFromEnvironment,
+              new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE),
+              namedArgumentValues);
+        }
+      } else if (constructor.name == "" &&
+          identical(definingClass, typeProvider.symbolType) &&
+          argumentCount == 1) {
+        if (!checkSymbolArguments(
+            arguments, argumentValues, namedArgumentValues)) {
+          errorReporter.reportErrorForNode(
+              CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
+          return null;
+        }
+        String argumentValue = argumentValues[0].toStringValue();
+        return new DartObjectImpl(
+            definingClass, new SymbolState(argumentValue));
+      }
+      // Either it's an external const factory constructor that we can't
+      // emulate, or an error occurred (a cycle, or a const constructor trying
+      // to delegate to a non-const constructor).
+      // In the former case, the best we can do is consider it an unknown value.
+      // In the latter case, the error has already been reported, so considering
+      // it an unknown value will suppress further errors.
+      return new DartObjectImpl.validWithUnknownValue(definingClass);
+    }
+    ConstructorElementImpl constructorBase = getConstructorImpl(constructor);
+    validator.beforeGetConstantInitializers(constructorBase);
+    List<ConstructorInitializer> initializers =
+        constructorBase.constantInitializers;
+    if (initializers == null) {
+      // This can happen in some cases where there are compile errors in the
+      // code being analyzed (for example if the code is trying to create a
+      // const instance using a non-const constructor, or the node we're
+      // visiting is involved in a cycle).  The error has already been reported,
+      // so consider it an unknown value to suppress further errors.
+      return new DartObjectImpl.validWithUnknownValue(definingClass);
+    }
+    HashMap<String, DartObjectImpl> fieldMap =
+        new HashMap<String, DartObjectImpl>();
+    // Start with final fields that are initialized at their declaration site.
+    for (FieldElement field in constructor.enclosingElement.fields) {
+      if ((field.isFinal || field.isConst) &&
+          !field.isStatic &&
+          field is ConstFieldElementImpl) {
+        validator.beforeGetFieldEvaluationResult(field);
+        EvaluationResultImpl evaluationResult = field.evaluationResult;
+        // It is possible that the evaluation result is null.
+        // This happens for example when we have duplicate fields.
+        // class Test {final x = 1; final x = 2; const Test();}
+        if (evaluationResult == null) {
+          continue;
+        }
+        // Match the value and the type.
+        DartType fieldType =
+            FieldMember.from(field, constructor.returnType).type;
+        DartObjectImpl fieldValue = evaluationResult.value;
+        if (fieldValue != null && !runtimeTypeMatch(fieldValue, fieldType)) {
+          errorReporter.reportErrorForNode(
+              CheckedModeCompileTimeErrorCode
+                  .CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
+              node,
+              [fieldValue.type, field.name, fieldType]);
+        }
+        fieldMap[field.name] = fieldValue;
+      }
+    }
+    // Now evaluate the constructor declaration.
+    HashMap<String, DartObjectImpl> parameterMap =
+        new HashMap<String, DartObjectImpl>();
+    List<ParameterElement> parameters = constructor.parameters;
+    int parameterCount = parameters.length;
+    for (int i = 0; i < parameterCount; i++) {
+      ParameterElement parameter = parameters[i];
+      ParameterElement baseParameter = parameter;
+      while (baseParameter is ParameterMember) {
+        baseParameter = (baseParameter as ParameterMember).baseElement;
+      }
+      DartObjectImpl argumentValue = null;
+      AstNode errorTarget = null;
+      if (baseParameter.parameterKind == ParameterKind.NAMED) {
+        argumentValue = namedArgumentValues[baseParameter.name];
+        errorTarget = namedArgumentNodes[baseParameter.name];
+      } else if (i < argumentCount) {
+        argumentValue = argumentValues[i];
+        errorTarget = argumentNodes[i];
+      }
+      if (errorTarget == null) {
+        // No argument node that we can direct error messages to, because we
+        // are handling an optional parameter that wasn't specified.  So just
+        // direct error messages to the constructor call.
+        errorTarget = node;
+      }
+      if (argumentValue == null && baseParameter is ParameterElementImpl) {
+        // The parameter is an optional positional parameter for which no value
+        // was provided, so use the default value.
+        validator.beforeGetParameterDefault(baseParameter);
+        EvaluationResultImpl evaluationResult = baseParameter.evaluationResult;
+        if (evaluationResult == null) {
+          // No default was provided, so the default value is null.
+          argumentValue = typeProvider.nullObject;
+        } else if (evaluationResult.value != null) {
+          argumentValue = evaluationResult.value;
+        }
+      }
+      if (argumentValue != null) {
+        if (!runtimeTypeMatch(argumentValue, parameter.type)) {
+          errorReporter.reportErrorForNode(
+              CheckedModeCompileTimeErrorCode
+                  .CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+              errorTarget,
+              [argumentValue.type, parameter.type]);
+        }
+        if (baseParameter.isInitializingFormal) {
+          FieldElement field = (parameter as FieldFormalParameterElement).field;
+          if (field != null) {
+            DartType fieldType = field.type;
+            if (fieldType != parameter.type) {
+              // We've already checked that the argument can be assigned to the
+              // parameter; we also need to check that it can be assigned to
+              // the field.
+              if (!runtimeTypeMatch(argumentValue, fieldType)) {
+                errorReporter.reportErrorForNode(
+                    CheckedModeCompileTimeErrorCode
+                        .CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+                    errorTarget,
+                    [argumentValue.type, fieldType]);
+              }
+            }
+            String fieldName = field.name;
+            if (fieldMap.containsKey(fieldName)) {
+              errorReporter.reportErrorForNode(
+                  CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
+            }
+            fieldMap[fieldName] = argumentValue;
+          }
+        } else {
+          String name = baseParameter.name;
+          parameterMap[name] = argumentValue;
+        }
+      }
+    }
+    ConstantVisitor initializerVisitor = new ConstantVisitor(
+        this, errorReporter,
+        lexicalEnvironment: parameterMap);
+    String superName = null;
+    NodeList<Expression> superArguments = null;
+    for (ConstructorInitializer initializer in initializers) {
+      if (initializer is ConstructorFieldInitializer) {
+        ConstructorFieldInitializer constructorFieldInitializer = initializer;
+        Expression initializerExpression =
+            constructorFieldInitializer.expression;
+        DartObjectImpl evaluationResult =
+            initializerExpression.accept(initializerVisitor);
+        if (evaluationResult != null) {
+          String fieldName = constructorFieldInitializer.fieldName.name;
+          if (fieldMap.containsKey(fieldName)) {
+            errorReporter.reportErrorForNode(
+                CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
+          }
+          fieldMap[fieldName] = evaluationResult;
+          PropertyAccessorElement getter = definingClass.getGetter(fieldName);
+          if (getter != null) {
+            PropertyInducingElement field = getter.variable;
+            if (!runtimeTypeMatch(evaluationResult, field.type)) {
+              errorReporter.reportErrorForNode(
+                  CheckedModeCompileTimeErrorCode
+                      .CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
+                  node,
+                  [evaluationResult.type, fieldName, field.type]);
+            }
+          }
+        }
+      } else if (initializer is SuperConstructorInvocation) {
+        SuperConstructorInvocation superConstructorInvocation = initializer;
+        SimpleIdentifier name = superConstructorInvocation.constructorName;
+        if (name != null) {
+          superName = name.name;
+        }
+        superArguments = superConstructorInvocation.argumentList.arguments;
+      } else if (initializer is RedirectingConstructorInvocation) {
+        // This is a redirecting constructor, so just evaluate the constructor
+        // it redirects to.
+        ConstructorElement constructor = initializer.staticElement;
+        if (constructor != null && constructor.isConst) {
+          return evaluateConstructorCall(
+              node,
+              initializer.argumentList.arguments,
+              constructor,
+              initializerVisitor,
+              errorReporter);
+        }
+      }
+    }
+    // Evaluate explicit or implicit call to super().
+    InterfaceType superclass = definingClass.superclass;
+    if (superclass != null && !superclass.isObject) {
+      ConstructorElement superConstructor =
+          superclass.lookUpConstructor(superName, constructor.library);
+      if (superConstructor != null) {
+        if (superArguments == null) {
+          superArguments = new NodeList<Expression>(null);
+        }
+        evaluateSuperConstructorCall(node, fieldMap, superConstructor,
+            superArguments, initializerVisitor, errorReporter);
+      }
+    }
+    return new DartObjectImpl(definingClass, new GenericState(fieldMap));
+  }
+
+  void evaluateSuperConstructorCall(
+      AstNode node,
+      HashMap<String, DartObjectImpl> fieldMap,
+      ConstructorElement superConstructor,
+      NodeList<Expression> superArguments,
+      ConstantVisitor initializerVisitor,
+      ErrorReporter errorReporter) {
+    if (superConstructor != null && superConstructor.isConst) {
+      DartObjectImpl evaluationResult = evaluateConstructorCall(node,
+          superArguments, superConstructor, initializerVisitor, errorReporter);
+      if (evaluationResult != null) {
+        fieldMap[GenericState.SUPERCLASS_FIELD] = evaluationResult;
+      }
+    }
+  }
+
+  /**
+   * Attempt to follow the chain of factory redirections until a constructor is
+   * reached which is not a const factory constructor. Return the constant
+   * constructor which terminates the chain of factory redirections, if the
+   * chain terminates. If there is a problem (e.g. a redirection can't be found,
+   * or a cycle is encountered), the chain will be followed as far as possible
+   * and then a const factory constructor will be returned.
+   */
+  ConstructorElement followConstantRedirectionChain(
+      ConstructorElement constructor) {
+    HashSet<ConstructorElement> constructorsVisited =
+        new HashSet<ConstructorElement>();
+    while (true) {
+      ConstructorElement redirectedConstructor =
+          getConstRedirectedConstructor(constructor);
+      if (redirectedConstructor == null) {
+        break;
+      } else {
+        ConstructorElement constructorBase = getConstructorImpl(constructor);
+        constructorsVisited.add(constructorBase);
+        ConstructorElement redirectedConstructorBase =
+            getConstructorImpl(redirectedConstructor);
+        if (constructorsVisited.contains(redirectedConstructorBase)) {
+          // Cycle in redirecting factory constructors--this is not allowed
+          // and is checked elsewhere--see
+          // [ErrorVerifier.checkForRecursiveFactoryRedirect()]).
+          break;
+        }
+      }
+      constructor = redirectedConstructor;
+    }
+    return constructor;
+  }
+
+  /**
+   * Generate an error indicating that the given [constant] is not a valid
+   * compile-time constant because it references at least one of the constants
+   * in the given [cycle], each of which directly or indirectly references the
+   * constant.
+   */
+  void generateCycleError(Iterable<ConstantEvaluationTarget> cycle,
+      ConstantEvaluationTarget constant) {
+    if (constant is VariableElement) {
+      RecordingErrorListener errorListener = new RecordingErrorListener();
+      ErrorReporter errorReporter =
+          new ErrorReporter(errorListener, constant.source);
+      // TODO(paulberry): It would be really nice if we could extract enough
+      // information from the 'cycle' argument to provide the user with a
+      // description of the cycle.
+      errorReporter.reportErrorForElement(
+          CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT, constant, []);
+      (constant as VariableElementImpl).evaluationResult =
+          new EvaluationResultImpl(null, errorListener.errors);
+    } else if (constant is ConstructorElement) {
+      // We don't report cycle errors on constructor declarations since there
+      // is nowhere to put the error information.
+    } else {
+      // Should not happen.  Formal parameter defaults and annotations should
+      // never appear as part of a cycle because they can't be referred to.
+      assert(false);
+      AnalysisEngine.instance.logger.logError(
+          "Constant value computer trying to report a cycle error for a node of type ${constant.runtimeType}");
+    }
+  }
+
+  /**
+   * If [constructor] redirects to another const constructor, return the
+   * const constructor it redirects to.  Otherwise return `null`.
+   */
+  ConstructorElement getConstRedirectedConstructor(
+      ConstructorElement constructor) {
+    if (!constructor.isFactory) {
+      return null;
+    }
+    if (identical(constructor.enclosingElement.type, typeProvider.symbolType)) {
+      // The dart:core.Symbol has a const factory constructor that redirects
+      // to dart:_internal.Symbol.  That in turn redirects to an external
+      // const constructor, which we won't be able to evaluate.
+      // So stop following the chain of redirections at dart:core.Symbol, and
+      // let [evaluateInstanceCreationExpression] handle it specially.
+      return null;
+    }
+    ConstructorElement redirectedConstructor =
+        constructor.redirectedConstructor;
+    if (redirectedConstructor == null) {
+      // This can happen if constructor is an external factory constructor.
+      return null;
+    }
+    if (!redirectedConstructor.isConst) {
+      // Delegating to a non-const constructor--this is not allowed (and
+      // is checked elsewhere--see
+      // [ErrorVerifier.checkForRedirectToNonConstConstructor()]).
+      return null;
+    }
+    return redirectedConstructor;
+  }
+
+  /**
+   * Check if the object [obj] matches the type [type] according to runtime type
+   * checking rules.
+   */
+  bool runtimeTypeMatch(DartObjectImpl obj, DartType type) {
+    if (obj.isNull) {
+      return true;
+    }
+    if (type.isUndefined) {
+      return false;
+    }
+    return obj.type.isSubtypeOf(type);
+  }
+
+  /**
+   * Determine whether the given string is a valid name for a public symbol
+   * (i.e. whether it is allowed for a call to the Symbol constructor).
+   */
+  static bool isValidPublicSymbol(String name) =>
+      name.isEmpty ||
+      name == "void" ||
+      new JavaPatternMatcher(_PUBLIC_SYMBOL_PATTERN, name).matches();
+}
+
+/**
+ * Interface used by unit tests to verify correct dependency analysis during
+ * constant evaluation.
+ */
+abstract class ConstantEvaluationValidator {
+  /**
+   * This method is called just before computing the constant value associated
+   * with [constant]. Unit tests will override this method to introduce
+   * additional error checking.
+   */
+  void beforeComputeValue(ConstantEvaluationTarget constant);
+
+  /**
+   * This method is called just before getting the constant initializers
+   * associated with the [constructor]. Unit tests will override this method to
+   * introduce additional error checking.
+   */
+  void beforeGetConstantInitializers(ConstructorElement constructor);
+
+  /**
+   * This method is called just before retrieving an evaluation result from an
+   * element. Unit tests will override it to introduce additional error
+   * checking.
+   */
+  void beforeGetEvaluationResult(ConstantEvaluationTarget constant);
+
+  /**
+   * This method is called just before getting the constant value of a field
+   * with an initializer.  Unit tests will override this method to introduce
+   * additional error checking.
+   */
+  void beforeGetFieldEvaluationResult(FieldElementImpl field);
+
+  /**
+   * This method is called just before getting a parameter's default value. Unit
+   * tests will override this method to introduce additional error checking.
+   */
+  void beforeGetParameterDefault(ParameterElement parameter);
+}
+
+/**
+ * Implementation of [ConstantEvaluationValidator] used in production; does no
+ * validation.
+ */
+class ConstantEvaluationValidator_ForProduction
+    implements ConstantEvaluationValidator {
+  @override
+  void beforeComputeValue(ConstantEvaluationTarget constant) {}
+
+  @override
+  void beforeGetConstantInitializers(ConstructorElement constructor) {}
+
+  @override
+  void beforeGetEvaluationResult(ConstantEvaluationTarget constant) {}
+
+  @override
+  void beforeGetFieldEvaluationResult(FieldElementImpl field) {}
+
+  @override
+  void beforeGetParameterDefault(ParameterElement parameter) {}
+}
+
+/**
+ * An object used to compute the values of constant variables and constant
+ * constructor invocations in one or more compilation units. The expected usage
+ * pattern is for the compilation units to be added to this computer using the
+ * method [add] and then for the method [computeValues] to be invoked exactly
+ * once. Any use of an instance after invoking the method [computeValues] will
+ * result in unpredictable behavior.
+ */
+class ConstantValueComputer {
+  /**
+   * Source of RegExp matching declarable operator names.
+   * From sdk/lib/internal/symbol.dart.
+   */
+  static String _OPERATOR_RE =
+      "(?:[\\-+*/%&|^]|\\[\\]=?|==|~/?|<[<=]?|>[>=]?|unary-)";
+
+  /**
+   * Source of RegExp matching Dart reserved words.
+   * From sdk/lib/internal/symbol.dart.
+   */
+  static String _RESERVED_WORD_RE =
+      "(?:assert|break|c(?:a(?:se|tch)|lass|on(?:st|tinue))|d(?:efault|o)|e(?:lse|num|xtends)|f(?:alse|inal(?:ly)?|or)|i[fns]|n(?:ew|ull)|ret(?:hrow|urn)|s(?:uper|witch)|t(?:h(?:is|row)|r(?:ue|y))|v(?:ar|oid)|w(?:hile|ith))";
+
+  /**
+   * A graph in which the nodes are the constants, and the edges are from each
+   * constant to the other constants that are referenced by it.
+   */
+  DirectedGraph<ConstantEvaluationTarget> referenceGraph =
+      new DirectedGraph<ConstantEvaluationTarget>();
+
+  /**
+   * The elements whose constant values need to be computed.  Any elements
+   * which appear in [referenceGraph] but not in this set either belong to a
+   * different library cycle (and hence don't need to be recomputed) or were
+   * computed during a previous stage of resolution stage (e.g. constants
+   * associated with enums).
+   */
+  HashSet<ConstantEvaluationTarget> _constantsToCompute =
+      new HashSet<ConstantEvaluationTarget>();
+
+  /**
+   * The evaluation engine that does the work of evaluating instance creation
+   * expressions.
+   */
+  final ConstantEvaluationEngine evaluationEngine;
+
+  final AnalysisContext _context;
+
+  /**
+   * Initialize a newly created constant value computer. The [typeProvider] is
+   * the type provider used to access known types. The [declaredVariables] is
+   * the set of variables declared on the command line using '-D'.
+   */
+  ConstantValueComputer(this._context, TypeProvider typeProvider,
+      DeclaredVariables declaredVariables,
+      [ConstantEvaluationValidator validator, TypeSystem typeSystem])
+      : evaluationEngine = new ConstantEvaluationEngine(
+            typeProvider, declaredVariables,
+            validator: validator, typeSystem: typeSystem);
+
+  /**
+   * Add the constants in the given compilation [unit] to the list of constants
+   * whose value needs to be computed.
+   */
+  void add(CompilationUnit unit, Source source, Source librarySource) {
+    ConstantFinder constantFinder =
+        new ConstantFinder(_context, source, librarySource);
+    unit.accept(constantFinder);
+    _constantsToCompute.addAll(constantFinder.constantsToCompute);
+  }
+
+  /**
+   * Compute values for all of the constants in the compilation units that were
+   * added.
+   */
+  void computeValues() {
+    for (ConstantEvaluationTarget constant in _constantsToCompute) {
+      referenceGraph.addNode(constant);
+      evaluationEngine.computeDependencies(constant,
+          (ConstantEvaluationTarget dependency) {
+        referenceGraph.addEdge(constant, dependency);
+      });
+    }
+    List<List<ConstantEvaluationTarget>> topologicalSort =
+        referenceGraph.computeTopologicalSort();
+    for (List<ConstantEvaluationTarget> constantsInCycle in topologicalSort) {
+      if (constantsInCycle.length == 1) {
+        ConstantEvaluationTarget constant = constantsInCycle[0];
+        if (!referenceGraph.getTails(constant).contains(constant)) {
+          _computeValueFor(constant);
+          continue;
+        }
+      }
+      for (ConstantEvaluationTarget constant in constantsInCycle) {
+        evaluationEngine.generateCycleError(constantsInCycle, constant);
+      }
+    }
+  }
+
+  /**
+   * Compute a value for the given [constant].
+   */
+  void _computeValueFor(ConstantEvaluationTarget constant) {
+    if (!_constantsToCompute.contains(constant)) {
+      // Element is in the dependency graph but should have been computed by
+      // a previous stage of analysis.
+      // TODO(paulberry): once we have moved over to the new task model, this
+      // should only occur for constants associated with enum members.  Once
+      // that happens we should add an assertion to verify that it doesn't
+      // occur in any other cases.
+      return;
+    }
+    evaluationEngine.computeConstantValue(constant);
+  }
+}
+
+/**
+ * A visitor used to evaluate constant expressions to produce their compile-time
+ * value. According to the Dart Language Specification: <blockquote> A constant
+ * expression is one of the following:
+ *
+ * * A literal number.
+ * * A literal boolean.
+ * * A literal string where any interpolated expression is a compile-time
+ *   constant that evaluates to a numeric, string or boolean value or to
+ *   <b>null</b>.
+ * * A literal symbol.
+ * * <b>null</b>.
+ * * A qualified reference to a static constant variable.
+ * * An identifier expression that denotes a constant variable, class or type
+ *   alias.
+ * * A constant constructor invocation.
+ * * A constant list literal.
+ * * A constant map literal.
+ * * A simple or qualified identifier denoting a top-level function or a static
+ *   method.
+ * * A parenthesized expression <i>(e)</i> where <i>e</i> is a constant
+ *   expression.
+ * * An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i>
+ *   where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
+ *   expressions and <i>identical()</i> is statically bound to the predefined
+ *   dart function <i>identical()</i> discussed above.
+ * * An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i> or
+ *   <i>e<sub>1</sub> != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and
+ *   <i>e<sub>2</sub></i> are constant expressions that evaluate to a numeric,
+ *   string or boolean value.
+ * * An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> &amp;&amp;
+ *   e<sub>2</sub></i> or <i>e<sub>1</sub> || e<sub>2</sub></i>, where <i>e</i>,
+ *   <i>e1</sub></i> and <i>e2</sub></i> are constant expressions that evaluate
+ *   to a boolean value.
+ * * An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^
+ *   e<sub>2</sub></i>, <i>e<sub>1</sub> &amp; e<sub>2</sub></i>,
+ *   <i>e<sub>1</sub> | e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;&gt;
+ *   e<sub>2</sub></i> or <i>e<sub>1</sub> &lt;&lt; e<sub>2</sub></i>, where
+ *   <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
+ *   expressions that evaluate to an integer value or to <b>null</b>.
+ * * An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> +
+ *   e<sub>2</sub></i>, <i>e<sub>1</sub> - e<sub>2</sub></i>, <i>e<sub>1</sub> *
+ *   e<sub>2</sub></i>, <i>e<sub>1</sub> / e<sub>2</sub></i>, <i>e<sub>1</sub>
+ *   ~/ e<sub>2</sub></i>, <i>e<sub>1</sub> &gt; e<sub>2</sub></i>,
+ *   <i>e<sub>1</sub> &lt; e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;=
+ *   e<sub>2</sub></i>, <i>e<sub>1</sub> &lt;= e<sub>2</sub></i> or
+ *   <i>e<sub>1</sub> % e<sub>2</sub></i>, where <i>e</i>, <i>e<sub>1</sub></i>
+ *   and <i>e<sub>2</sub></i> are constant expressions that evaluate to a
+ *   numeric value or to <b>null</b>.
+ * * An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> :
+ *   e<sub>3</sub></i> where <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and
+ *   <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i>
+ *   evaluates to a boolean value.
+ * </blockquote>
+ */
+class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
+  /**
+   * The type provider used to access the known types.
+   */
+  final ConstantEvaluationEngine evaluationEngine;
+
+  final HashMap<String, DartObjectImpl> _lexicalEnvironment;
+
+  /**
+   * Error reporter that we use to report errors accumulated while computing the
+   * constant.
+   */
+  final ErrorReporter _errorReporter;
+
+  /**
+   * Helper class used to compute constant values.
+   */
+  DartObjectComputer _dartObjectComputer;
+
+  /**
+   * Initialize a newly created constant visitor. The [evaluationEngine] is
+   * used to evaluate instance creation expressions. The [lexicalEnvironment]
+   * is a map containing values which should override identifiers, or `null` if
+   * no overriding is necessary. The [_errorReporter] is used to report errors
+   * found during evaluation.  The [validator] is used by unit tests to verify
+   * correct dependency analysis.
+   */
+  ConstantVisitor(this.evaluationEngine, this._errorReporter,
+      {HashMap<String, DartObjectImpl> lexicalEnvironment})
+      : _lexicalEnvironment = lexicalEnvironment {
+    this._dartObjectComputer =
+        new DartObjectComputer(_errorReporter, evaluationEngine.typeProvider);
+  }
+
+  /**
+   * Convenience getter to gain access to the [evalationEngine]'s type
+   * provider.
+   */
+  TypeProvider get _typeProvider => evaluationEngine.typeProvider;
+
+  /**
+   * Convenience getter to gain access to the [evaluationEngine]'s type system.
+   */
+  TypeSystem get _typeSystem => evaluationEngine.typeSystem;
+
+  @override
+  DartObjectImpl visitAdjacentStrings(AdjacentStrings node) {
+    DartObjectImpl result = null;
+    for (StringLiteral string in node.strings) {
+      if (result == null) {
+        result = string.accept(this);
+      } else {
+        result =
+            _dartObjectComputer.concatenate(node, result, string.accept(this));
+      }
+    }
+    return result;
+  }
+
+  @override
+  DartObjectImpl visitBinaryExpression(BinaryExpression node) {
+    DartObjectImpl leftResult = node.leftOperand.accept(this);
+    DartObjectImpl rightResult = node.rightOperand.accept(this);
+    TokenType operatorType = node.operator.type;
+    // 'null' is almost never good operand
+    if (operatorType != TokenType.BANG_EQ &&
+        operatorType != TokenType.EQ_EQ &&
+        operatorType != TokenType.QUESTION_QUESTION) {
+      if (leftResult != null && leftResult.isNull ||
+          rightResult != null && rightResult.isNull) {
+        _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+        return null;
+      }
+    }
+    // evaluate operator
+    while (true) {
+      if (operatorType == TokenType.AMPERSAND) {
+        return _dartObjectComputer.bitAnd(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.AMPERSAND_AMPERSAND) {
+        return _dartObjectComputer.logicalAnd(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.BANG_EQ) {
+        return _dartObjectComputer.notEqual(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.BAR) {
+        return _dartObjectComputer.bitOr(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.BAR_BAR) {
+        return _dartObjectComputer.logicalOr(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.CARET) {
+        return _dartObjectComputer.bitXor(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.EQ_EQ) {
+        return _dartObjectComputer.equalEqual(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.GT) {
+        return _dartObjectComputer.greaterThan(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.GT_EQ) {
+        return _dartObjectComputer.greaterThanOrEqual(
+            node, leftResult, rightResult);
+      } else if (operatorType == TokenType.GT_GT) {
+        return _dartObjectComputer.shiftRight(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.LT) {
+        return _dartObjectComputer.lessThan(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.LT_EQ) {
+        return _dartObjectComputer.lessThanOrEqual(
+            node, leftResult, rightResult);
+      } else if (operatorType == TokenType.LT_LT) {
+        return _dartObjectComputer.shiftLeft(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.MINUS) {
+        return _dartObjectComputer.minus(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.PERCENT) {
+        return _dartObjectComputer.remainder(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.PLUS) {
+        return _dartObjectComputer.add(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.STAR) {
+        return _dartObjectComputer.times(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.SLASH) {
+        return _dartObjectComputer.divide(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.TILDE_SLASH) {
+        return _dartObjectComputer.integerDivide(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.QUESTION_QUESTION) {
+        return _dartObjectComputer.questionQuestion(
+            node, leftResult, rightResult);
+      } else {
+        // TODO(brianwilkerson) Figure out which error to report.
+        _error(node, null);
+        return null;
+      }
+      break;
+    }
+  }
+
+  @override
+  DartObjectImpl visitBooleanLiteral(BooleanLiteral node) =>
+      new DartObjectImpl(_typeProvider.boolType, BoolState.from(node.value));
+
+  @override
+  DartObjectImpl visitConditionalExpression(ConditionalExpression node) {
+    Expression condition = node.condition;
+    DartObjectImpl conditionResult = condition.accept(this);
+    DartObjectImpl thenResult = node.thenExpression.accept(this);
+    DartObjectImpl elseResult = node.elseExpression.accept(this);
+    if (conditionResult == null) {
+      return conditionResult;
+    } else if (!conditionResult.isBool) {
+      _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL, condition);
+      return null;
+    } else if (thenResult == null) {
+      return thenResult;
+    } else if (elseResult == null) {
+      return elseResult;
+    }
+    conditionResult =
+        _dartObjectComputer.applyBooleanConversion(condition, conditionResult);
+    if (conditionResult == null) {
+      return conditionResult;
+    }
+    if (conditionResult.toBoolValue() == true) {
+      return thenResult;
+    } else if (conditionResult.toBoolValue() == false) {
+      return elseResult;
+    }
+    ParameterizedType thenType = thenResult.type;
+    ParameterizedType elseType = elseResult.type;
+    return new DartObjectImpl.validWithUnknownValue(
+        _typeSystem.getLeastUpperBound(_typeProvider, thenType, elseType)
+        as InterfaceType);
+  }
+
+  @override
+  DartObjectImpl visitDoubleLiteral(DoubleLiteral node) =>
+      new DartObjectImpl(_typeProvider.doubleType, new DoubleState(node.value));
+
+  @override
+  DartObjectImpl visitInstanceCreationExpression(
+      InstanceCreationExpression node) {
+    if (!node.isConst) {
+      // TODO(brianwilkerson) Figure out which error to report.
+      _error(node, null);
+      return null;
+    }
+    ConstructorElement constructor = node.staticElement;
+    if (constructor == null) {
+      // Couldn't resolve the constructor so we can't compute a value.  No
+      // problem - the error has already been reported.
+      return null;
+    }
+    return evaluationEngine.evaluateConstructorCall(
+        node, node.argumentList.arguments, constructor, this, _errorReporter);
+  }
+
+  @override
+  DartObjectImpl visitIntegerLiteral(IntegerLiteral node) =>
+      new DartObjectImpl(_typeProvider.intType, new IntState(node.value));
+
+  @override
+  DartObjectImpl visitInterpolationExpression(InterpolationExpression node) {
+    DartObjectImpl result = node.expression.accept(this);
+    if (result != null && !result.isBoolNumStringOrNull) {
+      _error(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
+      return null;
+    }
+    return _dartObjectComputer.performToString(node, result);
+  }
+
+  @override
+  DartObjectImpl visitInterpolationString(InterpolationString node) =>
+      new DartObjectImpl(_typeProvider.stringType, new StringState(node.value));
+
+  @override
+  DartObjectImpl visitListLiteral(ListLiteral node) {
+    if (node.constKeyword == null) {
+      _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL, node);
+      return null;
+    }
+    bool errorOccurred = false;
+    List<DartObjectImpl> elements = new List<DartObjectImpl>();
+    for (Expression element in node.elements) {
+      DartObjectImpl elementResult = element.accept(this);
+      if (elementResult == null) {
+        errorOccurred = true;
+      } else {
+        elements.add(elementResult);
+      }
+    }
+    if (errorOccurred) {
+      return null;
+    }
+    DartType elementType = _typeProvider.dynamicType;
+    if (node.typeArguments != null &&
+        node.typeArguments.arguments.length == 1) {
+      DartType type = node.typeArguments.arguments[0].type;
+      if (type != null) {
+        elementType = type;
+      }
+    }
+    InterfaceType listType = _typeProvider.listType.instantiate([elementType]);
+    return new DartObjectImpl(listType, new ListState(elements));
+  }
+
+  @override
+  DartObjectImpl visitMapLiteral(MapLiteral node) {
+    if (node.constKeyword == null) {
+      _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL, node);
+      return null;
+    }
+    bool errorOccurred = false;
+    LinkedHashMap<DartObjectImpl, DartObjectImpl> map =
+        new LinkedHashMap<DartObjectImpl, DartObjectImpl>();
+    for (MapLiteralEntry entry in node.entries) {
+      DartObjectImpl keyResult = entry.key.accept(this);
+      DartObjectImpl valueResult = entry.value.accept(this);
+      if (keyResult == null || valueResult == null) {
+        errorOccurred = true;
+      } else {
+        map[keyResult] = valueResult;
+      }
+    }
+    if (errorOccurred) {
+      return null;
+    }
+    DartType keyType = _typeProvider.dynamicType;
+    DartType valueType = _typeProvider.dynamicType;
+    if (node.typeArguments != null &&
+        node.typeArguments.arguments.length == 2) {
+      DartType keyTypeCandidate = node.typeArguments.arguments[0].type;
+      if (keyTypeCandidate != null) {
+        keyType = keyTypeCandidate;
+      }
+      DartType valueTypeCandidate = node.typeArguments.arguments[1].type;
+      if (valueTypeCandidate != null) {
+        valueType = valueTypeCandidate;
+      }
+    }
+    InterfaceType mapType =
+        _typeProvider.mapType.instantiate([keyType, valueType]);
+    return new DartObjectImpl(mapType, new MapState(map));
+  }
+
+  @override
+  DartObjectImpl visitMethodInvocation(MethodInvocation node) {
+    Element element = node.methodName.staticElement;
+    if (element is FunctionElement) {
+      FunctionElement function = element;
+      if (function.name == "identical") {
+        NodeList<Expression> arguments = node.argumentList.arguments;
+        if (arguments.length == 2) {
+          Element enclosingElement = function.enclosingElement;
+          if (enclosingElement is CompilationUnitElement) {
+            LibraryElement library = enclosingElement.library;
+            if (library.isDartCore) {
+              DartObjectImpl leftArgument = arguments[0].accept(this);
+              DartObjectImpl rightArgument = arguments[1].accept(this);
+              return _dartObjectComputer.isIdentical(
+                  node, leftArgument, rightArgument);
+            }
+          }
+        }
+      }
+    }
+    // TODO(brianwilkerson) Figure out which error to report.
+    _error(node, null);
+    return null;
+  }
+
+  @override
+  DartObjectImpl visitNamedExpression(NamedExpression node) =>
+      node.expression.accept(this);
+
+  @override
+  DartObjectImpl visitNode(AstNode node) {
+    // TODO(brianwilkerson) Figure out which error to report.
+    _error(node, null);
+    return null;
+  }
+
+  @override
+  DartObjectImpl visitNullLiteral(NullLiteral node) => _typeProvider.nullObject;
+
+  @override
+  DartObjectImpl visitParenthesizedExpression(ParenthesizedExpression node) =>
+      node.expression.accept(this);
+
+  @override
+  DartObjectImpl visitPrefixedIdentifier(PrefixedIdentifier node) {
+    SimpleIdentifier prefixNode = node.prefix;
+    Element prefixElement = prefixNode.staticElement;
+    // String.length
+    if (prefixElement is! PrefixElement && prefixElement is! ClassElement) {
+      DartObjectImpl prefixResult = node.prefix.accept(this);
+      if (_isStringLength(prefixResult, node.identifier)) {
+        return prefixResult.stringLength(_typeProvider);
+      }
+    }
+    // importPrefix.CONST
+    if (prefixElement is! PrefixElement) {
+      DartObjectImpl prefixResult = prefixNode.accept(this);
+      if (prefixResult == null) {
+        // The error has already been reported.
+        return null;
+      }
+    }
+    // validate prefixed identifier
+    return _getConstantValue(node, node.staticElement);
+  }
+
+  @override
+  DartObjectImpl visitPrefixExpression(PrefixExpression node) {
+    DartObjectImpl operand = node.operand.accept(this);
+    if (operand != null && operand.isNull) {
+      _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+      return null;
+    }
+    while (true) {
+      if (node.operator.type == TokenType.BANG) {
+        return _dartObjectComputer.logicalNot(node, operand);
+      } else if (node.operator.type == TokenType.TILDE) {
+        return _dartObjectComputer.bitNot(node, operand);
+      } else if (node.operator.type == TokenType.MINUS) {
+        return _dartObjectComputer.negated(node, operand);
+      } else {
+        // TODO(brianwilkerson) Figure out which error to report.
+        _error(node, null);
+        return null;
+      }
+      break;
+    }
+  }
+
+  @override
+  DartObjectImpl visitPropertyAccess(PropertyAccess node) {
+    if (node.target != null) {
+      DartObjectImpl prefixResult = node.target.accept(this);
+      if (_isStringLength(prefixResult, node.propertyName)) {
+        return prefixResult.stringLength(_typeProvider);
+      }
+    }
+    return _getConstantValue(node, node.propertyName.staticElement);
+  }
+
+  @override
+  DartObjectImpl visitSimpleIdentifier(SimpleIdentifier node) {
+    if (_lexicalEnvironment != null &&
+        _lexicalEnvironment.containsKey(node.name)) {
+      return _lexicalEnvironment[node.name];
+    }
+    return _getConstantValue(node, node.staticElement);
+  }
+
+  @override
+  DartObjectImpl visitSimpleStringLiteral(SimpleStringLiteral node) =>
+      new DartObjectImpl(_typeProvider.stringType, new StringState(node.value));
+
+  @override
+  DartObjectImpl visitStringInterpolation(StringInterpolation node) {
+    DartObjectImpl result = null;
+    bool first = true;
+    for (InterpolationElement element in node.elements) {
+      if (first) {
+        result = element.accept(this);
+        first = false;
+      } else {
+        result =
+            _dartObjectComputer.concatenate(node, result, element.accept(this));
+      }
+    }
+    return result;
+  }
+
+  @override
+  DartObjectImpl visitSymbolLiteral(SymbolLiteral node) {
+    StringBuffer buffer = new StringBuffer();
+    List<Token> components = node.components;
+    for (int i = 0; i < components.length; i++) {
+      if (i > 0) {
+        buffer.writeCharCode(0x2E);
+      }
+      buffer.write(components[i].lexeme);
+    }
+    return new DartObjectImpl(
+        _typeProvider.symbolType, new SymbolState(buffer.toString()));
+  }
+
+  /**
+   * Create an error associated with the given [node]. The error will have the
+   * given error [code].
+   */
+  void _error(AstNode node, ErrorCode code) {
+    _errorReporter.reportErrorForNode(
+        code == null ? CompileTimeErrorCode.INVALID_CONSTANT : code, node);
+  }
+
+  /**
+   * Return the constant value of the static constant represented by the given
+   * [element]. The [node] is the node to be used if an error needs to be
+   * reported.
+   */
+  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) {
+        return value.value;
+      }
+    } else if (element is ExecutableElement) {
+      ExecutableElement function = element;
+      if (function.isStatic) {
+        ParameterizedType functionType = function.type;
+        if (functionType == null) {
+          functionType = _typeProvider.functionType;
+        }
+        return new DartObjectImpl(functionType, new FunctionState(function));
+      }
+    } else if (element is ClassElement ||
+        element is FunctionTypeAliasElement ||
+        element is DynamicElementImpl) {
+      return new DartObjectImpl(_typeProvider.typeType, new TypeState(element));
+    }
+    // TODO(brianwilkerson) Figure out which error to report.
+    _error(node, null);
+    return null;
+  }
+
+  /**
+   * Return `true` if the given [targetResult] represents a string and the
+   * [identifier] is "length".
+   */
+  bool _isStringLength(
+      DartObjectImpl targetResult, SimpleIdentifier identifier) {
+    if (targetResult == null || targetResult.type != _typeProvider.stringType) {
+      return false;
+    }
+    return identifier.name == 'length';
+  }
+
+  /**
+   * Return the value of the given [expression], or a representation of 'null'
+   * if the expression cannot be evaluated.
+   */
+  DartObjectImpl _valueOf(Expression expression) {
+    DartObjectImpl expressionValue = expression.accept(this);
+    if (expressionValue != null) {
+      return expressionValue;
+    }
+    return _typeProvider.nullObject;
+  }
+}
+
+/**
+ * A utility class that contains methods for manipulating instances of a Dart
+ * class and for collecting errors during evaluation.
+ */
+class DartObjectComputer {
+  /**
+   * The error reporter that we are using to collect errors.
+   */
+  final ErrorReporter _errorReporter;
+
+  /**
+   * The type provider used to create objects of the appropriate types, and to
+   * identify when an object is of a built-in type.
+   */
+  final TypeProvider _typeProvider;
+
+  DartObjectComputer(this._errorReporter, this._typeProvider);
+
+  DartObjectImpl add(BinaryExpression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.add(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+        return null;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Return the result of applying boolean conversion to the [evaluationResult].
+   * The [node] is the node against which errors should be reported.
+   */
+  DartObjectImpl applyBooleanConversion(
+      AstNode node, DartObjectImpl evaluationResult) {
+    if (evaluationResult != null) {
+      try {
+        return evaluationResult.convertToBool(_typeProvider);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl bitAnd(BinaryExpression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.bitAnd(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl bitNot(Expression node, DartObjectImpl evaluationResult) {
+    if (evaluationResult != null) {
+      try {
+        return evaluationResult.bitNot(_typeProvider);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl bitOr(BinaryExpression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.bitOr(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl bitXor(BinaryExpression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.bitXor(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl concatenate(Expression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.concatenate(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl divide(BinaryExpression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.divide(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl equalEqual(Expression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.equalEqual(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl greaterThan(BinaryExpression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.greaterThan(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl greaterThanOrEqual(BinaryExpression node,
+      DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.greaterThanOrEqual(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl integerDivide(BinaryExpression node,
+      DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.integerDivide(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl isIdentical(Expression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.isIdentical(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl lessThan(BinaryExpression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.lessThan(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl lessThanOrEqual(BinaryExpression node,
+      DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.lessThanOrEqual(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl logicalAnd(BinaryExpression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.logicalAnd(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl logicalNot(Expression node, DartObjectImpl evaluationResult) {
+    if (evaluationResult != null) {
+      try {
+        return evaluationResult.logicalNot(_typeProvider);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl logicalOr(BinaryExpression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.logicalOr(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl minus(BinaryExpression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.minus(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl negated(Expression node, DartObjectImpl evaluationResult) {
+    if (evaluationResult != null) {
+      try {
+        return evaluationResult.negated(_typeProvider);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl notEqual(BinaryExpression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.notEqual(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl performToString(
+      AstNode node, DartObjectImpl evaluationResult) {
+    if (evaluationResult != null) {
+      try {
+        return evaluationResult.performToString(_typeProvider);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl questionQuestion(Expression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      if (leftOperand.isNull) {
+        return rightOperand;
+      }
+      return leftOperand;
+    }
+    return null;
+  }
+
+  DartObjectImpl remainder(BinaryExpression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.remainder(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl shiftLeft(BinaryExpression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.shiftLeft(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  DartObjectImpl shiftRight(BinaryExpression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.shiftRight(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Return the result of invoking the 'length' getter on the
+   * [evaluationResult]. The [node] is the node against which errors should be
+   * reported.
+   */
+  EvaluationResultImpl stringLength(
+      Expression node, EvaluationResultImpl evaluationResult) {
+    if (evaluationResult.value != null) {
+      try {
+        return new EvaluationResultImpl(
+            evaluationResult.value.stringLength(_typeProvider));
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return new EvaluationResultImpl(null);
+  }
+
+  DartObjectImpl times(BinaryExpression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      try {
+        return leftOperand.times(_typeProvider, rightOperand);
+      } on EvaluationException catch (exception) {
+        _errorReporter.reportErrorForNode(exception.errorCode, node);
+      }
+    }
+    return null;
+  }
+}
+
+/**
+ * The result of attempting to evaluate an expression.
+ */
+class EvaluationResult {
+  // TODO(brianwilkerson) Merge with EvaluationResultImpl
+  /**
+   * The value of the expression.
+   */
+  final DartObject value;
+
+  /**
+   * The errors that should be reported for the expression(s) that were
+   * evaluated.
+   */
+  final List<AnalysisError> _errors;
+
+  /**
+   * Initialize a newly created result object with the given [value] and set of
+   * [_errors]. Clients should use one of the factory methods: [forErrors] and
+   * [forValue].
+   */
+  EvaluationResult(this.value, this._errors);
+
+  /**
+   * Return a list containing the errors that should be reported for the
+   * expression(s) that were evaluated. If there are no such errors, the list
+   * will be empty. The list can be empty even if the expression is not a valid
+   * compile time constant if the errors would have been reported by other parts
+   * of the analysis engine.
+   */
+  List<AnalysisError> get errors =>
+      _errors == null ? AnalysisError.NO_ERRORS : _errors;
+
+  /**
+   * Return `true` if the expression is a compile-time constant expression that
+   * would not throw an exception when evaluated.
+   */
+  bool get isValid => _errors == null;
+
+  /**
+   * Return an evaluation result representing the result of evaluating an
+   * expression that is not a compile-time constant because of the given
+   * [errors].
+   */
+  static EvaluationResult forErrors(List<AnalysisError> errors) =>
+      new EvaluationResult(null, errors);
+
+  /**
+   * Return an evaluation result representing the result of evaluating an
+   * expression that is a compile-time constant that evaluates to the given
+   * [value].
+   */
+  static EvaluationResult forValue(DartObject value) =>
+      new EvaluationResult(value, null);
+}
+
+/**
+ * The result of attempting to evaluate a expression.
+ */
+class EvaluationResultImpl {
+  /**
+   * The errors encountered while trying to evaluate the compile time constant.
+   * These errors may or may not have prevented the expression from being a
+   * valid compile time constant.
+   */
+  List<AnalysisError> _errors;
+
+  /**
+   * The value of the expression, or `null` if the value couldn't be computed
+   * due to errors.
+   */
+  final DartObjectImpl value;
+
+  EvaluationResultImpl(this.value, [List<AnalysisError> errors]) {
+    this._errors = errors == null ? <AnalysisError>[] : errors;
+  }
+
+  List<AnalysisError> get errors => _errors;
+
+  bool equalValues(TypeProvider typeProvider, EvaluationResultImpl result) {
+    if (this.value != null) {
+      if (result.value == null) {
+        return false;
+      }
+      return value == result.value;
+    } else {
+      return false;
+    }
+  }
+
+  @override
+  String toString() {
+    if (value == null) {
+      return "error";
+    }
+    return value.toString();
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/constant/utilities.dart b/pkg/analyzer/lib/src/dart/constant/utilities.dart
new file mode 100644
index 0000000..c324d7f
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/constant/utilities.dart
@@ -0,0 +1,312 @@
+// 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.constant.utilities;
+
+import 'dart:collection';
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/handle.dart'
+    show ConstructorElementHandle;
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/source.dart' show Source;
+import 'package:analyzer/src/task/dart.dart';
+
+ConstructorElementImpl getConstructorImpl(ConstructorElement constructor) {
+  while (constructor is ConstructorMember) {
+    constructor = (constructor as ConstructorMember).baseElement;
+  }
+  if (constructor is ConstructorElementHandle) {
+    constructor = (constructor as ConstructorElementHandle).actualElement;
+  }
+  return constructor;
+}
+
+/**
+ * Callback used by [ReferenceFinder] to report that a dependency was found.
+ */
+typedef void ReferenceFinderCallback(ConstantEvaluationTarget dependency);
+
+/**
+ * An [AstCloner] that copies the necessary information from the AST to allow
+ * constants to be evaluated.
+ */
+class ConstantAstCloner extends AstCloner {
+  ConstantAstCloner() : super(true);
+
+  @override
+  ConstructorName visitConstructorName(ConstructorName node) {
+    ConstructorName name = super.visitConstructorName(node);
+    name.staticElement = node.staticElement;
+    return name;
+  }
+
+  @override
+  InstanceCreationExpression visitInstanceCreationExpression(
+      InstanceCreationExpression node) {
+    InstanceCreationExpression expression =
+        super.visitInstanceCreationExpression(node);
+    expression.staticElement = node.staticElement;
+    return expression;
+  }
+
+  @override
+  RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
+      RedirectingConstructorInvocation node) {
+    RedirectingConstructorInvocation invocation =
+        super.visitRedirectingConstructorInvocation(node);
+    invocation.staticElement = node.staticElement;
+    return invocation;
+  }
+
+  @override
+  SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) {
+    SimpleIdentifier identifier = super.visitSimpleIdentifier(node);
+    identifier.staticElement = node.staticElement;
+    return identifier;
+  }
+
+  @override
+  SuperConstructorInvocation visitSuperConstructorInvocation(
+      SuperConstructorInvocation node) {
+    SuperConstructorInvocation invocation =
+        super.visitSuperConstructorInvocation(node);
+    invocation.staticElement = node.staticElement;
+    return invocation;
+  }
+
+  @override
+  TypeName visitTypeName(TypeName node) {
+    TypeName typeName = super.visitTypeName(node);
+    typeName.type = node.type;
+    return typeName;
+  }
+}
+
+/**
+ * A visitor used to traverse the AST structures of all of the compilation units
+ * being resolved and build the full set of dependencies for all constant
+ * expressions.
+ */
+class ConstantExpressionsDependenciesFinder extends RecursiveAstVisitor {
+  /**
+   * The constants whose values need to be computed.
+   */
+  HashSet<ConstantEvaluationTarget> dependencies =
+      new HashSet<ConstantEvaluationTarget>();
+
+  @override
+  void visitInstanceCreationExpression(InstanceCreationExpression node) {
+    if (node.isConst) {
+      _find(node);
+    } else {
+      super.visitInstanceCreationExpression(node);
+    }
+  }
+
+  @override
+  void visitListLiteral(ListLiteral node) {
+    if (node.constKeyword != null) {
+      _find(node);
+    } else {
+      super.visitListLiteral(node);
+    }
+  }
+
+  @override
+  void visitMapLiteral(MapLiteral node) {
+    if (node.constKeyword != null) {
+      _find(node);
+    } else {
+      super.visitMapLiteral(node);
+    }
+  }
+
+  @override
+  void visitSwitchCase(SwitchCase node) {
+    _find(node.expression);
+    node.statements.accept(this);
+  }
+
+  void _find(Expression node) {
+    if (node != null) {
+      ReferenceFinder referenceFinder = new ReferenceFinder(dependencies.add);
+      node.accept(referenceFinder);
+    }
+  }
+}
+
+/**
+ * A visitor used to traverse the AST structures of all of the compilation units
+ * being resolved and build tables of the constant variables, constant
+ * constructors, constant constructor invocations, and annotations found in
+ * those compilation units.
+ */
+class ConstantFinder extends RecursiveAstVisitor<Object> {
+  final AnalysisContext context;
+  final Source source;
+  final Source librarySource;
+
+  /**
+   * The elements and AST nodes whose constant values need to be computed.
+   */
+  List<ConstantEvaluationTarget> constantsToCompute =
+      <ConstantEvaluationTarget>[];
+
+  /**
+   * A flag indicating whether instance variables marked as "final" should be
+   * treated as "const".
+   */
+  bool treatFinalInstanceVarAsConst = false;
+
+  ConstantFinder(this.context, this.source, this.librarySource);
+
+  @override
+  Object visitAnnotation(Annotation node) {
+    super.visitAnnotation(node);
+    ElementAnnotation elementAnnotation = node.elementAnnotation;
+    if (elementAnnotation == null) {
+      // Analyzer ignores annotations on "part of" directives.
+      assert(node.parent is PartOfDirective);
+    } else {
+      constantsToCompute.add(elementAnnotation);
+    }
+    return null;
+  }
+
+  @override
+  Object visitClassDeclaration(ClassDeclaration node) {
+    bool prevTreatFinalInstanceVarAsConst = treatFinalInstanceVarAsConst;
+    if (node.element.constructors.any((ConstructorElement e) => e.isConst)) {
+      // Instance vars marked "final" need to be included in the dependency
+      // graph, since constant constructors implicitly use the values in their
+      // initializers.
+      treatFinalInstanceVarAsConst = true;
+    }
+    try {
+      return super.visitClassDeclaration(node);
+    } finally {
+      treatFinalInstanceVarAsConst = prevTreatFinalInstanceVarAsConst;
+    }
+  }
+
+  @override
+  Object visitConstructorDeclaration(ConstructorDeclaration node) {
+    super.visitConstructorDeclaration(node);
+    if (node.constKeyword != null) {
+      ConstructorElement element = node.element;
+      if (element != null) {
+        constantsToCompute.add(element);
+        constantsToCompute.addAll(element.parameters);
+      }
+    }
+    return null;
+  }
+
+  @override
+  Object visitDefaultFormalParameter(DefaultFormalParameter node) {
+    super.visitDefaultFormalParameter(node);
+    Expression defaultValue = node.defaultValue;
+    if (defaultValue != null && node.element != null) {
+      constantsToCompute.add(node.element);
+    }
+    return null;
+  }
+
+  @override
+  Object visitVariableDeclaration(VariableDeclaration node) {
+    super.visitVariableDeclaration(node);
+    Expression initializer = node.initializer;
+    VariableElement element = node.element;
+    if (initializer != null &&
+        (node.isConst ||
+            treatFinalInstanceVarAsConst &&
+                element is FieldElement &&
+                node.isFinal &&
+                !element.isStatic)) {
+      if (element != null) {
+        constantsToCompute.add(element);
+      }
+    }
+    return null;
+  }
+}
+
+/**
+ * An object used to add reference information for a given variable to the
+ * bi-directional mapping used to order the evaluation of constants.
+ */
+class ReferenceFinder extends RecursiveAstVisitor<Object> {
+  /**
+   * The callback which should be used to report any dependencies that were
+   * found.
+   */
+  final ReferenceFinderCallback _callback;
+
+  /**
+   * Initialize a newly created reference finder to find references from a given
+   * variable to other variables and to add those references to the given graph.
+   * The [_callback] will be invoked for every dependency found.
+   */
+  ReferenceFinder(this._callback);
+
+  @override
+  Object visitInstanceCreationExpression(InstanceCreationExpression node) {
+    if (node.isConst) {
+      ConstructorElement constructor = getConstructorImpl(node.staticElement);
+      if (constructor != null) {
+        _callback(constructor);
+      }
+    }
+    return super.visitInstanceCreationExpression(node);
+  }
+
+  @override
+  Object visitLabel(Label node) {
+    // We are visiting the "label" part of a named expression in a function
+    // call (presumably a constructor call), e.g. "const C(label: ...)".  We
+    // don't want to visit the SimpleIdentifier for the label because that's a
+    // reference to a function parameter that needs to be filled in; it's not a
+    // constant whose value we depend on.
+    return null;
+  }
+
+  @override
+  Object visitRedirectingConstructorInvocation(
+      RedirectingConstructorInvocation node) {
+    super.visitRedirectingConstructorInvocation(node);
+    ConstructorElement target = getConstructorImpl(node.staticElement);
+    if (target != null) {
+      _callback(target);
+    }
+    return null;
+  }
+
+  @override
+  Object visitSimpleIdentifier(SimpleIdentifier node) {
+    Element element = node.staticElement;
+    if (element is PropertyAccessorElement) {
+      element = (element as PropertyAccessorElement).variable;
+    }
+    if (element is VariableElement && element.isConst) {
+      _callback(element);
+    }
+    return null;
+  }
+
+  @override
+  Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+    super.visitSuperConstructorInvocation(node);
+    ConstructorElement constructor = getConstructorImpl(node.staticElement);
+    if (constructor != null) {
+      _callback(constructor);
+    }
+    return null;
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
new file mode 100644
index 0000000..6ebb45d
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -0,0 +1,2818 @@
+// 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.
+
+/**
+ * The implementation of the class [DartObject].
+ */
+library analyzer.src.dart.constant.value;
+
+import 'dart:collection';
+
+import 'package:analyzer/dart/constant/value.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_core.dart';
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
+import 'package:analyzer/src/generated/utilities_general.dart';
+
+/**
+ * The state of an object representing a boolean value.
+ */
+class BoolState extends InstanceState {
+  /**
+   * An instance representing the boolean value 'false'.
+   */
+  static BoolState FALSE_STATE = new BoolState(false);
+
+  /**
+   * An instance representing the boolean value 'true'.
+   */
+  static BoolState TRUE_STATE = new BoolState(true);
+
+  /**
+   * A state that can be used to represent a boolean whose value is not known.
+   */
+  static BoolState UNKNOWN_VALUE = new BoolState(null);
+
+  /**
+   * The value of this instance.
+   */
+  final bool value;
+
+  /**
+   * Initialize a newly created state to represent the given [value].
+   */
+  BoolState(this.value);
+
+  @override
+  int get hashCode => value == null ? 0 : (value ? 2 : 3);
+
+  @override
+  bool get isBool => true;
+
+  @override
+  bool get isBoolNumStringOrNull => true;
+
+  @override
+  bool get isUnknown => value == null;
+
+  @override
+  String get typeName => "bool";
+
+  @override
+  bool operator ==(Object object) =>
+      object is BoolState && identical(value, object.value);
+
+  @override
+  BoolState convertToBool() => this;
+
+  @override
+  StringState convertToString() {
+    if (value == null) {
+      return StringState.UNKNOWN_VALUE;
+    }
+    return new StringState(value ? "true" : "false");
+  }
+
+  @override
+  BoolState equalEqual(InstanceState rightOperand) {
+    assertBoolNumStringOrNull(rightOperand);
+    return isIdentical(rightOperand);
+  }
+
+  @override
+  BoolState isIdentical(InstanceState rightOperand) {
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    if (rightOperand is BoolState) {
+      bool rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return BoolState.from(identical(value, rightValue));
+    } else if (rightOperand is DynamicState) {
+      return UNKNOWN_VALUE;
+    }
+    return FALSE_STATE;
+  }
+
+  @override
+  BoolState logicalAnd(InstanceState rightOperand) {
+    assertBool(rightOperand);
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    return value ? rightOperand.convertToBool() : FALSE_STATE;
+  }
+
+  @override
+  BoolState logicalNot() {
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    return value ? FALSE_STATE : TRUE_STATE;
+  }
+
+  @override
+  BoolState logicalOr(InstanceState rightOperand) {
+    assertBool(rightOperand);
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    return value ? TRUE_STATE : rightOperand.convertToBool();
+  }
+
+  @override
+  String toString() => value == null ? "-unknown-" : (value ? "true" : "false");
+
+  /**
+   * Return the boolean state representing the given boolean [value].
+   */
+  static BoolState from(bool value) =>
+      value ? BoolState.TRUE_STATE : BoolState.FALSE_STATE;
+}
+
+/**
+ * A representation of an instance of a Dart class.
+ */
+class DartObjectImpl implements DartObject {
+  /**
+   * An empty list of objects.
+   */
+  static const List<DartObjectImpl> EMPTY_LIST = const <DartObjectImpl>[];
+
+  /**
+   * The run-time type of this object.
+   */
+  @override
+  final ParameterizedType type;
+
+  /**
+   * The state of the object.
+   */
+  final InstanceState _state;
+
+  /**
+   * Initialize a newly created object to have the given [type] and [_state].
+   */
+  DartObjectImpl(this.type, this._state);
+
+  /**
+   * Create an object to represent an unknown value.
+   */
+  factory DartObjectImpl.validWithUnknownValue(InterfaceType type) {
+    if (type.element.library.isDartCore) {
+      String typeName = type.name;
+      if (typeName == "bool") {
+        return new DartObjectImpl(type, BoolState.UNKNOWN_VALUE);
+      } else if (typeName == "double") {
+        return new DartObjectImpl(type, DoubleState.UNKNOWN_VALUE);
+      } else if (typeName == "int") {
+        return new DartObjectImpl(type, IntState.UNKNOWN_VALUE);
+      } else if (typeName == "String") {
+        return new DartObjectImpl(type, StringState.UNKNOWN_VALUE);
+      }
+    }
+    return new DartObjectImpl(type, GenericState.UNKNOWN_VALUE);
+  }
+
+  HashMap<String, DartObjectImpl> get fields => _state.fields;
+
+  @override
+  int get hashCode => JenkinsSmiHash.hash2(type.hashCode, _state.hashCode);
+
+  @override
+  bool get hasKnownValue => !_state.isUnknown;
+
+  /**
+   * Return `true` if this object represents an object whose type is 'bool'.
+   */
+  bool get isBool => _state.isBool;
+
+  /**
+   * Return `true` if this object represents an object whose type is either
+   * 'bool', 'num', 'String', or 'Null'.
+   */
+  bool get isBoolNumStringOrNull => _state.isBoolNumStringOrNull;
+
+  @override
+  bool get isNull => _state is NullState;
+
+  /**
+   * Return `true` if this object represents an unknown value.
+   */
+  bool get isUnknown => _state.isUnknown;
+
+  /**
+   * Return `true` if this object represents an instance of a user-defined
+   * class.
+   */
+  bool get isUserDefinedObject => _state is GenericState;
+
+  @override
+  bool operator ==(Object object) {
+    if (object is! DartObjectImpl) {
+      return false;
+    }
+    DartObjectImpl dartObject = object as DartObjectImpl;
+    return type == dartObject.type && _state == dartObject._state;
+  }
+
+  /**
+   * Return the result of invoking the '+' operator on this object with the
+   * given [rightOperand]. The [typeProvider] is the type provider used to find
+   * known types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl add(TypeProvider typeProvider, DartObjectImpl rightOperand) {
+    InstanceState result = _state.add(rightOperand._state);
+    if (result is IntState) {
+      return new DartObjectImpl(typeProvider.intType, result);
+    } else if (result is DoubleState) {
+      return new DartObjectImpl(typeProvider.doubleType, result);
+    } else if (result is NumState) {
+      return new DartObjectImpl(typeProvider.numType, result);
+    } else if (result is StringState) {
+      return new DartObjectImpl(typeProvider.stringType, result);
+    }
+    // We should never get here.
+    throw new IllegalStateException("add returned a ${result.runtimeType}");
+  }
+
+  /**
+   * Return the result of invoking the '&' operator on this object with the
+   * [rightOperand]. The [typeProvider] is the type provider used to find known
+   * types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl bitAnd(
+          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+      new DartObjectImpl(
+          typeProvider.intType, _state.bitAnd(rightOperand._state));
+
+  /**
+   * Return the result of invoking the '~' operator on this object. The
+   * [typeProvider] is the type provider used to find known types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl bitNot(TypeProvider typeProvider) =>
+      new DartObjectImpl(typeProvider.intType, _state.bitNot());
+
+  /**
+   * Return the result of invoking the '|' operator on this object with the
+   * [rightOperand]. The [typeProvider] is the type provider used to find known
+   * types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl bitOr(
+          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+      new DartObjectImpl(
+          typeProvider.intType, _state.bitOr(rightOperand._state));
+
+  /**
+   * Return the result of invoking the '^' operator on this object with the
+   * [rightOperand]. The [typeProvider] is the type provider used to find known
+   * types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl bitXor(
+          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+      new DartObjectImpl(
+          typeProvider.intType, _state.bitXor(rightOperand._state));
+
+  /**
+   * Return the result of invoking the ' ' operator on this object with the
+   * [rightOperand]. The [typeProvider] is the type provider used to find known
+   * types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl concatenate(
+          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+      new DartObjectImpl(
+          typeProvider.stringType, _state.concatenate(rightOperand._state));
+
+  /**
+   * Return the result of applying boolean conversion to this object. The
+   * [typeProvider] is the type provider used to find known types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl convertToBool(TypeProvider typeProvider) {
+    InterfaceType boolType = typeProvider.boolType;
+    if (identical(type, boolType)) {
+      return this;
+    }
+    return new DartObjectImpl(boolType, _state.convertToBool());
+  }
+
+  /**
+   * Return the result of invoking the '/' operator on this object with the
+   * [rightOperand]. The [typeProvider] is the type provider used to find known
+   * types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for
+   * an object of this kind.
+   */
+  DartObjectImpl divide(
+      TypeProvider typeProvider, DartObjectImpl rightOperand) {
+    InstanceState result = _state.divide(rightOperand._state);
+    if (result is IntState) {
+      return new DartObjectImpl(typeProvider.intType, result);
+    } else if (result is DoubleState) {
+      return new DartObjectImpl(typeProvider.doubleType, result);
+    } else if (result is NumState) {
+      return new DartObjectImpl(typeProvider.numType, result);
+    }
+    // We should never get here.
+    throw new IllegalStateException("divide returned a ${result.runtimeType}");
+  }
+
+  /**
+   * Return the result of invoking the '==' operator on this object with the
+   * [rightOperand]. The [typeProvider] is the type provider used to find known
+   * types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl equalEqual(
+      TypeProvider typeProvider, DartObjectImpl rightOperand) {
+    if (type != rightOperand.type) {
+      String typeName = type.name;
+      if (!(typeName == "bool" ||
+          typeName == "double" ||
+          typeName == "int" ||
+          typeName == "num" ||
+          typeName == "String" ||
+          typeName == "Null" ||
+          type.isDynamic)) {
+        throw new EvaluationException(
+            CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
+      }
+    }
+    return new DartObjectImpl(
+        typeProvider.boolType, _state.equalEqual(rightOperand._state));
+  }
+
+  @override
+  DartObject getField(String name) {
+    if (_state is GenericState) {
+      return (_state as GenericState).fields[name];
+    }
+    return null;
+  }
+
+  /**
+   * Return the result of invoking the '&gt;' operator on this object with the
+   * [rightOperand]. The [typeProvider] is the type provider used to find known
+   * types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl greaterThan(
+          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+      new DartObjectImpl(
+          typeProvider.boolType, _state.greaterThan(rightOperand._state));
+
+  /**
+   * Return the result of invoking the '&gt;=' operator on this object with the
+   * [rightOperand]. The [typeProvider] is the type provider used to find known
+   * types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl greaterThanOrEqual(
+          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+      new DartObjectImpl(typeProvider.boolType,
+          _state.greaterThanOrEqual(rightOperand._state));
+
+  /**
+   * Return the result of invoking the '~/' operator on this object with the
+   * [rightOperand]. The [typeProvider] is the type provider used to find known
+   * types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl integerDivide(
+          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+      new DartObjectImpl(
+          typeProvider.intType, _state.integerDivide(rightOperand._state));
+
+  /**
+   * Return the result of invoking the identical function on this object with
+   * the [rightOperand]. The [typeProvider] is the type provider used to find
+   * known types.
+   */
+  DartObjectImpl isIdentical(
+      TypeProvider typeProvider, DartObjectImpl rightOperand) {
+    return new DartObjectImpl(
+        typeProvider.boolType, _state.isIdentical(rightOperand._state));
+  }
+
+  /**
+   * Return the result of invoking the '&lt;' operator on this object with the
+   * [rightOperand]. The [typeProvider] is the type provider used to find known
+   * types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl lessThan(
+          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+      new DartObjectImpl(
+          typeProvider.boolType, _state.lessThan(rightOperand._state));
+
+  /**
+   * Return the result of invoking the '&lt;=' operator on this object with the
+   * [rightOperand]. The [typeProvider] is the type provider used to find known
+   * types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl lessThanOrEqual(
+          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+      new DartObjectImpl(
+          typeProvider.boolType, _state.lessThanOrEqual(rightOperand._state));
+
+  /**
+   * Return the result of invoking the '&&' operator on this object with the
+   * [rightOperand]. The [typeProvider] is the type provider used to find known
+   * types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl logicalAnd(
+          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+      new DartObjectImpl(
+          typeProvider.boolType, _state.logicalAnd(rightOperand._state));
+
+  /**
+   * Return the result of invoking the '!' operator on this object. The
+   * [typeProvider] is the type provider used to find known types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl logicalNot(TypeProvider typeProvider) =>
+      new DartObjectImpl(typeProvider.boolType, _state.logicalNot());
+
+  /**
+   * Return the result of invoking the '||' operator on this object with the
+   * [rightOperand]. The [typeProvider] is the type provider used to find known
+   * types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl logicalOr(
+          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+      new DartObjectImpl(
+          typeProvider.boolType, _state.logicalOr(rightOperand._state));
+
+  /**
+   * Return the result of invoking the '-' operator on this object with the
+   * [rightOperand]. The [typeProvider] is the type provider used to find known
+   * types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl minus(TypeProvider typeProvider, DartObjectImpl rightOperand) {
+    InstanceState result = _state.minus(rightOperand._state);
+    if (result is IntState) {
+      return new DartObjectImpl(typeProvider.intType, result);
+    } else if (result is DoubleState) {
+      return new DartObjectImpl(typeProvider.doubleType, result);
+    } else if (result is NumState) {
+      return new DartObjectImpl(typeProvider.numType, result);
+    }
+    // We should never get here.
+    throw new IllegalStateException("minus returned a ${result.runtimeType}");
+  }
+
+  /**
+   * Return the result of invoking the '-' operator on this object. The
+   * [typeProvider] is the type provider used to find known types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl negated(TypeProvider typeProvider) {
+    InstanceState result = _state.negated();
+    if (result is IntState) {
+      return new DartObjectImpl(typeProvider.intType, result);
+    } else if (result is DoubleState) {
+      return new DartObjectImpl(typeProvider.doubleType, result);
+    } else if (result is NumState) {
+      return new DartObjectImpl(typeProvider.numType, result);
+    }
+    // We should never get here.
+    throw new IllegalStateException("negated returned a ${result.runtimeType}");
+  }
+
+  /**
+   * Return the result of invoking the '!=' operator on this object with the
+   * [rightOperand]. The [typeProvider] is the type provider used to find known
+   * types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl notEqual(
+      TypeProvider typeProvider, DartObjectImpl rightOperand) {
+    if (type != rightOperand.type) {
+      String typeName = type.name;
+      if (typeName != "bool" &&
+          typeName != "double" &&
+          typeName != "int" &&
+          typeName != "num" &&
+          typeName != "String") {
+        return new DartObjectImpl(typeProvider.boolType, BoolState.TRUE_STATE);
+      }
+    }
+    return new DartObjectImpl(typeProvider.boolType,
+        _state.equalEqual(rightOperand._state).logicalNot());
+  }
+
+  /**
+   * Return the result of converting this object to a 'String'. The
+   * [typeProvider] is the type provider used to find known types.
+   *
+   * Throws an [EvaluationException] if the object cannot be converted to a
+   * 'String'.
+   */
+  DartObjectImpl performToString(TypeProvider typeProvider) {
+    InterfaceType stringType = typeProvider.stringType;
+    if (identical(type, stringType)) {
+      return this;
+    }
+    return new DartObjectImpl(stringType, _state.convertToString());
+  }
+
+  /**
+   * Return the result of invoking the '%' operator on this object with the
+   * [rightOperand]. The [typeProvider] is the type provider used to find known
+   * types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl remainder(
+      TypeProvider typeProvider, DartObjectImpl rightOperand) {
+    InstanceState result = _state.remainder(rightOperand._state);
+    if (result is IntState) {
+      return new DartObjectImpl(typeProvider.intType, result);
+    } else if (result is DoubleState) {
+      return new DartObjectImpl(typeProvider.doubleType, result);
+    } else if (result is NumState) {
+      return new DartObjectImpl(typeProvider.numType, result);
+    }
+    // We should never get here.
+    throw new IllegalStateException(
+        "remainder returned a ${result.runtimeType}");
+  }
+
+  /**
+   * Return the result of invoking the '&lt;&lt;' operator on this object with
+   * the [rightOperand]. The [typeProvider] is the type provider used to find
+   * known types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl shiftLeft(
+          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+      new DartObjectImpl(
+          typeProvider.intType, _state.shiftLeft(rightOperand._state));
+
+  /**
+   * Return the result of invoking the '&gt;&gt;' operator on this object with
+   * the [rightOperand]. The [typeProvider] is the type provider used to find
+   * known types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl shiftRight(
+          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+      new DartObjectImpl(
+          typeProvider.intType, _state.shiftRight(rightOperand._state));
+
+  /**
+   * Return the result of invoking the 'length' getter on this object. The
+   * [typeProvider] is the type provider used to find known types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl stringLength(TypeProvider typeProvider) =>
+      new DartObjectImpl(typeProvider.intType, _state.stringLength());
+
+  /**
+   * Return the result of invoking the '*' operator on this object with the
+   * [rightOperand]. The [typeProvider] is the type provider used to find known
+   * types.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  DartObjectImpl times(TypeProvider typeProvider, DartObjectImpl rightOperand) {
+    InstanceState result = _state.times(rightOperand._state);
+    if (result is IntState) {
+      return new DartObjectImpl(typeProvider.intType, result);
+    } else if (result is DoubleState) {
+      return new DartObjectImpl(typeProvider.doubleType, result);
+    } else if (result is NumState) {
+      return new DartObjectImpl(typeProvider.numType, result);
+    }
+    // We should never get here.
+    throw new IllegalStateException("times returned a ${result.runtimeType}");
+  }
+
+  @override
+  bool toBoolValue() {
+    if (_state is BoolState) {
+      return (_state as BoolState).value;
+    }
+    return null;
+  }
+
+  @override
+  double toDoubleValue() {
+    if (_state is DoubleState) {
+      return (_state as DoubleState).value;
+    }
+    return null;
+  }
+
+  @override
+  int toIntValue() {
+    if (_state is IntState) {
+      return (_state as IntState).value;
+    }
+    return null;
+  }
+
+  @override
+  List<DartObject> toListValue() {
+    if (_state is ListState) {
+      return (_state as ListState)._elements;
+    }
+    return null;
+  }
+
+  @override
+  Map<DartObject, DartObject> toMapValue() {
+    if (_state is MapState) {
+      return (_state as MapState)._entries;
+    }
+    return null;
+  }
+
+  @override
+  String toString() => "${type.displayName} ($_state)";
+
+  @override
+  String toStringValue() {
+    if (_state is StringState) {
+      return (_state as StringState).value;
+    }
+    return null;
+  }
+
+  @override
+  String toSymbolValue() {
+    if (_state is SymbolState) {
+      return (_state as SymbolState).value;
+    }
+    return null;
+  }
+
+  @override
+  DartType toTypeValue() {
+    if (_state is TypeState) {
+      Element element = (_state as TypeState)._element;
+      if (element is TypeDefiningElement) {
+        return element.type;
+      }
+    }
+    return null;
+  }
+}
+
+/**
+ * The state of an object representing a double.
+ */
+class DoubleState extends NumState {
+  /**
+   * A state that can be used to represent a double whose value is not known.
+   */
+  static DoubleState UNKNOWN_VALUE = new DoubleState(null);
+
+  /**
+   * The value of this instance.
+   */
+  final double value;
+
+  /**
+   * Initialize a newly created state to represent a double with the given
+   * [value].
+   */
+  DoubleState(this.value);
+
+  @override
+  int get hashCode => value == null ? 0 : value.hashCode;
+
+  @override
+  bool get isBoolNumStringOrNull => true;
+
+  @override
+  bool get isUnknown => value == null;
+
+  @override
+  String get typeName => "double";
+
+  @override
+  bool operator ==(Object object) =>
+      object is DoubleState && (value == object.value);
+
+  @override
+  NumState add(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return new DoubleState(value + rightValue.toDouble());
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return new DoubleState(value + rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  StringState convertToString() {
+    if (value == null) {
+      return StringState.UNKNOWN_VALUE;
+    }
+    return new StringState(value.toString());
+  }
+
+  @override
+  NumState divide(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return new DoubleState(value / rightValue.toDouble());
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return new DoubleState(value / rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  BoolState equalEqual(InstanceState rightOperand) {
+    assertBoolNumStringOrNull(rightOperand);
+    return isIdentical(rightOperand);
+  }
+
+  @override
+  BoolState greaterThan(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value > rightValue.toDouble());
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value > rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  BoolState greaterThanOrEqual(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value >= rightValue.toDouble());
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value >= rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  IntState integerDivide(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      return IntState.UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return IntState.UNKNOWN_VALUE;
+      }
+      double result = value / rightValue.toDouble();
+      return new IntState(result.toInt());
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return IntState.UNKNOWN_VALUE;
+      }
+      double result = value / rightValue;
+      return new IntState(result.toInt());
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return IntState.UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  BoolState isIdentical(InstanceState rightOperand) {
+    if (value == null) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value == rightValue);
+    } else if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value == rightValue.toDouble());
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    return BoolState.FALSE_STATE;
+  }
+
+  @override
+  BoolState lessThan(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value < rightValue.toDouble());
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value < rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  BoolState lessThanOrEqual(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value <= rightValue.toDouble());
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value <= rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  NumState minus(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return new DoubleState(value - rightValue.toDouble());
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return new DoubleState(value - rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  NumState negated() {
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    return new DoubleState(-(value));
+  }
+
+  @override
+  NumState remainder(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return new DoubleState(value % rightValue.toDouble());
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return new DoubleState(value % rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  NumState times(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return new DoubleState(value * rightValue.toDouble());
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return new DoubleState(value * rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  String toString() => value == null ? "-unknown-" : value.toString();
+}
+
+/**
+ * The state of an object representing a Dart object for which there is no type
+ * information.
+ */
+class DynamicState extends InstanceState {
+  /**
+   * The unique instance of this class.
+   */
+  static DynamicState DYNAMIC_STATE = new DynamicState();
+
+  @override
+  bool get isBool => true;
+
+  @override
+  bool get isBoolNumStringOrNull => true;
+
+  @override
+  String get typeName => "dynamic";
+
+  @override
+  NumState add(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return _unknownNum(rightOperand);
+  }
+
+  @override
+  IntState bitAnd(InstanceState rightOperand) {
+    assertIntOrNull(rightOperand);
+    return IntState.UNKNOWN_VALUE;
+  }
+
+  @override
+  IntState bitNot() => IntState.UNKNOWN_VALUE;
+
+  @override
+  IntState bitOr(InstanceState rightOperand) {
+    assertIntOrNull(rightOperand);
+    return IntState.UNKNOWN_VALUE;
+  }
+
+  @override
+  IntState bitXor(InstanceState rightOperand) {
+    assertIntOrNull(rightOperand);
+    return IntState.UNKNOWN_VALUE;
+  }
+
+  @override
+  StringState concatenate(InstanceState rightOperand) {
+    assertString(rightOperand);
+    return StringState.UNKNOWN_VALUE;
+  }
+
+  @override
+  BoolState convertToBool() => BoolState.UNKNOWN_VALUE;
+
+  @override
+  StringState convertToString() => StringState.UNKNOWN_VALUE;
+
+  @override
+  NumState divide(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return _unknownNum(rightOperand);
+  }
+
+  @override
+  BoolState equalEqual(InstanceState rightOperand) {
+    assertBoolNumStringOrNull(rightOperand);
+    return BoolState.UNKNOWN_VALUE;
+  }
+
+  @override
+  BoolState greaterThan(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return BoolState.UNKNOWN_VALUE;
+  }
+
+  @override
+  BoolState greaterThanOrEqual(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return BoolState.UNKNOWN_VALUE;
+  }
+
+  @override
+  IntState integerDivide(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return IntState.UNKNOWN_VALUE;
+  }
+
+  @override
+  BoolState isIdentical(InstanceState rightOperand) {
+    return BoolState.UNKNOWN_VALUE;
+  }
+
+  @override
+  BoolState lessThan(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return BoolState.UNKNOWN_VALUE;
+  }
+
+  @override
+  BoolState lessThanOrEqual(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return BoolState.UNKNOWN_VALUE;
+  }
+
+  @override
+  BoolState logicalAnd(InstanceState rightOperand) {
+    assertBool(rightOperand);
+    return BoolState.UNKNOWN_VALUE;
+  }
+
+  @override
+  BoolState logicalNot() => BoolState.UNKNOWN_VALUE;
+
+  @override
+  BoolState logicalOr(InstanceState rightOperand) {
+    assertBool(rightOperand);
+    return rightOperand.convertToBool();
+  }
+
+  @override
+  NumState minus(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return _unknownNum(rightOperand);
+  }
+
+  @override
+  NumState negated() => NumState.UNKNOWN_VALUE;
+
+  @override
+  NumState remainder(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return _unknownNum(rightOperand);
+  }
+
+  @override
+  IntState shiftLeft(InstanceState rightOperand) {
+    assertIntOrNull(rightOperand);
+    return IntState.UNKNOWN_VALUE;
+  }
+
+  @override
+  IntState shiftRight(InstanceState rightOperand) {
+    assertIntOrNull(rightOperand);
+    return IntState.UNKNOWN_VALUE;
+  }
+
+  @override
+  NumState times(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return _unknownNum(rightOperand);
+  }
+
+  /**
+   * Return an object representing an unknown numeric value whose type is based
+   * on the type of the [rightOperand].
+   */
+  NumState _unknownNum(InstanceState rightOperand) {
+    if (rightOperand is IntState) {
+      return IntState.UNKNOWN_VALUE;
+    } else if (rightOperand is DoubleState) {
+      return DoubleState.UNKNOWN_VALUE;
+    }
+    return NumState.UNKNOWN_VALUE;
+  }
+}
+
+/**
+ * A run-time exception that would be thrown during the evaluation of Dart code.
+ */
+class EvaluationException extends JavaException {
+  /**
+   * The error code associated with the exception.
+   */
+  final ErrorCode errorCode;
+
+  /**
+   * Initialize a newly created exception to have the given [errorCode].
+   */
+  EvaluationException(this.errorCode);
+}
+
+/**
+ * The state of an object representing a function.
+ */
+class FunctionState extends InstanceState {
+  /**
+   * The element representing the function being modeled.
+   */
+  final ExecutableElement _element;
+
+  /**
+   * Initialize a newly created state to represent the function with the given
+   * [element].
+   */
+  FunctionState(this._element);
+
+  @override
+  int get hashCode => _element == null ? 0 : _element.hashCode;
+
+  @override
+  String get typeName => "Function";
+
+  @override
+  bool operator ==(Object object) =>
+      object is FunctionState && (_element == object._element);
+
+  @override
+  StringState convertToString() {
+    if (_element == null) {
+      return StringState.UNKNOWN_VALUE;
+    }
+    return new StringState(_element.name);
+  }
+
+  @override
+  BoolState equalEqual(InstanceState rightOperand) {
+    return isIdentical(rightOperand);
+  }
+
+  @override
+  BoolState isIdentical(InstanceState rightOperand) {
+    if (_element == null) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    if (rightOperand is FunctionState) {
+      ExecutableElement rightElement = rightOperand._element;
+      if (rightElement == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(_element == rightElement);
+    } else if (rightOperand is DynamicState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    return BoolState.FALSE_STATE;
+  }
+
+  @override
+  String toString() => _element == null ? "-unknown-" : _element.name;
+}
+
+/**
+ * The state of an object representing a Dart object for which there is no more
+ * specific state.
+ */
+class GenericState extends InstanceState {
+  /**
+   * Pseudo-field that we use to represent fields in the superclass.
+   */
+  static String SUPERCLASS_FIELD = "(super)";
+
+  /**
+   * A state that can be used to represent an object whose state is not known.
+   */
+  static GenericState UNKNOWN_VALUE =
+      new GenericState(new HashMap<String, DartObjectImpl>());
+
+  /**
+   * The values of the fields of this instance.
+   */
+  final HashMap<String, DartObjectImpl> _fieldMap;
+
+  /**
+   * Initialize a newly created state to represent a newly created object. The
+   * [fieldMap] contains the values of the fields of the instance.
+   */
+  GenericState(this._fieldMap);
+
+  @override
+  HashMap<String, DartObjectImpl> get fields => _fieldMap;
+
+  @override
+  int get hashCode {
+    int hashCode = 0;
+    for (DartObjectImpl value in _fieldMap.values) {
+      hashCode += value.hashCode;
+    }
+    return hashCode;
+  }
+
+  @override
+  bool get isUnknown => identical(this, UNKNOWN_VALUE);
+
+  @override
+  String get typeName => "user defined type";
+
+  @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;
+      }
+      otherFields.remove(fieldName);
+    }
+    for (String fieldName in otherFields) {
+      if (state._fieldMap[fieldName] != _fieldMap[fieldName]) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @override
+  StringState convertToString() => StringState.UNKNOWN_VALUE;
+
+  @override
+  BoolState equalEqual(InstanceState rightOperand) {
+    assertBoolNumStringOrNull(rightOperand);
+    return isIdentical(rightOperand);
+  }
+
+  @override
+  BoolState isIdentical(InstanceState rightOperand) {
+    if (rightOperand is DynamicState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    return BoolState.from(this == rightOperand);
+  }
+
+  @override
+  String toString() {
+    StringBuffer buffer = new StringBuffer();
+    List<String> fieldNames = _fieldMap.keys.toList();
+    fieldNames.sort();
+    bool first = true;
+    for (String fieldName in fieldNames) {
+      if (first) {
+        first = false;
+      } else {
+        buffer.write('; ');
+      }
+      buffer.write(fieldName);
+      buffer.write(' = ');
+      buffer.write(_fieldMap[fieldName]);
+    }
+    return buffer.toString();
+  }
+}
+
+/**
+ * The state of an object representing a Dart object.
+ */
+abstract class InstanceState {
+  /**
+   * If this represents a generic dart object, return a map from its field names
+   * to their values. Otherwise return null.
+   */
+  HashMap<String, DartObjectImpl> get fields => null;
+
+  /**
+   * Return `true` if this object represents an object whose type is 'bool'.
+   */
+  bool get isBool => false;
+
+  /**
+   * Return `true` if this object represents an object whose type is either
+   * 'bool', 'num', 'String', or 'Null'.
+   */
+  bool get isBoolNumStringOrNull => false;
+
+  /**
+   * Return `true` if this object represents an unknown value.
+   */
+  bool get isUnknown => false;
+
+  /**
+   * Return the name of the type of this value.
+   */
+  String get typeName;
+
+  /**
+   * Return the result of invoking the '+' operator on this object with the
+   * [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  InstanceState add(InstanceState rightOperand) {
+    if (this is StringState && rightOperand is StringState) {
+      return concatenate(rightOperand);
+    }
+    assertNumOrNull(this);
+    assertNumOrNull(rightOperand);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Throw an exception if the given [state] does not represent a boolean value.
+   */
+  void assertBool(InstanceState state) {
+    if (!(state is BoolState || state is DynamicState)) {
+      throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
+    }
+  }
+
+  /**
+   * Throw an exception if the given [state] does not represent a boolean,
+   * numeric, string or null value.
+   */
+  void assertBoolNumStringOrNull(InstanceState state) {
+    if (!(state is BoolState ||
+        state is DoubleState ||
+        state is IntState ||
+        state is NumState ||
+        state is StringState ||
+        state is NullState ||
+        state is DynamicState)) {
+      throw new EvaluationException(
+          CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
+    }
+  }
+
+  /**
+   * Throw an exception if the given [state] does not represent an integer or
+   * null value.
+   */
+  void assertIntOrNull(InstanceState state) {
+    if (!(state is IntState ||
+        state is NumState ||
+        state is NullState ||
+        state is DynamicState)) {
+      throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
+    }
+  }
+
+  /**
+   * Throw an exception if the given [state] does not represent a boolean,
+   * numeric, string or null value.
+   */
+  void assertNumOrNull(InstanceState state) {
+    if (!(state is DoubleState ||
+        state is IntState ||
+        state is NumState ||
+        state is NullState ||
+        state is DynamicState)) {
+      throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
+    }
+  }
+
+  /**
+   * Throw an exception if the given [state] does not represent a String value.
+   */
+  void assertString(InstanceState state) {
+    if (!(state is StringState || state is DynamicState)) {
+      throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
+    }
+  }
+
+  /**
+   * Return the result of invoking the '&' operator on this object with the
+   * [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  IntState bitAnd(InstanceState rightOperand) {
+    assertIntOrNull(this);
+    assertIntOrNull(rightOperand);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Return the result of invoking the '~' operator on this object.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  IntState bitNot() {
+    assertIntOrNull(this);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Return the result of invoking the '|' operator on this object with the
+   * [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  IntState bitOr(InstanceState rightOperand) {
+    assertIntOrNull(this);
+    assertIntOrNull(rightOperand);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Return the result of invoking the '^' operator on this object with the
+   * [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  IntState bitXor(InstanceState rightOperand) {
+    assertIntOrNull(this);
+    assertIntOrNull(rightOperand);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Return the result of invoking the ' ' operator on this object with the
+   * [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  StringState concatenate(InstanceState rightOperand) {
+    assertString(rightOperand);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Return the result of applying boolean conversion to this object.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  BoolState convertToBool() => BoolState.FALSE_STATE;
+
+  /**
+   * Return the result of converting this object to a String.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  StringState convertToString();
+
+  /**
+   * Return the result of invoking the '/' operator on this object with the
+   * [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  NumState divide(InstanceState rightOperand) {
+    assertNumOrNull(this);
+    assertNumOrNull(rightOperand);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Return the result of invoking the '==' operator on this object with the
+   * [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  BoolState equalEqual(InstanceState rightOperand);
+
+  /**
+   * Return the result of invoking the '&gt;' operator on this object with the
+   * [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  BoolState greaterThan(InstanceState rightOperand) {
+    assertNumOrNull(this);
+    assertNumOrNull(rightOperand);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Return the result of invoking the '&gt;=' operator on this object with the
+   * [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  BoolState greaterThanOrEqual(InstanceState rightOperand) {
+    assertNumOrNull(this);
+    assertNumOrNull(rightOperand);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Return the result of invoking the '~/' operator on this object with the
+   * [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  IntState integerDivide(InstanceState rightOperand) {
+    assertNumOrNull(this);
+    assertNumOrNull(rightOperand);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Return the result of invoking the identical function on this object with
+   * the [rightOperand].
+   */
+  BoolState isIdentical(InstanceState rightOperand);
+
+  /**
+   * Return the result of invoking the '&lt;' operator on this object with the
+   * [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  BoolState lessThan(InstanceState rightOperand) {
+    assertNumOrNull(this);
+    assertNumOrNull(rightOperand);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Return the result of invoking the '&lt;=' operator on this object with the
+   * [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  BoolState lessThanOrEqual(InstanceState rightOperand) {
+    assertNumOrNull(this);
+    assertNumOrNull(rightOperand);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Return the result of invoking the '&&' operator on this object with the
+   * [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  BoolState logicalAnd(InstanceState rightOperand) {
+    assertBool(this);
+    assertBool(rightOperand);
+    return BoolState.FALSE_STATE;
+  }
+
+  /**
+   * Return the result of invoking the '!' operator on this object.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  BoolState logicalNot() {
+    assertBool(this);
+    return BoolState.TRUE_STATE;
+  }
+
+  /**
+   * Return the result of invoking the '||' operator on this object with the
+   * [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  BoolState logicalOr(InstanceState rightOperand) {
+    assertBool(this);
+    assertBool(rightOperand);
+    return rightOperand.convertToBool();
+  }
+
+  /**
+   * Return the result of invoking the '-' operator on this object with the
+   * [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  NumState minus(InstanceState rightOperand) {
+    assertNumOrNull(this);
+    assertNumOrNull(rightOperand);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Return the result of invoking the '-' operator on this object.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  NumState negated() {
+    assertNumOrNull(this);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Return the result of invoking the '%' operator on this object with the
+   * [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  NumState remainder(InstanceState rightOperand) {
+    assertNumOrNull(this);
+    assertNumOrNull(rightOperand);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Return the result of invoking the '&lt;&lt;' operator on this object with
+   * the [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  IntState shiftLeft(InstanceState rightOperand) {
+    assertIntOrNull(this);
+    assertIntOrNull(rightOperand);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Return the result of invoking the '&gt;&gt;' operator on this object with
+   * the [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  IntState shiftRight(InstanceState rightOperand) {
+    assertIntOrNull(this);
+    assertIntOrNull(rightOperand);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Return the result of invoking the 'length' getter on this object.
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  IntState stringLength() {
+    assertString(this);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+
+  /**
+   * Return the result of invoking the '*' operator on this object with the
+   * [rightOperand].
+   *
+   * Throws an [EvaluationException] if the operator is not appropriate for an
+   * object of this kind.
+   */
+  NumState times(InstanceState rightOperand) {
+    assertNumOrNull(this);
+    assertNumOrNull(rightOperand);
+    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+  }
+}
+
+/**
+ * The state of an object representing an int.
+ */
+class IntState extends NumState {
+  /**
+   * A state that can be used to represent an int whose value is not known.
+   */
+  static IntState UNKNOWN_VALUE = new IntState(null);
+
+  /**
+   * The value of this instance.
+   */
+  final int value;
+
+  /**
+   * Initialize a newly created state to represent an int with the given
+   * [value].
+   */
+  IntState(this.value);
+
+  @override
+  int get hashCode => value == null ? 0 : value.hashCode;
+
+  @override
+  bool get isBoolNumStringOrNull => true;
+
+  @override
+  bool get isUnknown => value == null;
+
+  @override
+  String get typeName => "int";
+
+  @override
+  bool operator ==(Object object) =>
+      object is IntState && (value == object.value);
+
+  @override
+  NumState add(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      if (rightOperand is DoubleState) {
+        return DoubleState.UNKNOWN_VALUE;
+      }
+      return UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return new IntState(value + rightValue);
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return DoubleState.UNKNOWN_VALUE;
+      }
+      return new DoubleState(value.toDouble() + rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  IntState bitAnd(InstanceState rightOperand) {
+    assertIntOrNull(rightOperand);
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return new IntState(value & rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  IntState bitNot() {
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    return new IntState(~value);
+  }
+
+  @override
+  IntState bitOr(InstanceState rightOperand) {
+    assertIntOrNull(rightOperand);
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return new IntState(value | rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  IntState bitXor(InstanceState rightOperand) {
+    assertIntOrNull(rightOperand);
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return new IntState(value ^ rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  StringState convertToString() {
+    if (value == null) {
+      return StringState.UNKNOWN_VALUE;
+    }
+    return new StringState(value.toString());
+  }
+
+  @override
+  NumState divide(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      return DoubleState.UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return DoubleState.UNKNOWN_VALUE;
+      } else {
+        return new DoubleState(value.toDouble() / rightValue.toDouble());
+      }
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return DoubleState.UNKNOWN_VALUE;
+      }
+      return new DoubleState(value.toDouble() / rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return DoubleState.UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  BoolState equalEqual(InstanceState rightOperand) {
+    assertBoolNumStringOrNull(rightOperand);
+    return isIdentical(rightOperand);
+  }
+
+  @override
+  BoolState greaterThan(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value.compareTo(rightValue) > 0);
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value.toDouble() > rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  BoolState greaterThanOrEqual(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value.compareTo(rightValue) >= 0);
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value.toDouble() >= rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  IntState integerDivide(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      } else if (rightValue == 0) {
+        throw new EvaluationException(
+            CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE);
+      }
+      return new IntState(value ~/ rightValue);
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      double result = value.toDouble() / rightValue;
+      return new IntState(result.toInt());
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  BoolState isIdentical(InstanceState rightOperand) {
+    if (value == null) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value == rightValue);
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(rightValue == value.toDouble());
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    return BoolState.FALSE_STATE;
+  }
+
+  @override
+  BoolState lessThan(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value.compareTo(rightValue) < 0);
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value.toDouble() < rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  BoolState lessThanOrEqual(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value.compareTo(rightValue) <= 0);
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value.toDouble() <= rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  NumState minus(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      if (rightOperand is DoubleState) {
+        return DoubleState.UNKNOWN_VALUE;
+      }
+      return UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return new IntState(value - rightValue);
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return DoubleState.UNKNOWN_VALUE;
+      }
+      return new DoubleState(value.toDouble() - rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  NumState negated() {
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    return new IntState(-value);
+  }
+
+  @override
+  NumState remainder(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      if (rightOperand is DoubleState) {
+        return DoubleState.UNKNOWN_VALUE;
+      }
+      return UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      } else if (rightValue == 0) {
+        return new DoubleState(value.toDouble() % rightValue.toDouble());
+      }
+      return new IntState(value.remainder(rightValue));
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return DoubleState.UNKNOWN_VALUE;
+      }
+      return new DoubleState(value.toDouble() % rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  IntState shiftLeft(InstanceState rightOperand) {
+    assertIntOrNull(rightOperand);
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      } else if (rightValue.bitLength > 31) {
+        return UNKNOWN_VALUE;
+      }
+      return new IntState(value << rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  IntState shiftRight(InstanceState rightOperand) {
+    assertIntOrNull(rightOperand);
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      } else if (rightValue.bitLength > 31) {
+        return UNKNOWN_VALUE;
+      }
+      return new IntState(value >> rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  NumState times(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (value == null) {
+      if (rightOperand is DoubleState) {
+        return DoubleState.UNKNOWN_VALUE;
+      }
+      return UNKNOWN_VALUE;
+    }
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return new IntState(value * rightValue);
+    } else if (rightOperand is DoubleState) {
+      double rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return DoubleState.UNKNOWN_VALUE;
+      }
+      return new DoubleState(value.toDouble() * rightValue);
+    } else if (rightOperand is DynamicState || rightOperand is NumState) {
+      return UNKNOWN_VALUE;
+    }
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  String toString() => value == null ? "-unknown-" : value.toString();
+}
+
+/**
+ * The state of an object representing a list.
+ */
+class ListState extends InstanceState {
+  /**
+   * The elements of the list.
+   */
+  final List<DartObjectImpl> _elements;
+
+  /**
+   * Initialize a newly created state to represent a list with the given
+   * [elements].
+   */
+  ListState(this._elements);
+
+  @override
+  int get hashCode {
+    int value = 0;
+    int count = _elements.length;
+    for (int i = 0; i < count; i++) {
+      value = (value << 3) ^ _elements[i].hashCode;
+    }
+    return value;
+  }
+
+  @override
+  String get typeName => "List";
+
+  @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) {
+      return true;
+    }
+    for (int i = 0; i < count; i++) {
+      if (_elements[i] != otherElements[i]) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @override
+  StringState convertToString() => StringState.UNKNOWN_VALUE;
+
+  @override
+  BoolState equalEqual(InstanceState rightOperand) {
+    assertBoolNumStringOrNull(rightOperand);
+    return isIdentical(rightOperand);
+  }
+
+  @override
+  BoolState isIdentical(InstanceState rightOperand) {
+    if (rightOperand is DynamicState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    return BoolState.from(this == rightOperand);
+  }
+
+  @override
+  String toString() {
+    StringBuffer buffer = new StringBuffer();
+    buffer.write('[');
+    bool first = true;
+    _elements.forEach((DartObjectImpl element) {
+      if (first) {
+        first = false;
+      } else {
+        buffer.write(', ');
+      }
+      buffer.write(element);
+    });
+    buffer.write(']');
+    return buffer.toString();
+  }
+}
+
+/**
+ * The state of an object representing a map.
+ */
+class MapState extends InstanceState {
+  /**
+   * The entries in the map.
+   */
+  final HashMap<DartObjectImpl, DartObjectImpl> _entries;
+
+  /**
+   * Initialize a newly created state to represent a map with the given
+   * [entries].
+   */
+  MapState(this._entries);
+
+  @override
+  int get hashCode {
+    int value = 0;
+    for (DartObjectImpl key in _entries.keys.toSet()) {
+      value = (value << 3) ^ key.hashCode;
+    }
+    return value;
+  }
+
+  @override
+  String get typeName => "Map";
+
+  @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) {
+      return true;
+    }
+    for (DartObjectImpl key in _entries.keys) {
+      DartObjectImpl value = _entries[key];
+      DartObjectImpl otherValue = otherElements[key];
+      if (value != otherValue) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @override
+  StringState convertToString() => StringState.UNKNOWN_VALUE;
+
+  @override
+  BoolState equalEqual(InstanceState rightOperand) {
+    assertBoolNumStringOrNull(rightOperand);
+    return isIdentical(rightOperand);
+  }
+
+  @override
+  BoolState isIdentical(InstanceState rightOperand) {
+    if (rightOperand is DynamicState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    return BoolState.from(this == rightOperand);
+  }
+
+  @override
+  String toString() {
+    StringBuffer buffer = new StringBuffer();
+    buffer.write('{');
+    bool first = true;
+    _entries.forEach((DartObjectImpl key, DartObjectImpl value) {
+      if (first) {
+        first = false;
+      } else {
+        buffer.write(', ');
+      }
+      buffer.write(key);
+      buffer.write(' = ');
+      buffer.write(value);
+    });
+    buffer.write('}');
+    return buffer.toString();
+  }
+}
+
+/**
+ * The state of an object representing the value 'null'.
+ */
+class NullState extends InstanceState {
+  /**
+   * An instance representing the boolean value 'null'.
+   */
+  static NullState NULL_STATE = new NullState();
+
+  @override
+  int get hashCode => 0;
+
+  @override
+  bool get isBoolNumStringOrNull => true;
+
+  @override
+  String get typeName => "Null";
+
+  @override
+  bool operator ==(Object object) => object is NullState;
+
+  @override
+  BoolState convertToBool() {
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  StringState convertToString() => new StringState("null");
+
+  @override
+  BoolState equalEqual(InstanceState rightOperand) {
+    assertBoolNumStringOrNull(rightOperand);
+    return isIdentical(rightOperand);
+  }
+
+  @override
+  BoolState isIdentical(InstanceState rightOperand) {
+    if (rightOperand is DynamicState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    return BoolState.from(rightOperand is NullState);
+  }
+
+  @override
+  BoolState logicalNot() {
+    throw new EvaluationException(
+        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+  }
+
+  @override
+  String toString() => "null";
+}
+
+/**
+ * The state of an object representing a number of an unknown type (a 'num').
+ */
+class NumState extends InstanceState {
+  /**
+   * A state that can be used to represent a number whose value is not known.
+   */
+  static NumState UNKNOWN_VALUE = new NumState();
+
+  @override
+  int get hashCode => 7;
+
+  @override
+  bool get isBoolNumStringOrNull => true;
+
+  @override
+  bool get isUnknown => identical(this, UNKNOWN_VALUE);
+
+  @override
+  String get typeName => "num";
+
+  @override
+  bool operator ==(Object object) => object is NumState;
+
+  @override
+  NumState add(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return UNKNOWN_VALUE;
+  }
+
+  @override
+  StringState convertToString() => StringState.UNKNOWN_VALUE;
+
+  @override
+  NumState divide(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return DoubleState.UNKNOWN_VALUE;
+  }
+
+  @override
+  BoolState equalEqual(InstanceState rightOperand) {
+    assertBoolNumStringOrNull(rightOperand);
+    return BoolState.UNKNOWN_VALUE;
+  }
+
+  @override
+  BoolState greaterThan(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return BoolState.UNKNOWN_VALUE;
+  }
+
+  @override
+  BoolState greaterThanOrEqual(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return BoolState.UNKNOWN_VALUE;
+  }
+
+  @override
+  IntState integerDivide(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    if (rightOperand is IntState) {
+      int rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return IntState.UNKNOWN_VALUE;
+      } else if (rightValue == 0) {
+        throw new EvaluationException(
+            CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE);
+      }
+    } else if (rightOperand is DynamicState) {
+      return IntState.UNKNOWN_VALUE;
+    }
+    return IntState.UNKNOWN_VALUE;
+  }
+
+  @override
+  BoolState isIdentical(InstanceState rightOperand) {
+    return BoolState.UNKNOWN_VALUE;
+  }
+
+  @override
+  BoolState lessThan(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return BoolState.UNKNOWN_VALUE;
+  }
+
+  @override
+  BoolState lessThanOrEqual(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return BoolState.UNKNOWN_VALUE;
+  }
+
+  @override
+  NumState minus(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return UNKNOWN_VALUE;
+  }
+
+  @override
+  NumState negated() => UNKNOWN_VALUE;
+
+  @override
+  NumState remainder(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return UNKNOWN_VALUE;
+  }
+
+  @override
+  NumState times(InstanceState rightOperand) {
+    assertNumOrNull(rightOperand);
+    return UNKNOWN_VALUE;
+  }
+
+  @override
+  String toString() => "-unknown-";
+}
+
+/**
+ * The state of an object representing a string.
+ */
+class StringState extends InstanceState {
+  /**
+   * A state that can be used to represent a double whose value is not known.
+   */
+  static StringState UNKNOWN_VALUE = new StringState(null);
+
+  /**
+   * The value of this instance.
+   */
+  final String value;
+
+  /**
+   * Initialize a newly created state to represent the given [value].
+   */
+  StringState(this.value);
+
+  @override
+  int get hashCode => value == null ? 0 : value.hashCode;
+
+  @override
+  bool get isBoolNumStringOrNull => true;
+
+  @override
+  bool get isUnknown => value == null;
+
+  @override
+  String get typeName => "String";
+
+  @override
+  bool operator ==(Object object) =>
+      object is StringState && (value == object.value);
+
+  @override
+  StringState concatenate(InstanceState rightOperand) {
+    if (value == null) {
+      return UNKNOWN_VALUE;
+    }
+    if (rightOperand is StringState) {
+      String rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return UNKNOWN_VALUE;
+      }
+      return new StringState("$value$rightValue");
+    } else if (rightOperand is DynamicState) {
+      return UNKNOWN_VALUE;
+    }
+    return super.concatenate(rightOperand);
+  }
+
+  @override
+  StringState convertToString() => this;
+
+  @override
+  BoolState equalEqual(InstanceState rightOperand) {
+    assertBoolNumStringOrNull(rightOperand);
+    return isIdentical(rightOperand);
+  }
+
+  @override
+  BoolState isIdentical(InstanceState rightOperand) {
+    if (value == null) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    if (rightOperand is StringState) {
+      String rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value == rightValue);
+    } else if (rightOperand is DynamicState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    return BoolState.FALSE_STATE;
+  }
+
+  @override
+  IntState stringLength() {
+    if (value == null) {
+      return IntState.UNKNOWN_VALUE;
+    }
+    return new IntState(value.length);
+  }
+
+  @override
+  String toString() => value == null ? "-unknown-" : "'$value'";
+}
+
+/**
+ * The state of an object representing a symbol.
+ */
+class SymbolState extends InstanceState {
+  /**
+   * The value of this instance.
+   */
+  final String value;
+
+  /**
+   * Initialize a newly created state to represent the given [value].
+   */
+  SymbolState(this.value);
+
+  @override
+  int get hashCode => value == null ? 0 : value.hashCode;
+
+  @override
+  String get typeName => "Symbol";
+
+  @override
+  bool operator ==(Object object) =>
+      object is SymbolState && (value == object.value);
+
+  @override
+  StringState convertToString() {
+    if (value == null) {
+      return StringState.UNKNOWN_VALUE;
+    }
+    return new StringState(value);
+  }
+
+  @override
+  BoolState equalEqual(InstanceState rightOperand) {
+    assertBoolNumStringOrNull(rightOperand);
+    return isIdentical(rightOperand);
+  }
+
+  @override
+  BoolState isIdentical(InstanceState rightOperand) {
+    if (value == null) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    if (rightOperand is SymbolState) {
+      String rightValue = rightOperand.value;
+      if (rightValue == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(value == rightValue);
+    } else if (rightOperand is DynamicState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    return BoolState.FALSE_STATE;
+  }
+
+  @override
+  String toString() => value == null ? "-unknown-" : "#$value";
+}
+
+/**
+ * The state of an object representing a type.
+ */
+class TypeState extends InstanceState {
+  /**
+   * The element representing the type being modeled.
+   */
+  final Element _element;
+
+  /**
+   * Initialize a newly created state to represent the given [value].
+   */
+  TypeState(this._element);
+
+  @override
+  int get hashCode => _element == null ? 0 : _element.hashCode;
+
+  @override
+  String get typeName => "Type";
+
+  @override
+  bool operator ==(Object object) =>
+      object is TypeState && (_element == object._element);
+
+  @override
+  StringState convertToString() {
+    if (_element == null) {
+      return StringState.UNKNOWN_VALUE;
+    }
+    return new StringState(_element.name);
+  }
+
+  @override
+  BoolState equalEqual(InstanceState rightOperand) {
+    assertBoolNumStringOrNull(rightOperand);
+    return isIdentical(rightOperand);
+  }
+
+  @override
+  BoolState isIdentical(InstanceState rightOperand) {
+    if (_element == null) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    if (rightOperand is TypeState) {
+      Element rightElement = rightOperand._element;
+      if (rightElement == null) {
+        return BoolState.UNKNOWN_VALUE;
+      }
+      return BoolState.from(_element == rightElement);
+    } else if (rightOperand is DynamicState) {
+      return BoolState.UNKNOWN_VALUE;
+    }
+    return BoolState.FALSE_STATE;
+  }
+
+  @override
+  String toString() => _element == null ? "-unknown-" : _element.name;
+}
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 24241df..c91582c 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -9,14 +9,14 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/constant/value.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/visitor.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/handle.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/constant.dart'
-    show DartObject, EvaluationResultImpl;
+import 'package:analyzer/src/generated/constant.dart' show EvaluationResultImpl;
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisContext, AnalysisEngine;
 import 'package:analyzer/src/generated/java_core.dart';
@@ -679,9 +679,12 @@
         visitedClasses.add(this);
       }
       try {
-        ClassElementImpl superclass = supertype.element;
-        constructorsToForward =
-            superclass._computeMixinAppConstructors(visitedClasses);
+        ClassElement superclass = supertype.element;
+        if (superclass is ClassElementHandle) {
+          superclass = (superclass as ClassElementHandle).actualElement;
+        }
+        constructorsToForward = (superclass as ClassElementImpl)
+            ._computeMixinAppConstructors(visitedClasses);
       } finally {
         visitedClasses.removeLast();
       }
@@ -2091,15 +2094,6 @@
   }
 
   /**
-   * If the given [child] is not `null`, use the given [visitor] to visit it.
-   */
-  void safelyVisitChild(Element child, ElementVisitor visitor) {
-    if (child != null) {
-      child.accept(visitor);
-    }
-  }
-
-  /**
    * Use the given [visitor] to visit all of the [children] in the given array.
    */
   void safelyVisitChildren(List<Element> children, ElementVisitor visitor) {
@@ -3048,7 +3042,7 @@
   @override
   void visitChildren(ElementVisitor visitor) {
     super.visitChildren(visitor);
-    safelyVisitChild(prefix, visitor);
+    prefix?.accept(visitor);
   }
 }
 
@@ -3194,8 +3188,8 @@
    * the given [name].
    */
   LibraryElementImpl.forNode(this.context, LibraryIdentifier name)
-      : super.forNode(name),
-        nameLength = name != null ? name.length : 0;
+      : nameLength = name != null ? name.length : 0,
+        super.forNode(name);
 
   @override
   int get codeLength {
@@ -3600,14 +3594,19 @@
     // are in the case where library cycles have simply never been computed from
     // a newly reachable node.
     Set<LibraryElementImpl> active = new HashSet();
-    void invalidate(LibraryElementImpl library) {
-      if (!active.add(library)) return;
-      if (library._libraryCycle != null) {
-        library._libraryCycle.forEach(invalidate);
-        library._libraryCycle = null;
+    void invalidate(LibraryElement library) {
+      if (library is LibraryElementHandle) {
+        library = (library as LibraryElementHandle).actualElement;
       }
-      library.exportedLibraries.forEach(invalidate);
-      library.importedLibraries.forEach(invalidate);
+      LibraryElementImpl libraryImpl = library;
+      if (active.add(libraryImpl)) {
+        if (libraryImpl._libraryCycle != null) {
+          libraryImpl._libraryCycle.forEach(invalidate);
+          libraryImpl._libraryCycle = null;
+        }
+        library.exportedLibraries.forEach(invalidate);
+        library.importedLibraries.forEach(invalidate);
+      }
     }
     invalidate(this);
   }
@@ -3621,7 +3620,7 @@
   @override
   void visitChildren(ElementVisitor visitor) {
     super.visitChildren(visitor);
-    safelyVisitChild(_definingCompilationUnit, visitor);
+    _definingCompilationUnit?.accept(visitor);
     safelyVisitChildren(_exports, visitor);
     safelyVisitChildren(_imports, visitor);
     safelyVisitChildren(_parts, visitor);
@@ -4917,7 +4916,7 @@
   @override
   void visitChildren(ElementVisitor visitor) {
     super.visitChildren(visitor);
-    safelyVisitChild(_initializer, visitor);
+    _initializer?.accept(visitor);
   }
 }
 
diff --git a/pkg/analyzer/lib/src/dart/element/handle.dart b/pkg/analyzer/lib/src/dart/element/handle.dart
index dfecff2..8cde8d0 100644
--- a/pkg/analyzer/lib/src/dart/element/handle.dart
+++ b/pkg/analyzer/lib/src/dart/element/handle.dart
@@ -5,10 +5,10 @@
 library analyzer.src.generated.element_handle;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/constant/value.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/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 28bce1e..0ac6d4a 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -5,12 +5,11 @@
 library analyzer.src.dart.element.member;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/constant/value.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/constant.dart'
-    show DartObject, EvaluationResultImpl;
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisContext, AnalysisEngine;
 import 'package:analyzer/src/generated/java_core.dart';
@@ -524,6 +523,7 @@
   /**
    * If the given [child] is not `null`, use the given [visitor] to visit it.
    */
+  @deprecated
   void safelyVisitChild(Element child, ElementVisitor visitor) {
     // TODO(brianwilkerson) Make this private
     if (child != null) {
@@ -1017,10 +1017,12 @@
   bool get isFinal => baseElement.isFinal;
 
   @override
+  @deprecated
   bool get isPotentiallyMutatedInClosure =>
       baseElement.isPotentiallyMutatedInClosure;
 
   @override
+  @deprecated
   bool get isPotentiallyMutatedInScope =>
       baseElement.isPotentiallyMutatedInScope;
 
@@ -1032,6 +1034,6 @@
     // TODO(brianwilkerson) We need to finish implementing the accessors used
     // below so that we can safely invoke them.
     super.visitChildren(visitor);
-    safelyVisitChild(baseElement.initializer, visitor);
+    baseElement.initializer?.accept(visitor);
   }
 }
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index 0f1d7e9..16113c5 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -4,1069 +4,24 @@
 
 library analyzer.src.generated.constant;
 
-import 'dart:collection';
-
+import 'package:analyzer/context/declared_variables.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/handle.dart'
-    show ConstructorElementHandle;
-import 'package:analyzer/src/dart/element/member.dart';
+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/error.dart';
-import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
 import 'package:analyzer/src/generated/source.dart' show Source;
 import 'package:analyzer/src/generated/type_system.dart'
     show TypeSystem, TypeSystemImpl;
-import 'package:analyzer/src/generated/utilities_collection.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart' show ParameterKind;
-import 'package:analyzer/src/generated/utilities_general.dart';
-import 'package:analyzer/src/task/dart.dart';
 
-ConstructorElementImpl _getConstructorImpl(ConstructorElement constructor) {
-  while (constructor is ConstructorMember) {
-    constructor = (constructor as ConstructorMember).baseElement;
-  }
-  if (constructor is ConstructorElementHandle) {
-    constructor = (constructor as ConstructorElementHandle).actualElement;
-  }
-  return constructor;
-}
-
-/**
- * Callback used by [ReferenceFinder] to report that a dependency was found.
- */
-typedef void ReferenceFinderCallback(ConstantEvaluationTarget dependency);
-
-/**
- * The state of an object representing a boolean value.
- */
-class BoolState extends InstanceState {
-  /**
-   * An instance representing the boolean value 'false'.
-   */
-  static BoolState FALSE_STATE = new BoolState(false);
-
-  /**
-   * An instance representing the boolean value 'true'.
-   */
-  static BoolState TRUE_STATE = new BoolState(true);
-
-  /**
-   * A state that can be used to represent a boolean whose value is not known.
-   */
-  static BoolState UNKNOWN_VALUE = new BoolState(null);
-
-  /**
-   * The value of this instance.
-   */
-  final bool value;
-
-  /**
-   * Initialize a newly created state to represent the given [value].
-   */
-  BoolState(this.value);
-
-  @override
-  int get hashCode => value == null ? 0 : (value ? 2 : 3);
-
-  @override
-  bool get isBool => true;
-
-  @override
-  bool get isBoolNumStringOrNull => true;
-
-  @override
-  bool get isUnknown => value == null;
-
-  @override
-  String get typeName => "bool";
-
-  @override
-  bool operator ==(Object object) =>
-      object is BoolState && identical(value, object.value);
-
-  @override
-  BoolState convertToBool() => this;
-
-  @override
-  StringState convertToString() {
-    if (value == null) {
-      return StringState.UNKNOWN_VALUE;
-    }
-    return new StringState(value ? "true" : "false");
-  }
-
-  @override
-  BoolState equalEqual(InstanceState rightOperand) {
-    assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
-  }
-
-  @override
-  BoolState isIdentical(InstanceState rightOperand) {
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    if (rightOperand is BoolState) {
-      bool rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return BoolState.from(identical(value, rightValue));
-    } else if (rightOperand is DynamicState) {
-      return UNKNOWN_VALUE;
-    }
-    return FALSE_STATE;
-  }
-
-  @override
-  BoolState logicalAnd(InstanceState rightOperand) {
-    assertBool(rightOperand);
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    return value ? rightOperand.convertToBool() : FALSE_STATE;
-  }
-
-  @override
-  BoolState logicalNot() {
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    return value ? FALSE_STATE : TRUE_STATE;
-  }
-
-  @override
-  BoolState logicalOr(InstanceState rightOperand) {
-    assertBool(rightOperand);
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    return value ? TRUE_STATE : rightOperand.convertToBool();
-  }
-
-  @override
-  String toString() => value == null ? "-unknown-" : (value ? "true" : "false");
-
-  /**
-   * Return the boolean state representing the given boolean [value].
-   */
-  static BoolState from(bool value) =>
-      value ? BoolState.TRUE_STATE : BoolState.FALSE_STATE;
-}
-
-/**
- * An [AstCloner] that copies the necessary information from the AST to allow
- * constants to be evaluated.
- */
-class ConstantAstCloner extends AstCloner {
-  ConstantAstCloner() : super(true);
-
-  @override
-  ConstructorName visitConstructorName(ConstructorName node) {
-    ConstructorName name = super.visitConstructorName(node);
-    name.staticElement = node.staticElement;
-    return name;
-  }
-
-  @override
-  InstanceCreationExpression visitInstanceCreationExpression(
-      InstanceCreationExpression node) {
-    InstanceCreationExpression expression =
-        super.visitInstanceCreationExpression(node);
-    expression.staticElement = node.staticElement;
-    return expression;
-  }
-
-  @override
-  RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
-      RedirectingConstructorInvocation node) {
-    RedirectingConstructorInvocation invocation =
-        super.visitRedirectingConstructorInvocation(node);
-    invocation.staticElement = node.staticElement;
-    return invocation;
-  }
-
-  @override
-  SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) {
-    SimpleIdentifier identifier = super.visitSimpleIdentifier(node);
-    identifier.staticElement = node.staticElement;
-    return identifier;
-  }
-
-  @override
-  SuperConstructorInvocation visitSuperConstructorInvocation(
-      SuperConstructorInvocation node) {
-    SuperConstructorInvocation invocation =
-        super.visitSuperConstructorInvocation(node);
-    invocation.staticElement = node.staticElement;
-    return invocation;
-  }
-
-  @override
-  TypeName visitTypeName(TypeName node) {
-    TypeName typeName = super.visitTypeName(node);
-    typeName.type = node.type;
-    return typeName;
-  }
-}
-
-/**
- * Helper class encapsulating the methods for evaluating constants and
- * constant instance creation expressions.
- */
-class ConstantEvaluationEngine {
-  /**
-   * Parameter to "fromEnvironment" methods that denotes the default value.
-   */
-  static String _DEFAULT_VALUE_PARAM = "defaultValue";
-
-  /**
-   * Source of RegExp matching any public identifier.
-   * From sdk/lib/internal/symbol.dart.
-   */
-  static String _PUBLIC_IDENTIFIER_RE =
-      "(?!${ConstantValueComputer._RESERVED_WORD_RE}\\b(?!\\\$))[a-zA-Z\$][\\w\$]*";
-
-  /**
-   * RegExp that validates a non-empty non-private symbol.
-   * From sdk/lib/internal/symbol.dart.
-   */
-  static RegExp _PUBLIC_SYMBOL_PATTERN = new RegExp(
-      "^(?:${ConstantValueComputer._OPERATOR_RE}\$|$_PUBLIC_IDENTIFIER_RE(?:=?\$|[.](?!\$)))+?\$");
-
-  /**
-   * The type provider used to access the known types.
-   */
-  final TypeProvider typeProvider;
-
-  /**
-   * The type system.  This is used to guess the types of constants when their
-   * exact value is unknown.
-   */
-  final TypeSystem typeSystem;
-
-  /**
-   * The set of variables declared on the command line using '-D'.
-   */
-  final DeclaredVariables _declaredVariables;
-
-  /**
-   * Validator used to verify correct dependency analysis when running unit
-   * tests.
-   */
-  final ConstantEvaluationValidator validator;
-
-  /**
-   * Initialize a newly created [ConstantEvaluationEngine].  The [typeProvider]
-   * is used to access known types.  [_declaredVariables] is the set of
-   * variables declared on the command line using '-D'.  The [validator], if
-   * given, is used to verify correct dependency analysis when running unit
-   * tests.
-   */
-  ConstantEvaluationEngine(this.typeProvider, this._declaredVariables,
-      {ConstantEvaluationValidator validator, TypeSystem typeSystem})
-      : validator = validator != null
-            ? validator
-            : new ConstantEvaluationValidator_ForProduction(),
-        typeSystem = typeSystem != null ? typeSystem : new TypeSystemImpl();
-
-  /**
-   * Check that the arguments to a call to fromEnvironment() are correct. The
-   * [arguments] are the AST nodes of the arguments. The [argumentValues] are
-   * the values of the unnamed arguments. The [namedArgumentValues] are the
-   * values of the named arguments. The [expectedDefaultValueType] is the
-   * allowed type of the "defaultValue" parameter (if present). Note:
-   * "defaultValue" is always allowed to be null. Return `true` if the arguments
-   * are correct, `false` if there is an error.
-   */
-  bool checkFromEnvironmentArguments(
-      NodeList<Expression> arguments,
-      List<DartObjectImpl> argumentValues,
-      HashMap<String, DartObjectImpl> namedArgumentValues,
-      InterfaceType expectedDefaultValueType) {
-    int argumentCount = arguments.length;
-    if (argumentCount < 1 || argumentCount > 2) {
-      return false;
-    }
-    if (arguments[0] is NamedExpression) {
-      return false;
-    }
-    if (!identical(argumentValues[0].type, typeProvider.stringType)) {
-      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))) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  /**
-   * Check that the arguments to a call to Symbol() are correct. The [arguments]
-   * are the AST nodes of the arguments. The [argumentValues] are the values of
-   * the unnamed arguments. The [namedArgumentValues] are the values of the
-   * named arguments. Return `true` if the arguments are correct, `false` if
-   * there is an error.
-   */
-  bool checkSymbolArguments(
-      NodeList<Expression> arguments,
-      List<DartObjectImpl> argumentValues,
-      HashMap<String, DartObjectImpl> namedArgumentValues) {
-    if (arguments.length != 1) {
-      return false;
-    }
-    if (arguments[0] is NamedExpression) {
-      return false;
-    }
-    if (!identical(argumentValues[0].type, typeProvider.stringType)) {
-      return false;
-    }
-    String name = argumentValues[0].toStringValue();
-    return isValidPublicSymbol(name);
-  }
-
-  /**
-   * Compute the constant value associated with the given [constant].
-   */
-  void computeConstantValue(ConstantEvaluationTarget constant) {
-    validator.beforeComputeValue(constant);
-    if (constant is ParameterElementImpl) {
-      Expression defaultValue = constant.constantInitializer;
-      if (defaultValue != null) {
-        RecordingErrorListener errorListener = new RecordingErrorListener();
-        ErrorReporter errorReporter =
-            new ErrorReporter(errorListener, constant.source);
-        DartObjectImpl dartObject =
-            defaultValue.accept(new ConstantVisitor(this, errorReporter));
-        constant.evaluationResult =
-            new EvaluationResultImpl(dartObject, errorListener.errors);
-      }
-    } else if (constant is VariableElementImpl) {
-      Expression constantInitializer = constant.constantInitializer;
-      if (constantInitializer != null) {
-        RecordingErrorListener errorListener = new RecordingErrorListener();
-        ErrorReporter errorReporter =
-            new ErrorReporter(errorListener, constant.source);
-        DartObjectImpl dartObject = constantInitializer
-            .accept(new ConstantVisitor(this, errorReporter));
-        // Only check the type for truly const declarations (don't check final
-        // fields with initializers, since their types may be generic.  The type
-        // of the final field will be checked later, when the constructor is
-        // invoked).
-        if (dartObject != null && constant.isConst) {
-          if (!runtimeTypeMatch(dartObject, constant.type)) {
-            errorReporter.reportErrorForElement(
-                CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
-                constant,
-                [dartObject.type, constant.type]);
-          }
-        }
-        constant.evaluationResult =
-            new EvaluationResultImpl(dartObject, errorListener.errors);
-      }
-    } else if (constant is ConstructorElement) {
-      if (constant.isConst) {
-        // No evaluation needs to be done; constructor declarations are only in
-        // the dependency graph to ensure that any constants referred to in
-        // initializer lists and parameter defaults are evaluated before
-        // invocations of the constructor.  However we do need to annotate the
-        // element as being free of constant evaluation cycles so that later
-        // code will know that it is safe to evaluate.
-        (constant as ConstructorElementImpl).isCycleFree = true;
-      }
-    } else if (constant is ElementAnnotationImpl) {
-      Annotation constNode = constant.annotationAst;
-      Element element = constant.element;
-      if (element is PropertyAccessorElement &&
-          element.variable is VariableElementImpl) {
-        // The annotation is a reference to a compile-time constant variable.
-        // Just copy the evaluation result.
-        VariableElementImpl variableElement =
-            element.variable as VariableElementImpl;
-        if (variableElement.evaluationResult != null) {
-          constant.evaluationResult = variableElement.evaluationResult;
-        } else {
-          // This could happen in the event that the annotation refers to a
-          // non-constant.  The error is detected elsewhere, so just silently
-          // ignore it here.
-          constant.evaluationResult = new EvaluationResultImpl(null);
-        }
-      } else if (element is ConstructorElementImpl &&
-          element.isConst &&
-          constNode.arguments != null) {
-        RecordingErrorListener errorListener = new RecordingErrorListener();
-        ErrorReporter errorReporter =
-            new ErrorReporter(errorListener, constant.source);
-        ConstantVisitor constantVisitor =
-            new ConstantVisitor(this, errorReporter);
-        DartObjectImpl result = evaluateConstructorCall(
-            constNode,
-            constNode.arguments.arguments,
-            element,
-            constantVisitor,
-            errorReporter);
-        constant.evaluationResult =
-            new EvaluationResultImpl(result, errorListener.errors);
-      } else {
-        // This may happen for invalid code (e.g. failing to pass arguments
-        // to an annotation which references a const constructor).  The error
-        // is detected elsewhere, so just silently ignore it here.
-        constant.evaluationResult = new EvaluationResultImpl(null);
-      }
-    } else if (constant is VariableElement) {
-      // constant is a VariableElement but not a VariableElementImpl.  This can
-      // happen sometimes in the case of invalid user code (for example, a
-      // constant expression that refers to a non-static field inside a generic
-      // class will wind up referring to a FieldMember).  The error is detected
-      // elsewhere, so just silently ignore it here.
-    } else {
-      // Should not happen.
-      assert(false);
-      AnalysisEngine.instance.logger.logError(
-          "Constant value computer trying to compute the value of a node of type ${constant.runtimeType}");
-      return;
-    }
-  }
-
-  /**
-   * Determine which constant elements need to have their values computed
-   * prior to computing the value of [constant], and report them using
-   * [callback].
-   */
-  void computeDependencies(
-      ConstantEvaluationTarget constant, ReferenceFinderCallback callback) {
-    ReferenceFinder referenceFinder = new ReferenceFinder(callback);
-    if (constant is ConstructorElement) {
-      constant = _getConstructorImpl(constant);
-    }
-    if (constant is VariableElementImpl) {
-      Expression initializer = constant.constantInitializer;
-      if (initializer != null) {
-        initializer.accept(referenceFinder);
-      }
-    } else if (constant is ConstructorElementImpl) {
-      if (constant.isConst) {
-        constant.isCycleFree = false;
-        ConstructorElement redirectedConstructor =
-            getConstRedirectedConstructor(constant);
-        if (redirectedConstructor != null) {
-          ConstructorElement redirectedConstructorBase =
-              _getConstructorImpl(redirectedConstructor);
-          callback(redirectedConstructorBase);
-          return;
-        } else if (constant.isFactory) {
-          // Factory constructor, but getConstRedirectedConstructor returned
-          // null.  This can happen if we're visiting one of the special external
-          // const factory constructors in the SDK, or if the code contains
-          // errors (such as delegating to a non-const constructor, or delegating
-          // to a constructor that can't be resolved).  In any of these cases,
-          // we'll evaluate calls to this constructor without having to refer to
-          // any other constants.  So we don't need to report any dependencies.
-          return;
-        }
-        bool superInvocationFound = false;
-        List<ConstructorInitializer> initializers =
-            constant.constantInitializers;
-        for (ConstructorInitializer initializer in initializers) {
-          if (initializer is SuperConstructorInvocation) {
-            superInvocationFound = true;
-          }
-          initializer.accept(referenceFinder);
-        }
-        if (!superInvocationFound) {
-          // No explicit superconstructor invocation found, so we need to
-          // manually insert a reference to the implicit superconstructor.
-          InterfaceType superclass =
-              (constant.returnType as InterfaceType).superclass;
-          if (superclass != null && !superclass.isObject) {
-            ConstructorElement unnamedConstructor =
-                _getConstructorImpl(superclass.element.unnamedConstructor);
-            if (unnamedConstructor != null) {
-              callback(unnamedConstructor);
-            }
-          }
-        }
-        for (FieldElement field in constant.enclosingElement.fields) {
-          // Note: non-static const isn't allowed but we handle it anyway so
-          // that we won't be confused by incorrect code.
-          if ((field.isFinal || field.isConst) &&
-              !field.isStatic &&
-              field.initializer != null) {
-            callback(field);
-          }
-        }
-        for (ParameterElement parameterElement in constant.parameters) {
-          callback(parameterElement);
-        }
-      }
-    } else if (constant is ElementAnnotationImpl) {
-      Annotation constNode = constant.annotationAst;
-      Element element = constant.element;
-      if (element is PropertyAccessorElement &&
-          element.variable is VariableElementImpl) {
-        // The annotation is a reference to a compile-time constant variable,
-        // so it depends on the variable.
-        callback(element.variable);
-      } else if (element is ConstructorElementImpl) {
-        // The annotation is a constructor invocation, so it depends on the
-        // constructor.
-        callback(element);
-      } else {
-        // This could happen in the event of invalid code.  The error will be
-        // reported at constant evaluation time.
-      }
-      if (constNode.arguments != null) {
-        constNode.arguments.accept(referenceFinder);
-      }
-    } else if (constant is VariableElement) {
-      // constant is a VariableElement but not a VariableElementImpl.  This can
-      // happen sometimes in the case of invalid user code (for example, a
-      // constant expression that refers to a non-static field inside a generic
-      // class will wind up referring to a FieldMember).  So just don't bother
-      // computing any dependencies.
-    } else {
-      // Should not happen.
-      assert(false);
-      AnalysisEngine.instance.logger.logError(
-          "Constant value computer trying to compute the value of a node of type ${constant.runtimeType}");
-    }
-  }
-
-  /**
-   * Evaluate a call to fromEnvironment() on the bool, int, or String class. The
-   * [environmentValue] is the value fetched from the environment. The
-   * [builtInDefaultValue] is the value that should be used as the default if no
-   * "defaultValue" argument appears in [namedArgumentValues]. The
-   * [namedArgumentValues] are the values of the named parameters passed to
-   * fromEnvironment(). Return a [DartObjectImpl] object corresponding to the
-   * evaluated result.
-   */
-  DartObjectImpl computeValueFromEnvironment(
-      DartObject environmentValue,
-      DartObjectImpl builtInDefaultValue,
-      HashMap<String, DartObjectImpl> namedArgumentValues) {
-    DartObjectImpl value = environmentValue as DartObjectImpl;
-    if (value.isUnknown || value.isNull) {
-      // The name either doesn't exist in the environment or we couldn't parse
-      // the corresponding value.
-      // If the code supplied an explicit default, use it.
-      if (namedArgumentValues.containsKey(_DEFAULT_VALUE_PARAM)) {
-        value = namedArgumentValues[_DEFAULT_VALUE_PARAM];
-      } else if (value.isNull) {
-        // The code didn't supply an explicit default.
-        // The name exists in the environment but we couldn't parse the
-        // corresponding value.
-        // So use the built-in default value, because this is what the VM does.
-        value = builtInDefaultValue;
-      } else {
-        // The code didn't supply an explicit default.
-        // The name doesn't exist in the environment.
-        // The VM would use the built-in default value, but we don't want to do
-        // that for analysis because it's likely to lead to cascading errors.
-        // So just leave [value] in the unknown state.
-      }
-    }
-    return value;
-  }
-
-  DartObjectImpl evaluateConstructorCall(
-      AstNode node,
-      NodeList<Expression> arguments,
-      ConstructorElement constructor,
-      ConstantVisitor constantVisitor,
-      ErrorReporter errorReporter) {
-    if (!_getConstructorImpl(constructor).isCycleFree) {
-      // It's not safe to evaluate this constructor, so bail out.
-      // TODO(paulberry): ensure that a reasonable error message is produced
-      // in this case, as well as other cases involving constant expression
-      // circularities (e.g. "compile-time constant expression depends on
-      // itself")
-      return new DartObjectImpl.validWithUnknownValue(constructor.returnType);
-    }
-    int argumentCount = arguments.length;
-    List<DartObjectImpl> argumentValues =
-        new List<DartObjectImpl>(argumentCount);
-    List<Expression> argumentNodes = new List<Expression>(argumentCount);
-    HashMap<String, DartObjectImpl> namedArgumentValues =
-        new HashMap<String, DartObjectImpl>();
-    HashMap<String, NamedExpression> namedArgumentNodes =
-        new HashMap<String, NamedExpression>();
-    for (int i = 0; i < argumentCount; i++) {
-      Expression argument = arguments[i];
-      if (argument is NamedExpression) {
-        String name = argument.name.label.name;
-        namedArgumentValues[name] =
-            constantVisitor._valueOf(argument.expression);
-        namedArgumentNodes[name] = argument;
-        argumentValues[i] = typeProvider.nullObject;
-      } else {
-        argumentValues[i] = constantVisitor._valueOf(argument);
-        argumentNodes[i] = argument;
-      }
-    }
-    constructor = followConstantRedirectionChain(constructor);
-    InterfaceType definingClass = constructor.returnType as InterfaceType;
-    if (constructor.isFactory) {
-      // We couldn't find a non-factory constructor.
-      // See if it's because we reached an external const factory constructor
-      // that we can emulate.
-      if (constructor.name == "fromEnvironment") {
-        if (!checkFromEnvironmentArguments(
-            arguments, argumentValues, namedArgumentValues, definingClass)) {
-          errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
-          return null;
-        }
-        String variableName =
-            argumentCount < 1 ? null : argumentValues[0].toStringValue();
-        if (identical(definingClass, typeProvider.boolType)) {
-          DartObject valueFromEnvironment;
-          valueFromEnvironment =
-              _declaredVariables.getBool(typeProvider, variableName);
-          return computeValueFromEnvironment(
-              valueFromEnvironment,
-              new DartObjectImpl(typeProvider.boolType, BoolState.FALSE_STATE),
-              namedArgumentValues);
-        } else if (identical(definingClass, typeProvider.intType)) {
-          DartObject valueFromEnvironment;
-          valueFromEnvironment =
-              _declaredVariables.getInt(typeProvider, variableName);
-          return computeValueFromEnvironment(
-              valueFromEnvironment,
-              new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE),
-              namedArgumentValues);
-        } else if (identical(definingClass, typeProvider.stringType)) {
-          DartObject valueFromEnvironment;
-          valueFromEnvironment =
-              _declaredVariables.getString(typeProvider, variableName);
-          return computeValueFromEnvironment(
-              valueFromEnvironment,
-              new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE),
-              namedArgumentValues);
-        }
-      } else if (constructor.name == "" &&
-          identical(definingClass, typeProvider.symbolType) &&
-          argumentCount == 1) {
-        if (!checkSymbolArguments(
-            arguments, argumentValues, namedArgumentValues)) {
-          errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
-          return null;
-        }
-        String argumentValue = argumentValues[0].toStringValue();
-        return new DartObjectImpl(
-            definingClass, new SymbolState(argumentValue));
-      }
-      // Either it's an external const factory constructor that we can't
-      // emulate, or an error occurred (a cycle, or a const constructor trying
-      // to delegate to a non-const constructor).
-      // In the former case, the best we can do is consider it an unknown value.
-      // In the latter case, the error has already been reported, so considering
-      // it an unknown value will suppress further errors.
-      return new DartObjectImpl.validWithUnknownValue(definingClass);
-    }
-    ConstructorElementImpl constructorBase = _getConstructorImpl(constructor);
-    validator.beforeGetConstantInitializers(constructorBase);
-    List<ConstructorInitializer> initializers =
-        constructorBase.constantInitializers;
-    if (initializers == null) {
-      // This can happen in some cases where there are compile errors in the
-      // code being analyzed (for example if the code is trying to create a
-      // const instance using a non-const constructor, or the node we're
-      // visiting is involved in a cycle).  The error has already been reported,
-      // so consider it an unknown value to suppress further errors.
-      return new DartObjectImpl.validWithUnknownValue(definingClass);
-    }
-    HashMap<String, DartObjectImpl> fieldMap =
-        new HashMap<String, DartObjectImpl>();
-    // Start with final fields that are initialized at their declaration site.
-    for (FieldElement field in constructor.enclosingElement.fields) {
-      if ((field.isFinal || field.isConst) &&
-          !field.isStatic &&
-          field is ConstFieldElementImpl) {
-        validator.beforeGetFieldEvaluationResult(field);
-        EvaluationResultImpl evaluationResult = field.evaluationResult;
-        // It is possible that the evaluation result is null.
-        // This happens for example when we have duplicate fields.
-        // class Test {final x = 1; final x = 2; const Test();}
-        if (evaluationResult == null) {
-          continue;
-        }
-        // Match the value and the type.
-        DartType fieldType =
-            FieldMember.from(field, constructor.returnType).type;
-        DartObjectImpl fieldValue = evaluationResult.value;
-        if (fieldValue != null && !runtimeTypeMatch(fieldValue, fieldType)) {
-          errorReporter.reportErrorForNode(
-              CheckedModeCompileTimeErrorCode
-                  .CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
-              node,
-              [fieldValue.type, field.name, fieldType]);
-        }
-        fieldMap[field.name] = fieldValue;
-      }
-    }
-    // Now evaluate the constructor declaration.
-    HashMap<String, DartObjectImpl> parameterMap =
-        new HashMap<String, DartObjectImpl>();
-    List<ParameterElement> parameters = constructor.parameters;
-    int parameterCount = parameters.length;
-    for (int i = 0; i < parameterCount; i++) {
-      ParameterElement parameter = parameters[i];
-      ParameterElement baseParameter = parameter;
-      while (baseParameter is ParameterMember) {
-        baseParameter = (baseParameter as ParameterMember).baseElement;
-      }
-      DartObjectImpl argumentValue = null;
-      AstNode errorTarget = null;
-      if (baseParameter.parameterKind == ParameterKind.NAMED) {
-        argumentValue = namedArgumentValues[baseParameter.name];
-        errorTarget = namedArgumentNodes[baseParameter.name];
-      } else if (i < argumentCount) {
-        argumentValue = argumentValues[i];
-        errorTarget = argumentNodes[i];
-      }
-      if (errorTarget == null) {
-        // No argument node that we can direct error messages to, because we
-        // are handling an optional parameter that wasn't specified.  So just
-        // direct error messages to the constructor call.
-        errorTarget = node;
-      }
-      if (argumentValue == null && baseParameter is ParameterElementImpl) {
-        // The parameter is an optional positional parameter for which no value
-        // was provided, so use the default value.
-        validator.beforeGetParameterDefault(baseParameter);
-        EvaluationResultImpl evaluationResult = baseParameter.evaluationResult;
-        if (evaluationResult == null) {
-          // No default was provided, so the default value is null.
-          argumentValue = typeProvider.nullObject;
-        } else if (evaluationResult.value != null) {
-          argumentValue = evaluationResult.value;
-        }
-      }
-      if (argumentValue != null) {
-        if (!runtimeTypeMatch(argumentValue, parameter.type)) {
-          errorReporter.reportErrorForNode(
-              CheckedModeCompileTimeErrorCode
-                  .CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-              errorTarget,
-              [argumentValue.type, parameter.type]);
-        }
-        if (baseParameter.isInitializingFormal) {
-          FieldElement field = (parameter as FieldFormalParameterElement).field;
-          if (field != null) {
-            DartType fieldType = field.type;
-            if (fieldType != parameter.type) {
-              // We've already checked that the argument can be assigned to the
-              // parameter; we also need to check that it can be assigned to
-              // the field.
-              if (!runtimeTypeMatch(argumentValue, fieldType)) {
-                errorReporter.reportErrorForNode(
-                    CheckedModeCompileTimeErrorCode
-                        .CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-                    errorTarget,
-                    [argumentValue.type, fieldType]);
-              }
-            }
-            String fieldName = field.name;
-            if (fieldMap.containsKey(fieldName)) {
-              errorReporter.reportErrorForNode(
-                  CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
-            }
-            fieldMap[fieldName] = argumentValue;
-          }
-        } else {
-          String name = baseParameter.name;
-          parameterMap[name] = argumentValue;
-        }
-      }
-    }
-    ConstantVisitor initializerVisitor = new ConstantVisitor(
-        this, errorReporter,
-        lexicalEnvironment: parameterMap);
-    String superName = null;
-    NodeList<Expression> superArguments = null;
-    for (ConstructorInitializer initializer in initializers) {
-      if (initializer is ConstructorFieldInitializer) {
-        ConstructorFieldInitializer constructorFieldInitializer = initializer;
-        Expression initializerExpression =
-            constructorFieldInitializer.expression;
-        DartObjectImpl evaluationResult =
-            initializerExpression.accept(initializerVisitor);
-        if (evaluationResult != null) {
-          String fieldName = constructorFieldInitializer.fieldName.name;
-          if (fieldMap.containsKey(fieldName)) {
-            errorReporter.reportErrorForNode(
-                CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
-          }
-          fieldMap[fieldName] = evaluationResult;
-          PropertyAccessorElement getter = definingClass.getGetter(fieldName);
-          if (getter != null) {
-            PropertyInducingElement field = getter.variable;
-            if (!runtimeTypeMatch(evaluationResult, field.type)) {
-              errorReporter.reportErrorForNode(
-                  CheckedModeCompileTimeErrorCode
-                      .CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
-                  node,
-                  [evaluationResult.type, fieldName, field.type]);
-            }
-          }
-        }
-      } else if (initializer is SuperConstructorInvocation) {
-        SuperConstructorInvocation superConstructorInvocation = initializer;
-        SimpleIdentifier name = superConstructorInvocation.constructorName;
-        if (name != null) {
-          superName = name.name;
-        }
-        superArguments = superConstructorInvocation.argumentList.arguments;
-      } else if (initializer is RedirectingConstructorInvocation) {
-        // This is a redirecting constructor, so just evaluate the constructor
-        // it redirects to.
-        ConstructorElement constructor = initializer.staticElement;
-        if (constructor != null && constructor.isConst) {
-          return evaluateConstructorCall(
-              node,
-              initializer.argumentList.arguments,
-              constructor,
-              initializerVisitor,
-              errorReporter);
-        }
-      }
-    }
-    // Evaluate explicit or implicit call to super().
-    InterfaceType superclass = definingClass.superclass;
-    if (superclass != null && !superclass.isObject) {
-      ConstructorElement superConstructor =
-          superclass.lookUpConstructor(superName, constructor.library);
-      if (superConstructor != null) {
-        if (superArguments == null) {
-          superArguments = new NodeList<Expression>(null);
-        }
-        evaluateSuperConstructorCall(node, fieldMap, superConstructor,
-            superArguments, initializerVisitor, errorReporter);
-      }
-    }
-    return new DartObjectImpl(definingClass, new GenericState(fieldMap));
-  }
-
-  void evaluateSuperConstructorCall(
-      AstNode node,
-      HashMap<String, DartObjectImpl> fieldMap,
-      ConstructorElement superConstructor,
-      NodeList<Expression> superArguments,
-      ConstantVisitor initializerVisitor,
-      ErrorReporter errorReporter) {
-    if (superConstructor != null && superConstructor.isConst) {
-      DartObjectImpl evaluationResult = evaluateConstructorCall(node,
-          superArguments, superConstructor, initializerVisitor, errorReporter);
-      if (evaluationResult != null) {
-        fieldMap[GenericState.SUPERCLASS_FIELD] = evaluationResult;
-      }
-    }
-  }
-
-  /**
-   * Attempt to follow the chain of factory redirections until a constructor is
-   * reached which is not a const factory constructor. Return the constant
-   * constructor which terminates the chain of factory redirections, if the
-   * chain terminates. If there is a problem (e.g. a redirection can't be found,
-   * or a cycle is encountered), the chain will be followed as far as possible
-   * and then a const factory constructor will be returned.
-   */
-  ConstructorElement followConstantRedirectionChain(
-      ConstructorElement constructor) {
-    HashSet<ConstructorElement> constructorsVisited =
-        new HashSet<ConstructorElement>();
-    while (true) {
-      ConstructorElement redirectedConstructor =
-          getConstRedirectedConstructor(constructor);
-      if (redirectedConstructor == null) {
-        break;
-      } else {
-        ConstructorElement constructorBase = _getConstructorImpl(constructor);
-        constructorsVisited.add(constructorBase);
-        ConstructorElement redirectedConstructorBase =
-            _getConstructorImpl(redirectedConstructor);
-        if (constructorsVisited.contains(redirectedConstructorBase)) {
-          // Cycle in redirecting factory constructors--this is not allowed
-          // and is checked elsewhere--see
-          // [ErrorVerifier.checkForRecursiveFactoryRedirect()]).
-          break;
-        }
-      }
-      constructor = redirectedConstructor;
-    }
-    return constructor;
-  }
-
-  /**
-   * Generate an error indicating that the given [constant] is not a valid
-   * compile-time constant because it references at least one of the constants
-   * in the given [cycle], each of which directly or indirectly references the
-   * constant.
-   */
-  void generateCycleError(Iterable<ConstantEvaluationTarget> cycle,
-      ConstantEvaluationTarget constant) {
-    if (constant is VariableElement) {
-      RecordingErrorListener errorListener = new RecordingErrorListener();
-      ErrorReporter errorReporter =
-          new ErrorReporter(errorListener, constant.source);
-      // TODO(paulberry): It would be really nice if we could extract enough
-      // information from the 'cycle' argument to provide the user with a
-      // description of the cycle.
-      errorReporter.reportErrorForElement(
-          CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT, constant, []);
-      (constant as VariableElementImpl).evaluationResult =
-          new EvaluationResultImpl(null, errorListener.errors);
-    } else if (constant is ConstructorElement) {
-      // We don't report cycle errors on constructor declarations since there
-      // is nowhere to put the error information.
-    } else {
-      // Should not happen.  Formal parameter defaults and annotations should
-      // never appear as part of a cycle because they can't be referred to.
-      assert(false);
-      AnalysisEngine.instance.logger.logError(
-          "Constant value computer trying to report a cycle error for a node of type ${constant.runtimeType}");
-    }
-  }
-
-  /**
-   * If [constructor] redirects to another const constructor, return the
-   * const constructor it redirects to.  Otherwise return `null`.
-   */
-  ConstructorElement getConstRedirectedConstructor(
-      ConstructorElement constructor) {
-    if (!constructor.isFactory) {
-      return null;
-    }
-    if (identical(constructor.enclosingElement.type, typeProvider.symbolType)) {
-      // The dart:core.Symbol has a const factory constructor that redirects
-      // to dart:_internal.Symbol.  That in turn redirects to an external
-      // const constructor, which we won't be able to evaluate.
-      // So stop following the chain of redirections at dart:core.Symbol, and
-      // let [evaluateInstanceCreationExpression] handle it specially.
-      return null;
-    }
-    ConstructorElement redirectedConstructor =
-        constructor.redirectedConstructor;
-    if (redirectedConstructor == null) {
-      // This can happen if constructor is an external factory constructor.
-      return null;
-    }
-    if (!redirectedConstructor.isConst) {
-      // Delegating to a non-const constructor--this is not allowed (and
-      // is checked elsewhere--see
-      // [ErrorVerifier.checkForRedirectToNonConstConstructor()]).
-      return null;
-    }
-    return redirectedConstructor;
-  }
-
-  /**
-   * Check if the object [obj] matches the type [type] according to runtime type
-   * checking rules.
-   */
-  bool runtimeTypeMatch(DartObjectImpl obj, DartType type) {
-    if (obj.isNull) {
-      return true;
-    }
-    if (type.isUndefined) {
-      return false;
-    }
-    return obj.type.isSubtypeOf(type);
-  }
-
-  /**
-   * Determine whether the given string is a valid name for a public symbol
-   * (i.e. whether it is allowed for a call to the Symbol constructor).
-   */
-  static bool isValidPublicSymbol(String name) =>
-      name.isEmpty ||
-      name == "void" ||
-      new JavaPatternMatcher(_PUBLIC_SYMBOL_PATTERN, name).matches();
-}
-
-/**
- * Interface used by unit tests to verify correct dependency analysis during
- * constant evaluation.
- */
-abstract class ConstantEvaluationValidator {
-  /**
-   * This method is called just before computing the constant value associated
-   * with [constant]. Unit tests will override this method to introduce
-   * additional error checking.
-   */
-  void beforeComputeValue(ConstantEvaluationTarget constant);
-
-  /**
-   * This method is called just before getting the constant initializers
-   * associated with the [constructor]. Unit tests will override this method to
-   * introduce additional error checking.
-   */
-  void beforeGetConstantInitializers(ConstructorElement constructor);
-
-  /**
-   * This method is called just before retrieving an evaluation result from an
-   * element. Unit tests will override it to introduce additional error
-   * checking.
-   */
-  void beforeGetEvaluationResult(ConstantEvaluationTarget constant);
-
-  /**
-   * This method is called just before getting the constant value of a field
-   * with an initializer.  Unit tests will override this method to introduce
-   * additional error checking.
-   */
-  void beforeGetFieldEvaluationResult(FieldElementImpl field);
-
-  /**
-   * This method is called just before getting a parameter's default value. Unit
-   * tests will override this method to introduce additional error checking.
-   */
-  void beforeGetParameterDefault(ParameterElement parameter);
-}
-
-/**
- * Implementation of [ConstantEvaluationValidator] used in production; does no
- * validation.
- */
-class ConstantEvaluationValidator_ForProduction
-    implements ConstantEvaluationValidator {
-  @override
-  void beforeComputeValue(ConstantEvaluationTarget constant) {}
-
-  @override
-  void beforeGetConstantInitializers(ConstructorElement constructor) {}
-
-  @override
-  void beforeGetEvaluationResult(ConstantEvaluationTarget constant) {}
-
-  @override
-  void beforeGetFieldEvaluationResult(FieldElementImpl field) {}
-
-  @override
-  void beforeGetParameterDefault(ParameterElement parameter) {}
-}
+export 'package:analyzer/context/declared_variables.dart';
+export 'package:analyzer/dart/constant/value.dart';
+export 'package:analyzer/src/dart/constant/evaluation.dart';
+export 'package:analyzer/src/dart/constant/utilities.dart';
+export 'package:analyzer/src/dart/constant/value.dart';
 
 /// Instances of the class [ConstantEvaluator] evaluate constant expressions to
 /// produce their compile-time value.
@@ -1143,6 +98,7 @@
 /// In addition, this class defines several values that can be returned to
 /// indicate various conditions encountered during evaluation. These are
 /// documented with the static fields that define those values.
+@deprecated
 class ConstantEvaluator {
   /**
    * The source containing the expression(s) that will be evaluated.
@@ -1180,4243 +136,3 @@
     return EvaluationResult.forErrors(errorListener.errors);
   }
 }
-
-/**
- * A visitor used to traverse the AST structures of all of the compilation units
- * being resolved and build the full set of dependencies for all constant
- * expressions.
- */
-class ConstantExpressionsDependenciesFinder extends RecursiveAstVisitor {
-  /**
-   * The constants whose values need to be computed.
-   */
-  HashSet<ConstantEvaluationTarget> dependencies =
-      new HashSet<ConstantEvaluationTarget>();
-
-  @override
-  void visitInstanceCreationExpression(InstanceCreationExpression node) {
-    if (node.isConst) {
-      _find(node);
-    } else {
-      super.visitInstanceCreationExpression(node);
-    }
-  }
-
-  @override
-  void visitListLiteral(ListLiteral node) {
-    if (node.constKeyword != null) {
-      _find(node);
-    } else {
-      super.visitListLiteral(node);
-    }
-  }
-
-  @override
-  void visitMapLiteral(MapLiteral node) {
-    if (node.constKeyword != null) {
-      _find(node);
-    } else {
-      super.visitMapLiteral(node);
-    }
-  }
-
-  @override
-  void visitSwitchCase(SwitchCase node) {
-    _find(node.expression);
-    node.statements.accept(this);
-  }
-
-  void _find(Expression node) {
-    if (node != null) {
-      ReferenceFinder referenceFinder = new ReferenceFinder(dependencies.add);
-      node.accept(referenceFinder);
-    }
-  }
-}
-
-/**
- * A visitor used to traverse the AST structures of all of the compilation units
- * being resolved and build tables of the constant variables, constant
- * constructors, constant constructor invocations, and annotations found in
- * those compilation units.
- */
-class ConstantFinder extends RecursiveAstVisitor<Object> {
-  final AnalysisContext context;
-  final Source source;
-  final Source librarySource;
-
-  /**
-   * The elements and AST nodes whose constant values need to be computed.
-   */
-  List<ConstantEvaluationTarget> constantsToCompute =
-      <ConstantEvaluationTarget>[];
-
-  /**
-   * True if instance variables marked as "final" should be treated as "const".
-   */
-  bool treatFinalInstanceVarAsConst = false;
-
-  ConstantFinder(this.context, this.source, this.librarySource);
-
-  @override
-  Object visitAnnotation(Annotation node) {
-    super.visitAnnotation(node);
-    ElementAnnotation elementAnnotation = node.elementAnnotation;
-    if (elementAnnotation == null) {
-      // Analyzer ignores annotations on "part of" directives.
-      assert(node.parent is PartOfDirective);
-    } else {
-      constantsToCompute.add(elementAnnotation);
-    }
-    return null;
-  }
-
-  @override
-  Object visitClassDeclaration(ClassDeclaration node) {
-    bool prevTreatFinalInstanceVarAsConst = treatFinalInstanceVarAsConst;
-    if (node.element.constructors.any((ConstructorElement e) => e.isConst)) {
-      // Instance vars marked "final" need to be included in the dependency
-      // graph, since constant constructors implicitly use the values in their
-      // initializers.
-      treatFinalInstanceVarAsConst = true;
-    }
-    try {
-      return super.visitClassDeclaration(node);
-    } finally {
-      treatFinalInstanceVarAsConst = prevTreatFinalInstanceVarAsConst;
-    }
-  }
-
-  @override
-  Object visitConstructorDeclaration(ConstructorDeclaration node) {
-    super.visitConstructorDeclaration(node);
-    if (node.constKeyword != null) {
-      ConstructorElement element = node.element;
-      if (element != null) {
-        constantsToCompute.add(element);
-        constantsToCompute.addAll(element.parameters);
-      }
-    }
-    return null;
-  }
-
-  @override
-  Object visitDefaultFormalParameter(DefaultFormalParameter node) {
-    super.visitDefaultFormalParameter(node);
-    Expression defaultValue = node.defaultValue;
-    if (defaultValue != null && node.element != null) {
-      constantsToCompute.add(node.element);
-    }
-    return null;
-  }
-
-  @override
-  Object visitVariableDeclaration(VariableDeclaration node) {
-    super.visitVariableDeclaration(node);
-    Expression initializer = node.initializer;
-    VariableElement element = node.element;
-    if (initializer != null &&
-        (node.isConst ||
-            treatFinalInstanceVarAsConst &&
-                element is FieldElement &&
-                node.isFinal &&
-                !element.isStatic)) {
-      if (element != null) {
-        constantsToCompute.add(element);
-      }
-    }
-    return null;
-  }
-}
-
-/**
- * An object used to compute the values of constant variables and constant
- * constructor invocations in one or more compilation units. The expected usage
- * pattern is for the compilation units to be added to this computer using the
- * method [add] and then for the method [computeValues] to be invoked exactly
- * once. Any use of an instance after invoking the method [computeValues] will
- * result in unpredictable behavior.
- */
-class ConstantValueComputer {
-  /**
-   * Source of RegExp matching declarable operator names.
-   * From sdk/lib/internal/symbol.dart.
-   */
-  static String _OPERATOR_RE =
-      "(?:[\\-+*/%&|^]|\\[\\]=?|==|~/?|<[<=]?|>[>=]?|unary-)";
-
-  /**
-   * Source of RegExp matching Dart reserved words.
-   * From sdk/lib/internal/symbol.dart.
-   */
-  static String _RESERVED_WORD_RE =
-      "(?:assert|break|c(?:a(?:se|tch)|lass|on(?:st|tinue))|d(?:efault|o)|e(?:lse|num|xtends)|f(?:alse|inal(?:ly)?|or)|i[fns]|n(?:ew|ull)|ret(?:hrow|urn)|s(?:uper|witch)|t(?:h(?:is|row)|r(?:ue|y))|v(?:ar|oid)|w(?:hile|ith))";
-
-  /**
-   * A graph in which the nodes are the constants, and the edges are from each
-   * constant to the other constants that are referenced by it.
-   */
-  DirectedGraph<ConstantEvaluationTarget> referenceGraph =
-      new DirectedGraph<ConstantEvaluationTarget>();
-
-  /**
-   * The elements whose constant values need to be computed.  Any elements
-   * which appear in [referenceGraph] but not in this set either belong to a
-   * different library cycle (and hence don't need to be recomputed) or were
-   * computed during a previous stage of resolution stage (e.g. constants
-   * associated with enums).
-   */
-  HashSet<ConstantEvaluationTarget> _constantsToCompute =
-      new HashSet<ConstantEvaluationTarget>();
-
-  /**
-   * The evaluation engine that does the work of evaluating instance creation
-   * expressions.
-   */
-  final ConstantEvaluationEngine evaluationEngine;
-
-  final AnalysisContext _context;
-
-  /**
-   * Initialize a newly created constant value computer. The [typeProvider] is
-   * the type provider used to access known types. The [declaredVariables] is
-   * the set of variables declared on the command line using '-D'.
-   */
-  ConstantValueComputer(this._context, TypeProvider typeProvider,
-      DeclaredVariables declaredVariables,
-      [ConstantEvaluationValidator validator, TypeSystem typeSystem])
-      : evaluationEngine = new ConstantEvaluationEngine(
-            typeProvider, declaredVariables,
-            validator: validator, typeSystem: typeSystem);
-
-  /**
-   * Add the constants in the given compilation [unit] to the list of constants
-   * whose value needs to be computed.
-   */
-  void add(CompilationUnit unit, Source source, Source librarySource) {
-    ConstantFinder constantFinder =
-        new ConstantFinder(_context, source, librarySource);
-    unit.accept(constantFinder);
-    _constantsToCompute.addAll(constantFinder.constantsToCompute);
-  }
-
-  /**
-   * Compute values for all of the constants in the compilation units that were
-   * added.
-   */
-  void computeValues() {
-    for (ConstantEvaluationTarget constant in _constantsToCompute) {
-      referenceGraph.addNode(constant);
-      evaluationEngine.computeDependencies(constant,
-          (ConstantEvaluationTarget dependency) {
-        referenceGraph.addEdge(constant, dependency);
-      });
-    }
-    List<List<ConstantEvaluationTarget>> topologicalSort =
-        referenceGraph.computeTopologicalSort();
-    for (List<ConstantEvaluationTarget> constantsInCycle in topologicalSort) {
-      if (constantsInCycle.length == 1) {
-        ConstantEvaluationTarget constant = constantsInCycle[0];
-        if (!referenceGraph.getTails(constant).contains(constant)) {
-          _computeValueFor(constant);
-          continue;
-        }
-      }
-      for (ConstantEvaluationTarget constant in constantsInCycle) {
-        evaluationEngine.generateCycleError(constantsInCycle, constant);
-      }
-    }
-  }
-
-  /**
-   * Compute a value for the given [constant].
-   */
-  void _computeValueFor(ConstantEvaluationTarget constant) {
-    if (!_constantsToCompute.contains(constant)) {
-      // Element is in the dependency graph but should have been computed by
-      // a previous stage of analysis.
-      // TODO(paulberry): once we have moved over to the new task model, this
-      // should only occur for constants associated with enum members.  Once
-      // that happens we should add an assertion to verify that it doesn't
-      // occur in any other cases.
-      return;
-    }
-    evaluationEngine.computeConstantValue(constant);
-  }
-}
-
-/**
- * A visitor used to evaluate constant expressions to produce their compile-time
- * value. According to the Dart Language Specification: <blockquote> A constant
- * expression is one of the following:
- *
- * * A literal number.
- * * A literal boolean.
- * * A literal string where any interpolated expression is a compile-time
- *   constant that evaluates to a numeric, string or boolean value or to
- *   <b>null</b>.
- * * A literal symbol.
- * * <b>null</b>.
- * * A qualified reference to a static constant variable.
- * * An identifier expression that denotes a constant variable, class or type
- *   alias.
- * * A constant constructor invocation.
- * * A constant list literal.
- * * A constant map literal.
- * * A simple or qualified identifier denoting a top-level function or a static
- *   method.
- * * A parenthesized expression <i>(e)</i> where <i>e</i> is a constant
- *   expression.
- * * An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i>
- *   where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
- *   expressions and <i>identical()</i> is statically bound to the predefined
- *   dart function <i>identical()</i> discussed above.
- * * An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i> or
- *   <i>e<sub>1</sub> != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and
- *   <i>e<sub>2</sub></i> are constant expressions that evaluate to a numeric,
- *   string or boolean value.
- * * An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> &amp;&amp;
- *   e<sub>2</sub></i> or <i>e<sub>1</sub> || e<sub>2</sub></i>, where <i>e</i>,
- *   <i>e1</sub></i> and <i>e2</sub></i> are constant expressions that evaluate
- *   to a boolean value.
- * * An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^
- *   e<sub>2</sub></i>, <i>e<sub>1</sub> &amp; e<sub>2</sub></i>,
- *   <i>e<sub>1</sub> | e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;&gt;
- *   e<sub>2</sub></i> or <i>e<sub>1</sub> &lt;&lt; e<sub>2</sub></i>, where
- *   <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
- *   expressions that evaluate to an integer value or to <b>null</b>.
- * * An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> +
- *   e<sub>2</sub></i>, <i>e<sub>1</sub> - e<sub>2</sub></i>, <i>e<sub>1</sub> *
- *   e<sub>2</sub></i>, <i>e<sub>1</sub> / e<sub>2</sub></i>, <i>e<sub>1</sub>
- *   ~/ e<sub>2</sub></i>, <i>e<sub>1</sub> &gt; e<sub>2</sub></i>,
- *   <i>e<sub>1</sub> &lt; e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;=
- *   e<sub>2</sub></i>, <i>e<sub>1</sub> &lt;= e<sub>2</sub></i> or
- *   <i>e<sub>1</sub> % e<sub>2</sub></i>, where <i>e</i>, <i>e<sub>1</sub></i>
- *   and <i>e<sub>2</sub></i> are constant expressions that evaluate to a
- *   numeric value or to <b>null</b>.
- * * An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> :
- *   e<sub>3</sub></i> where <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and
- *   <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i>
- *   evaluates to a boolean value.
- * </blockquote>
- */
-class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
-  /**
-   * The type provider used to access the known types.
-   */
-  final ConstantEvaluationEngine evaluationEngine;
-
-  final HashMap<String, DartObjectImpl> _lexicalEnvironment;
-
-  /**
-   * Error reporter that we use to report errors accumulated while computing the
-   * constant.
-   */
-  final ErrorReporter _errorReporter;
-
-  /**
-   * Helper class used to compute constant values.
-   */
-  DartObjectComputer _dartObjectComputer;
-
-  /**
-   * Initialize a newly created constant visitor. The [evaluationEngine] is
-   * used to evaluate instance creation expressions. The [lexicalEnvironment]
-   * is a map containing values which should override identifiers, or `null` if
-   * no overriding is necessary. The [_errorReporter] is used to report errors
-   * found during evaluation.  The [validator] is used by unit tests to verify
-   * correct dependency analysis.
-   */
-  ConstantVisitor(this.evaluationEngine, this._errorReporter,
-      {HashMap<String, DartObjectImpl> lexicalEnvironment})
-      : _lexicalEnvironment = lexicalEnvironment {
-    this._dartObjectComputer =
-        new DartObjectComputer(_errorReporter, evaluationEngine.typeProvider);
-  }
-
-  /**
-   * Convenience getter to gain access to the [evalationEngine]'s type
-   * provider.
-   */
-  TypeProvider get _typeProvider => evaluationEngine.typeProvider;
-
-  /**
-   * Convenience getter to gain access to the [evaluationEngine]'s type system.
-   */
-  TypeSystem get _typeSystem => evaluationEngine.typeSystem;
-
-  @override
-  DartObjectImpl visitAdjacentStrings(AdjacentStrings node) {
-    DartObjectImpl result = null;
-    for (StringLiteral string in node.strings) {
-      if (result == null) {
-        result = string.accept(this);
-      } else {
-        result =
-            _dartObjectComputer.concatenate(node, result, string.accept(this));
-      }
-    }
-    return result;
-  }
-
-  @override
-  DartObjectImpl visitBinaryExpression(BinaryExpression node) {
-    DartObjectImpl leftResult = node.leftOperand.accept(this);
-    DartObjectImpl rightResult = node.rightOperand.accept(this);
-    TokenType operatorType = node.operator.type;
-    // 'null' is almost never good operand
-    if (operatorType != TokenType.BANG_EQ &&
-        operatorType != TokenType.EQ_EQ &&
-        operatorType != TokenType.QUESTION_QUESTION) {
-      if (leftResult != null && leftResult.isNull ||
-          rightResult != null && rightResult.isNull) {
-        _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-        return null;
-      }
-    }
-    // evaluate operator
-    while (true) {
-      if (operatorType == TokenType.AMPERSAND) {
-        return _dartObjectComputer.bitAnd(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.AMPERSAND_AMPERSAND) {
-        return _dartObjectComputer.logicalAnd(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.BANG_EQ) {
-        return _dartObjectComputer.notEqual(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.BAR) {
-        return _dartObjectComputer.bitOr(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.BAR_BAR) {
-        return _dartObjectComputer.logicalOr(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.CARET) {
-        return _dartObjectComputer.bitXor(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.EQ_EQ) {
-        return _dartObjectComputer.equalEqual(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.GT) {
-        return _dartObjectComputer.greaterThan(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.GT_EQ) {
-        return _dartObjectComputer.greaterThanOrEqual(
-            node, leftResult, rightResult);
-      } else if (operatorType == TokenType.GT_GT) {
-        return _dartObjectComputer.shiftRight(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.LT) {
-        return _dartObjectComputer.lessThan(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.LT_EQ) {
-        return _dartObjectComputer.lessThanOrEqual(
-            node, leftResult, rightResult);
-      } else if (operatorType == TokenType.LT_LT) {
-        return _dartObjectComputer.shiftLeft(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.MINUS) {
-        return _dartObjectComputer.minus(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.PERCENT) {
-        return _dartObjectComputer.remainder(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.PLUS) {
-        return _dartObjectComputer.add(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.STAR) {
-        return _dartObjectComputer.times(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.SLASH) {
-        return _dartObjectComputer.divide(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.TILDE_SLASH) {
-        return _dartObjectComputer.integerDivide(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.QUESTION_QUESTION) {
-        return _dartObjectComputer.questionQuestion(
-            node, leftResult, rightResult);
-      } else {
-        // TODO(brianwilkerson) Figure out which error to report.
-        _error(node, null);
-        return null;
-      }
-      break;
-    }
-  }
-
-  @override
-  DartObjectImpl visitBooleanLiteral(BooleanLiteral node) =>
-      new DartObjectImpl(_typeProvider.boolType, BoolState.from(node.value));
-
-  @override
-  DartObjectImpl visitConditionalExpression(ConditionalExpression node) {
-    Expression condition = node.condition;
-    DartObjectImpl conditionResult = condition.accept(this);
-    DartObjectImpl thenResult = node.thenExpression.accept(this);
-    DartObjectImpl elseResult = node.elseExpression.accept(this);
-    if (conditionResult == null) {
-      return conditionResult;
-    } else if (!conditionResult.isBool) {
-      _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL, condition);
-      return null;
-    } else if (thenResult == null) {
-      return thenResult;
-    } else if (elseResult == null) {
-      return elseResult;
-    }
-    conditionResult =
-        _dartObjectComputer.applyBooleanConversion(condition, conditionResult);
-    if (conditionResult == null) {
-      return conditionResult;
-    }
-    if (conditionResult.toBoolValue() == true) {
-      return thenResult;
-    } else if (conditionResult.toBoolValue() == false) {
-      return elseResult;
-    }
-    ParameterizedType thenType = thenResult.type;
-    ParameterizedType elseType = elseResult.type;
-    return new DartObjectImpl.validWithUnknownValue(
-        _typeSystem.getLeastUpperBound(_typeProvider, thenType, elseType)
-        as InterfaceType);
-  }
-
-  @override
-  DartObjectImpl visitDoubleLiteral(DoubleLiteral node) =>
-      new DartObjectImpl(_typeProvider.doubleType, new DoubleState(node.value));
-
-  @override
-  DartObjectImpl visitInstanceCreationExpression(
-      InstanceCreationExpression node) {
-    if (!node.isConst) {
-      // TODO(brianwilkerson) Figure out which error to report.
-      _error(node, null);
-      return null;
-    }
-    ConstructorElement constructor = node.staticElement;
-    if (constructor == null) {
-      // Couldn't resolve the constructor so we can't compute a value.  No
-      // problem - the error has already been reported.
-      return null;
-    }
-    return evaluationEngine.evaluateConstructorCall(
-        node, node.argumentList.arguments, constructor, this, _errorReporter);
-  }
-
-  @override
-  DartObjectImpl visitIntegerLiteral(IntegerLiteral node) =>
-      new DartObjectImpl(_typeProvider.intType, new IntState(node.value));
-
-  @override
-  DartObjectImpl visitInterpolationExpression(InterpolationExpression node) {
-    DartObjectImpl result = node.expression.accept(this);
-    if (result != null && !result.isBoolNumStringOrNull) {
-      _error(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
-      return null;
-    }
-    return _dartObjectComputer.performToString(node, result);
-  }
-
-  @override
-  DartObjectImpl visitInterpolationString(InterpolationString node) =>
-      new DartObjectImpl(_typeProvider.stringType, new StringState(node.value));
-
-  @override
-  DartObjectImpl visitListLiteral(ListLiteral node) {
-    if (node.constKeyword == null) {
-      _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL, node);
-      return null;
-    }
-    bool errorOccurred = false;
-    List<DartObjectImpl> elements = new List<DartObjectImpl>();
-    for (Expression element in node.elements) {
-      DartObjectImpl elementResult = element.accept(this);
-      if (elementResult == null) {
-        errorOccurred = true;
-      } else {
-        elements.add(elementResult);
-      }
-    }
-    if (errorOccurred) {
-      return null;
-    }
-    DartType elementType = _typeProvider.dynamicType;
-    if (node.typeArguments != null &&
-        node.typeArguments.arguments.length == 1) {
-      DartType type = node.typeArguments.arguments[0].type;
-      if (type != null) {
-        elementType = type;
-      }
-    }
-    InterfaceType listType = _typeProvider.listType.instantiate([elementType]);
-    return new DartObjectImpl(listType, new ListState(elements));
-  }
-
-  @override
-  DartObjectImpl visitMapLiteral(MapLiteral node) {
-    if (node.constKeyword == null) {
-      _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL, node);
-      return null;
-    }
-    bool errorOccurred = false;
-    LinkedHashMap<DartObjectImpl, DartObjectImpl> map =
-        new LinkedHashMap<DartObjectImpl, DartObjectImpl>();
-    for (MapLiteralEntry entry in node.entries) {
-      DartObjectImpl keyResult = entry.key.accept(this);
-      DartObjectImpl valueResult = entry.value.accept(this);
-      if (keyResult == null || valueResult == null) {
-        errorOccurred = true;
-      } else {
-        map[keyResult] = valueResult;
-      }
-    }
-    if (errorOccurred) {
-      return null;
-    }
-    DartType keyType = _typeProvider.dynamicType;
-    DartType valueType = _typeProvider.dynamicType;
-    if (node.typeArguments != null &&
-        node.typeArguments.arguments.length == 2) {
-      DartType keyTypeCandidate = node.typeArguments.arguments[0].type;
-      if (keyTypeCandidate != null) {
-        keyType = keyTypeCandidate;
-      }
-      DartType valueTypeCandidate = node.typeArguments.arguments[1].type;
-      if (valueTypeCandidate != null) {
-        valueType = valueTypeCandidate;
-      }
-    }
-    InterfaceType mapType =
-        _typeProvider.mapType.instantiate([keyType, valueType]);
-    return new DartObjectImpl(mapType, new MapState(map));
-  }
-
-  @override
-  DartObjectImpl visitMethodInvocation(MethodInvocation node) {
-    Element element = node.methodName.staticElement;
-    if (element is FunctionElement) {
-      FunctionElement function = element;
-      if (function.name == "identical") {
-        NodeList<Expression> arguments = node.argumentList.arguments;
-        if (arguments.length == 2) {
-          Element enclosingElement = function.enclosingElement;
-          if (enclosingElement is CompilationUnitElement) {
-            LibraryElement library = enclosingElement.library;
-            if (library.isDartCore) {
-              DartObjectImpl leftArgument = arguments[0].accept(this);
-              DartObjectImpl rightArgument = arguments[1].accept(this);
-              return _dartObjectComputer.isIdentical(
-                  node, leftArgument, rightArgument);
-            }
-          }
-        }
-      }
-    }
-    // TODO(brianwilkerson) Figure out which error to report.
-    _error(node, null);
-    return null;
-  }
-
-  @override
-  DartObjectImpl visitNamedExpression(NamedExpression node) =>
-      node.expression.accept(this);
-
-  @override
-  DartObjectImpl visitNode(AstNode node) {
-    // TODO(brianwilkerson) Figure out which error to report.
-    _error(node, null);
-    return null;
-  }
-
-  @override
-  DartObjectImpl visitNullLiteral(NullLiteral node) => _typeProvider.nullObject;
-
-  @override
-  DartObjectImpl visitParenthesizedExpression(ParenthesizedExpression node) =>
-      node.expression.accept(this);
-
-  @override
-  DartObjectImpl visitPrefixedIdentifier(PrefixedIdentifier node) {
-    SimpleIdentifier prefixNode = node.prefix;
-    Element prefixElement = prefixNode.staticElement;
-    // String.length
-    if (prefixElement is! PrefixElement && prefixElement is! ClassElement) {
-      DartObjectImpl prefixResult = node.prefix.accept(this);
-      if (_isStringLength(prefixResult, node.identifier)) {
-        return prefixResult.stringLength(_typeProvider);
-      }
-    }
-    // importPrefix.CONST
-    if (prefixElement is! PrefixElement) {
-      DartObjectImpl prefixResult = prefixNode.accept(this);
-      if (prefixResult == null) {
-        // The error has already been reported.
-        return null;
-      }
-    }
-    // validate prefixed identifier
-    return _getConstantValue(node, node.staticElement);
-  }
-
-  @override
-  DartObjectImpl visitPrefixExpression(PrefixExpression node) {
-    DartObjectImpl operand = node.operand.accept(this);
-    if (operand != null && operand.isNull) {
-      _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-      return null;
-    }
-    while (true) {
-      if (node.operator.type == TokenType.BANG) {
-        return _dartObjectComputer.logicalNot(node, operand);
-      } else if (node.operator.type == TokenType.TILDE) {
-        return _dartObjectComputer.bitNot(node, operand);
-      } else if (node.operator.type == TokenType.MINUS) {
-        return _dartObjectComputer.negated(node, operand);
-      } else {
-        // TODO(brianwilkerson) Figure out which error to report.
-        _error(node, null);
-        return null;
-      }
-      break;
-    }
-  }
-
-  @override
-  DartObjectImpl visitPropertyAccess(PropertyAccess node) {
-    if (node.target != null) {
-      DartObjectImpl prefixResult = node.target.accept(this);
-      if (_isStringLength(prefixResult, node.propertyName)) {
-        return prefixResult.stringLength(_typeProvider);
-      }
-    }
-    return _getConstantValue(node, node.propertyName.staticElement);
-  }
-
-  @override
-  DartObjectImpl visitSimpleIdentifier(SimpleIdentifier node) {
-    if (_lexicalEnvironment != null &&
-        _lexicalEnvironment.containsKey(node.name)) {
-      return _lexicalEnvironment[node.name];
-    }
-    return _getConstantValue(node, node.staticElement);
-  }
-
-  @override
-  DartObjectImpl visitSimpleStringLiteral(SimpleStringLiteral node) =>
-      new DartObjectImpl(_typeProvider.stringType, new StringState(node.value));
-
-  @override
-  DartObjectImpl visitStringInterpolation(StringInterpolation node) {
-    DartObjectImpl result = null;
-    bool first = true;
-    for (InterpolationElement element in node.elements) {
-      if (first) {
-        result = element.accept(this);
-        first = false;
-      } else {
-        result =
-            _dartObjectComputer.concatenate(node, result, element.accept(this));
-      }
-    }
-    return result;
-  }
-
-  @override
-  DartObjectImpl visitSymbolLiteral(SymbolLiteral node) {
-    StringBuffer buffer = new StringBuffer();
-    List<Token> components = node.components;
-    for (int i = 0; i < components.length; i++) {
-      if (i > 0) {
-        buffer.writeCharCode(0x2E);
-      }
-      buffer.write(components[i].lexeme);
-    }
-    return new DartObjectImpl(
-        _typeProvider.symbolType, new SymbolState(buffer.toString()));
-  }
-
-  /**
-   * Create an error associated with the given [node]. The error will have the
-   * given error [code].
-   */
-  void _error(AstNode node, ErrorCode code) {
-    _errorReporter.reportErrorForNode(
-        code == null ? CompileTimeErrorCode.INVALID_CONSTANT : code, node);
-  }
-
-  /**
-   * Return the constant value of the static constant represented by the given
-   * [element]. The [node] is the node to be used if an error needs to be
-   * reported.
-   */
-  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) {
-        return value.value;
-      }
-    } else if (element is ExecutableElement) {
-      ExecutableElement function = element;
-      if (function.isStatic) {
-        ParameterizedType functionType = function.type;
-        if (functionType == null) {
-          functionType = _typeProvider.functionType;
-        }
-        return new DartObjectImpl(functionType, new FunctionState(function));
-      }
-    } else if (element is ClassElement ||
-        element is FunctionTypeAliasElement ||
-        element is DynamicElementImpl) {
-      return new DartObjectImpl(_typeProvider.typeType, new TypeState(element));
-    }
-    // TODO(brianwilkerson) Figure out which error to report.
-    _error(node, null);
-    return null;
-  }
-
-  /**
-   * Return `true` if the given [targetResult] represents a string and the
-   * [identifier] is "length".
-   */
-  bool _isStringLength(
-      DartObjectImpl targetResult, SimpleIdentifier identifier) {
-    if (targetResult == null || targetResult.type != _typeProvider.stringType) {
-      return false;
-    }
-    return identifier.name == 'length';
-  }
-
-  /**
-   * Return the value of the given [expression], or a representation of 'null'
-   * if the expression cannot be evaluated.
-   */
-  DartObjectImpl _valueOf(Expression expression) {
-    DartObjectImpl expressionValue = expression.accept(this);
-    if (expressionValue != null) {
-      return expressionValue;
-    }
-    return _typeProvider.nullObject;
-  }
-}
-
-/**
- * A representation of the value of a compile-time constant expression.
- *
- * Note that, unlike the mirrors system, the object being represented does *not*
- * exist. This interface allows static analysis tools to determine something
- * about the state of the object that would exist if the code that creates the
- * object were executed, but none of the code being analyzed is actually
- * executed.
- */
-abstract class DartObject {
-  /**
-   * Return `true` if the value of the object being represented is known.
-   *
-   * This method will return `false` if
-   * * the value being represented is the value of a declared variable (a
-   *   variable whose value is provided at run-time using a `-D` command-line
-   *   option), or
-   * * the value is a function.
-   *
-   * The result of this method does not imply anything about the state of
-   * object representations returned by the method [getField], those that are
-   * elements of the list returned by [toListValue], or the keys or values in
-   * the map returned by [toMapValue]. For example, a representation of a list
-   * can return `true` even if one or more of the elements of that list would
-   * return `false`.
-   */
-  bool get hasKnownValue;
-
-  /**
-   * Return `true` if the object being represented represents the value 'null'.
-   */
-  bool get isNull;
-
-  /**
-   * Return a representation of the type of the object being represented.
-   *
-   * For values resulting from the invocation of a 'const' constructor, this
-   * will be a representation of the run-time type of the object.
-   *
-   * For values resulting from a literal expression, this will be a
-   * representation of the static type of the value -- `int` for integer
-   * literals, `List` for list literals, etc. -- even when the static type is an
-   * abstract type (such as `List`) and hence will never be the run-time type of
-   * the represented object.
-   *
-   * For values resulting from any other kind of expression, this will be a
-   * representation of the result of evaluating the expression.
-   *
-   * Return `null` if the expression cannot be evaluated, either because it is
-   * not a valid constant expression or because one or more of the values used
-   * in the expression does not have a known value.
-   *
-   * This method can return a representation of the type, even if this object
-   * would return `false` from [hasKnownValue].
-   */
-  ParameterizedType get type;
-
-  /**
-   * Return a representation of the value of the field with the given [name].
-   *
-   * Return `null` if either the object being represented does not have a field
-   * with the given name or if the implementation of the class of the object is
-   * invalid, making it impossible to determine that value of the field.
-   *
-   * Note that, unlike the mirrors API, this method does *not* invoke a getter;
-   * it simply returns a representation of the known state of a field.
-   */
-  DartObject getField(String name);
-
-  /**
-   * Return a boolean corresponding to the value of the object being
-   * represented, or `null` if
-   * * this object is not of type 'bool',
-   * * the value of the object being represented is not known, or
-   * * the value of the object being represented is `null`.
-   */
-  bool toBoolValue();
-
-  /**
-   * Return a double corresponding to the value of the object being represented,
-   * or `null`
-   * if
-   * * this object is not of type 'double',
-   * * the value of the object being represented is not known, or
-   * * the value of the object being represented is `null`.
-   */
-  double toDoubleValue();
-
-  /**
-   * Return an integer corresponding to the value of the object being
-   * represented, or `null` if
-   * * this object is not of type 'int',
-   * * the value of the object being represented is not known, or
-   * * the value of the object being represented is `null`.
-   */
-  int toIntValue();
-
-  /**
-   * Return a list corresponding to the value of the object being represented,
-   * or `null` if
-   * * this object is not of type 'List', or
-   * * the value of the object being represented is `null`.
-   */
-  List<DartObject> toListValue();
-
-  /**
-   * Return a map corresponding to the value of the object being represented, or
-   * `null` if
-   * * this object is not of type 'Map', or
-   * * the value of the object being represented is `null`.
-   */
-  Map<DartObject, DartObject> toMapValue();
-
-  /**
-   * Return a string corresponding to the value of the object being represented,
-   * or `null` if
-   * * this object is not of type 'String',
-   * * the value of the object being represented is not known, or
-   * * the value of the object being represented is `null`.
-   */
-  String toStringValue();
-
-  /**
-   * Return a string corresponding to the value of the object being represented,
-   * or `null` if
-   * * this object is not of type 'Symbol', or
-   * * the value of the object being represented is `null`.
-   * (We return the string
-   */
-  String toSymbolValue();
-
-  /**
-   * Return the representation of the type corresponding to the value of the
-   * object being represented, or `null` if
-   * * this object is not of type 'Type', or
-   * * the value of the object being represented is `null`.
-   */
-  DartType toTypeValue();
-}
-
-/**
- * A utility class that contains methods for manipulating instances of a Dart
- * class and for collecting errors during evaluation.
- */
-class DartObjectComputer {
-  /**
-   * The error reporter that we are using to collect errors.
-   */
-  final ErrorReporter _errorReporter;
-
-  /**
-   * The type provider used to create objects of the appropriate types, and to
-   * identify when an object is of a built-in type.
-   */
-  final TypeProvider _typeProvider;
-
-  DartObjectComputer(this._errorReporter, this._typeProvider);
-
-  DartObjectImpl add(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.add(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-        return null;
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Return the result of applying boolean conversion to the [evaluationResult].
-   * The [node] is the node against which errors should be reported.
-   */
-  DartObjectImpl applyBooleanConversion(
-      AstNode node, DartObjectImpl evaluationResult) {
-    if (evaluationResult != null) {
-      try {
-        return evaluationResult.convertToBool(_typeProvider);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl bitAnd(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.bitAnd(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl bitNot(Expression node, DartObjectImpl evaluationResult) {
-    if (evaluationResult != null) {
-      try {
-        return evaluationResult.bitNot(_typeProvider);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl bitOr(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.bitOr(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl bitXor(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.bitXor(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl concatenate(Expression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.concatenate(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl divide(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.divide(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl equalEqual(Expression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.equalEqual(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl greaterThan(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.greaterThan(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl greaterThanOrEqual(BinaryExpression node,
-      DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.greaterThanOrEqual(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl integerDivide(BinaryExpression node,
-      DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.integerDivide(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl isIdentical(Expression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.isIdentical(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl lessThan(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.lessThan(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl lessThanOrEqual(BinaryExpression node,
-      DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.lessThanOrEqual(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl logicalAnd(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.logicalAnd(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl logicalNot(Expression node, DartObjectImpl evaluationResult) {
-    if (evaluationResult != null) {
-      try {
-        return evaluationResult.logicalNot(_typeProvider);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl logicalOr(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.logicalOr(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl minus(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.minus(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl negated(Expression node, DartObjectImpl evaluationResult) {
-    if (evaluationResult != null) {
-      try {
-        return evaluationResult.negated(_typeProvider);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl notEqual(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.notEqual(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl performToString(
-      AstNode node, DartObjectImpl evaluationResult) {
-    if (evaluationResult != null) {
-      try {
-        return evaluationResult.performToString(_typeProvider);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl questionQuestion(Expression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      if (leftOperand.isNull) {
-        return rightOperand;
-      }
-      return leftOperand;
-    }
-    return null;
-  }
-
-  DartObjectImpl remainder(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.remainder(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl shiftLeft(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.shiftLeft(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  DartObjectImpl shiftRight(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.shiftRight(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Return the result of invoking the 'length' getter on the
-   * [evaluationResult]. The [node] is the node against which errors should be
-   * reported.
-   */
-  EvaluationResultImpl stringLength(
-      Expression node, EvaluationResultImpl evaluationResult) {
-    if (evaluationResult.value != null) {
-      try {
-        return new EvaluationResultImpl(
-            evaluationResult.value.stringLength(_typeProvider));
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return new EvaluationResultImpl(null);
-  }
-
-  DartObjectImpl times(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (leftOperand != null && rightOperand != null) {
-      try {
-        return leftOperand.times(_typeProvider, rightOperand);
-      } on EvaluationException catch (exception) {
-        _errorReporter.reportErrorForNode(exception.errorCode, node);
-      }
-    }
-    return null;
-  }
-}
-
-/**
- * An instance of a Dart class.
- */
-class DartObjectImpl implements DartObject {
-  /**
-   * An empty list of objects.
-   */
-  static const List<DartObjectImpl> EMPTY_LIST = const <DartObjectImpl>[];
-
-  /**
-   * The run-time type of this object.
-   */
-  @override
-  final ParameterizedType type;
-
-  /**
-   * The state of the object.
-   */
-  final InstanceState _state;
-
-  /**
-   * Initialize a newly created object to have the given [type] and [_state].
-   */
-  DartObjectImpl(this.type, this._state);
-
-  /**
-   * Create an object to represent an unknown value.
-   */
-  factory DartObjectImpl.validWithUnknownValue(InterfaceType type) {
-    if (type.element.library.isDartCore) {
-      String typeName = type.name;
-      if (typeName == "bool") {
-        return new DartObjectImpl(type, BoolState.UNKNOWN_VALUE);
-      } else if (typeName == "double") {
-        return new DartObjectImpl(type, DoubleState.UNKNOWN_VALUE);
-      } else if (typeName == "int") {
-        return new DartObjectImpl(type, IntState.UNKNOWN_VALUE);
-      } else if (typeName == "String") {
-        return new DartObjectImpl(type, StringState.UNKNOWN_VALUE);
-      }
-    }
-    return new DartObjectImpl(type, GenericState.UNKNOWN_VALUE);
-  }
-
-  HashMap<String, DartObjectImpl> get fields => _state.fields;
-
-  @override
-  int get hashCode => JenkinsSmiHash.hash2(type.hashCode, _state.hashCode);
-
-  @override
-  bool get hasKnownValue => !_state.isUnknown;
-
-  /**
-   * Return `true` if this object represents an object whose type is 'bool'.
-   */
-  bool get isBool => _state.isBool;
-
-  /**
-   * Return `true` if this object represents an object whose type is either
-   * 'bool', 'num', 'String', or 'Null'.
-   */
-  bool get isBoolNumStringOrNull => _state.isBoolNumStringOrNull;
-
-  @override
-  bool get isNull => _state is NullState;
-
-  /**
-   * Return `true` if this object represents an unknown value.
-   */
-  bool get isUnknown => _state.isUnknown;
-
-  /**
-   * Return `true` if this object represents an instance of a user-defined
-   * class.
-   */
-  bool get isUserDefinedObject => _state is GenericState;
-
-  @override
-  bool operator ==(Object object) {
-    if (object is! DartObjectImpl) {
-      return false;
-    }
-    DartObjectImpl dartObject = object as DartObjectImpl;
-    return type == dartObject.type && _state == dartObject._state;
-  }
-
-  /**
-   * Return the result of invoking the '+' operator on this object with the
-   * given [rightOperand]. The [typeProvider] is the type provider used to find
-   * known types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl add(TypeProvider typeProvider, DartObjectImpl rightOperand) {
-    InstanceState result = _state.add(rightOperand._state);
-    if (result is IntState) {
-      return new DartObjectImpl(typeProvider.intType, result);
-    } else if (result is DoubleState) {
-      return new DartObjectImpl(typeProvider.doubleType, result);
-    } else if (result is NumState) {
-      return new DartObjectImpl(typeProvider.numType, result);
-    } else if (result is StringState) {
-      return new DartObjectImpl(typeProvider.stringType, result);
-    }
-    // We should never get here.
-    throw new IllegalStateException("add returned a ${result.runtimeType}");
-  }
-
-  /**
-   * Return the result of invoking the '&' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl bitAnd(
-          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
-      new DartObjectImpl(
-          typeProvider.intType, _state.bitAnd(rightOperand._state));
-
-  /**
-   * Return the result of invoking the '~' operator on this object. The
-   * [typeProvider] is the type provider used to find known types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl bitNot(TypeProvider typeProvider) =>
-      new DartObjectImpl(typeProvider.intType, _state.bitNot());
-
-  /**
-   * Return the result of invoking the '|' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl bitOr(
-          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
-      new DartObjectImpl(
-          typeProvider.intType, _state.bitOr(rightOperand._state));
-
-  /**
-   * Return the result of invoking the '^' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl bitXor(
-          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
-      new DartObjectImpl(
-          typeProvider.intType, _state.bitXor(rightOperand._state));
-
-  /**
-   * Return the result of invoking the ' ' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl concatenate(
-          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
-      new DartObjectImpl(
-          typeProvider.stringType, _state.concatenate(rightOperand._state));
-
-  /**
-   * Return the result of applying boolean conversion to this object. The
-   * [typeProvider] is the type provider used to find known types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl convertToBool(TypeProvider typeProvider) {
-    InterfaceType boolType = typeProvider.boolType;
-    if (identical(type, boolType)) {
-      return this;
-    }
-    return new DartObjectImpl(boolType, _state.convertToBool());
-  }
-
-  /**
-   * Return the result of invoking the '/' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for
-   * an object of this kind.
-   */
-  DartObjectImpl divide(
-      TypeProvider typeProvider, DartObjectImpl rightOperand) {
-    InstanceState result = _state.divide(rightOperand._state);
-    if (result is IntState) {
-      return new DartObjectImpl(typeProvider.intType, result);
-    } else if (result is DoubleState) {
-      return new DartObjectImpl(typeProvider.doubleType, result);
-    } else if (result is NumState) {
-      return new DartObjectImpl(typeProvider.numType, result);
-    }
-    // We should never get here.
-    throw new IllegalStateException("divide returned a ${result.runtimeType}");
-  }
-
-  /**
-   * Return the result of invoking the '==' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl equalEqual(
-      TypeProvider typeProvider, DartObjectImpl rightOperand) {
-    if (type != rightOperand.type) {
-      String typeName = type.name;
-      if (!(typeName == "bool" ||
-          typeName == "double" ||
-          typeName == "int" ||
-          typeName == "num" ||
-          typeName == "String" ||
-          typeName == "Null" ||
-          type.isDynamic)) {
-        throw new EvaluationException(
-            CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
-      }
-    }
-    return new DartObjectImpl(
-        typeProvider.boolType, _state.equalEqual(rightOperand._state));
-  }
-
-  @override
-  DartObject getField(String name) {
-    if (_state is GenericState) {
-      return (_state as GenericState).fields[name];
-    }
-    return null;
-  }
-
-  /**
-   * Return the result of invoking the '&gt;' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl greaterThan(
-          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
-      new DartObjectImpl(
-          typeProvider.boolType, _state.greaterThan(rightOperand._state));
-
-  /**
-   * Return the result of invoking the '&gt;=' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl greaterThanOrEqual(
-          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
-      new DartObjectImpl(typeProvider.boolType,
-          _state.greaterThanOrEqual(rightOperand._state));
-
-  /**
-   * Return the result of invoking the '~/' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl integerDivide(
-          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
-      new DartObjectImpl(
-          typeProvider.intType, _state.integerDivide(rightOperand._state));
-
-  /**
-   * Return the result of invoking the identical function on this object with
-   * the [rightOperand]. The [typeProvider] is the type provider used to find
-   * known types.
-   */
-  DartObjectImpl isIdentical(
-      TypeProvider typeProvider, DartObjectImpl rightOperand) {
-    return new DartObjectImpl(
-        typeProvider.boolType, _state.isIdentical(rightOperand._state));
-  }
-
-  /**
-   * Return the result of invoking the '&lt;' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl lessThan(
-          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
-      new DartObjectImpl(
-          typeProvider.boolType, _state.lessThan(rightOperand._state));
-
-  /**
-   * Return the result of invoking the '&lt;=' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl lessThanOrEqual(
-          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
-      new DartObjectImpl(
-          typeProvider.boolType, _state.lessThanOrEqual(rightOperand._state));
-
-  /**
-   * Return the result of invoking the '&&' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl logicalAnd(
-          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
-      new DartObjectImpl(
-          typeProvider.boolType, _state.logicalAnd(rightOperand._state));
-
-  /**
-   * Return the result of invoking the '!' operator on this object. The
-   * [typeProvider] is the type provider used to find known types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl logicalNot(TypeProvider typeProvider) =>
-      new DartObjectImpl(typeProvider.boolType, _state.logicalNot());
-
-  /**
-   * Return the result of invoking the '||' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl logicalOr(
-          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
-      new DartObjectImpl(
-          typeProvider.boolType, _state.logicalOr(rightOperand._state));
-
-  /**
-   * Return the result of invoking the '-' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl minus(TypeProvider typeProvider, DartObjectImpl rightOperand) {
-    InstanceState result = _state.minus(rightOperand._state);
-    if (result is IntState) {
-      return new DartObjectImpl(typeProvider.intType, result);
-    } else if (result is DoubleState) {
-      return new DartObjectImpl(typeProvider.doubleType, result);
-    } else if (result is NumState) {
-      return new DartObjectImpl(typeProvider.numType, result);
-    }
-    // We should never get here.
-    throw new IllegalStateException("minus returned a ${result.runtimeType}");
-  }
-
-  /**
-   * Return the result of invoking the '-' operator on this object. The
-   * [typeProvider] is the type provider used to find known types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl negated(TypeProvider typeProvider) {
-    InstanceState result = _state.negated();
-    if (result is IntState) {
-      return new DartObjectImpl(typeProvider.intType, result);
-    } else if (result is DoubleState) {
-      return new DartObjectImpl(typeProvider.doubleType, result);
-    } else if (result is NumState) {
-      return new DartObjectImpl(typeProvider.numType, result);
-    }
-    // We should never get here.
-    throw new IllegalStateException("negated returned a ${result.runtimeType}");
-  }
-
-  /**
-   * Return the result of invoking the '!=' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl notEqual(
-      TypeProvider typeProvider, DartObjectImpl rightOperand) {
-    if (type != rightOperand.type) {
-      String typeName = type.name;
-      if (typeName != "bool" &&
-          typeName != "double" &&
-          typeName != "int" &&
-          typeName != "num" &&
-          typeName != "String") {
-        return new DartObjectImpl(typeProvider.boolType, BoolState.TRUE_STATE);
-      }
-    }
-    return new DartObjectImpl(typeProvider.boolType,
-        _state.equalEqual(rightOperand._state).logicalNot());
-  }
-
-  /**
-   * Return the result of converting this object to a 'String'. The
-   * [typeProvider] is the type provider used to find known types.
-   *
-   * Throws an [EvaluationException] if the object cannot be converted to a
-   * 'String'.
-   */
-  DartObjectImpl performToString(TypeProvider typeProvider) {
-    InterfaceType stringType = typeProvider.stringType;
-    if (identical(type, stringType)) {
-      return this;
-    }
-    return new DartObjectImpl(stringType, _state.convertToString());
-  }
-
-  /**
-   * Return the result of invoking the '%' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl remainder(
-      TypeProvider typeProvider, DartObjectImpl rightOperand) {
-    InstanceState result = _state.remainder(rightOperand._state);
-    if (result is IntState) {
-      return new DartObjectImpl(typeProvider.intType, result);
-    } else if (result is DoubleState) {
-      return new DartObjectImpl(typeProvider.doubleType, result);
-    } else if (result is NumState) {
-      return new DartObjectImpl(typeProvider.numType, result);
-    }
-    // We should never get here.
-    throw new IllegalStateException(
-        "remainder returned a ${result.runtimeType}");
-  }
-
-  /**
-   * Return the result of invoking the '&lt;&lt;' operator on this object with
-   * the [rightOperand]. The [typeProvider] is the type provider used to find
-   * known types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl shiftLeft(
-          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
-      new DartObjectImpl(
-          typeProvider.intType, _state.shiftLeft(rightOperand._state));
-
-  /**
-   * Return the result of invoking the '&gt;&gt;' operator on this object with
-   * the [rightOperand]. The [typeProvider] is the type provider used to find
-   * known types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl shiftRight(
-          TypeProvider typeProvider, DartObjectImpl rightOperand) =>
-      new DartObjectImpl(
-          typeProvider.intType, _state.shiftRight(rightOperand._state));
-
-  /**
-   * Return the result of invoking the 'length' getter on this object. The
-   * [typeProvider] is the type provider used to find known types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl stringLength(TypeProvider typeProvider) =>
-      new DartObjectImpl(typeProvider.intType, _state.stringLength());
-
-  /**
-   * Return the result of invoking the '*' operator on this object with the
-   * [rightOperand]. The [typeProvider] is the type provider used to find known
-   * types.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  DartObjectImpl times(TypeProvider typeProvider, DartObjectImpl rightOperand) {
-    InstanceState result = _state.times(rightOperand._state);
-    if (result is IntState) {
-      return new DartObjectImpl(typeProvider.intType, result);
-    } else if (result is DoubleState) {
-      return new DartObjectImpl(typeProvider.doubleType, result);
-    } else if (result is NumState) {
-      return new DartObjectImpl(typeProvider.numType, result);
-    }
-    // We should never get here.
-    throw new IllegalStateException("times returned a ${result.runtimeType}");
-  }
-
-  @override
-  bool toBoolValue() {
-    if (_state is BoolState) {
-      return (_state as BoolState).value;
-    }
-    return null;
-  }
-
-  @override
-  double toDoubleValue() {
-    if (_state is DoubleState) {
-      return (_state as DoubleState).value;
-    }
-    return null;
-  }
-
-  @override
-  int toIntValue() {
-    if (_state is IntState) {
-      return (_state as IntState).value;
-    }
-    return null;
-  }
-
-  @override
-  List<DartObject> toListValue() {
-    if (_state is ListState) {
-      return (_state as ListState)._elements;
-    }
-    return null;
-  }
-
-  @override
-  Map<DartObject, DartObject> toMapValue() {
-    if (_state is MapState) {
-      return (_state as MapState)._entries;
-    }
-    return null;
-  }
-
-  @override
-  String toString() => "${type.displayName} ($_state)";
-
-  @override
-  String toStringValue() {
-    if (_state is StringState) {
-      return (_state as StringState).value;
-    }
-    return null;
-  }
-
-  @override
-  String toSymbolValue() {
-    if (_state is SymbolState) {
-      return (_state as SymbolState).value;
-    }
-    return null;
-  }
-
-  @override
-  DartType toTypeValue() {
-    if (_state is TypeState) {
-      Element element = (_state as TypeState)._element;
-      if (element is TypeDefiningElement) {
-        return element.type;
-      }
-    }
-    return null;
-  }
-}
-
-/**
- * An object used to provide access to the values of variables that have been
- * defined on the command line using the `-D` option.
- */
-class DeclaredVariables {
-  /**
-   * A table mapping the names of declared variables to their values.
-   */
-  HashMap<String, String> _declaredVariables = new HashMap<String, String>();
-
-  /**
-   * Define a variable with the given [name] to have the given [value].
-   */
-  void define(String name, String value) {
-    _declaredVariables[name] = value;
-  }
-
-  /**
-   * Return the value of the variable with the given [name] interpreted as a
-   * 'boolean' value. If the variable is not defined (or [name] is `null`), a
-   * DartObject representing "unknown" is returned. If the value cannot be
-   * parsed as a boolean, a DartObject representing 'null' is returned. The
-   * [typeProvider] is the type provider used to find the type 'bool'.
-   */
-  DartObject getBool(TypeProvider typeProvider, String name) {
-    String value = _declaredVariables[name];
-    if (value == null) {
-      return new DartObjectImpl(typeProvider.boolType, BoolState.UNKNOWN_VALUE);
-    }
-    if (value == "true") {
-      return new DartObjectImpl(typeProvider.boolType, BoolState.TRUE_STATE);
-    } else if (value == "false") {
-      return new DartObjectImpl(typeProvider.boolType, BoolState.FALSE_STATE);
-    }
-    return new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE);
-  }
-
-  /**
-   * Return the value of the variable with the given [name] interpreted as an
-   * integer value. If the variable is not defined (or [name] is `null`), a
-   * DartObject representing "unknown" is returned. If the value cannot be
-   * parsed as an integer, a DartObject representing 'null' is returned.
-   */
-  DartObject getInt(TypeProvider typeProvider, String name) {
-    String value = _declaredVariables[name];
-    if (value == null) {
-      return new DartObjectImpl(typeProvider.intType, IntState.UNKNOWN_VALUE);
-    }
-    int bigInteger;
-    try {
-      bigInteger = int.parse(value);
-    } on FormatException {
-      return new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE);
-    }
-    return new DartObjectImpl(typeProvider.intType, new IntState(bigInteger));
-  }
-
-  /**
-   * Return the value of the variable with the given [name] interpreted as a
-   * String value, or `null` if the variable is not defined. Return the value of
-   * the variable with the given name interpreted as a String value. If the
-   * variable is not defined (or [name] is `null`), a DartObject representing
-   * "unknown" is returned. The [typeProvider] is the type provider used to find
-   * the type 'String'.
-   */
-  DartObject getString(TypeProvider typeProvider, String name) {
-    String value = _declaredVariables[name];
-    if (value == null) {
-      return new DartObjectImpl(
-          typeProvider.stringType, StringState.UNKNOWN_VALUE);
-    }
-    return new DartObjectImpl(typeProvider.stringType, new StringState(value));
-  }
-}
-
-/**
- * The state of an object representing a double.
- */
-class DoubleState extends NumState {
-  /**
-   * A state that can be used to represent a double whose value is not known.
-   */
-  static DoubleState UNKNOWN_VALUE = new DoubleState(null);
-
-  /**
-   * The value of this instance.
-   */
-  final double value;
-
-  /**
-   * Initialize a newly created state to represent a double with the given
-   * [value].
-   */
-  DoubleState(this.value);
-
-  @override
-  int get hashCode => value == null ? 0 : value.hashCode;
-
-  @override
-  bool get isBoolNumStringOrNull => true;
-
-  @override
-  bool get isUnknown => value == null;
-
-  @override
-  String get typeName => "double";
-
-  @override
-  bool operator ==(Object object) =>
-      object is DoubleState && (value == object.value);
-
-  @override
-  NumState add(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return new DoubleState(value + rightValue.toDouble());
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return new DoubleState(value + rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  StringState convertToString() {
-    if (value == null) {
-      return StringState.UNKNOWN_VALUE;
-    }
-    return new StringState(value.toString());
-  }
-
-  @override
-  NumState divide(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return new DoubleState(value / rightValue.toDouble());
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return new DoubleState(value / rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  BoolState equalEqual(InstanceState rightOperand) {
-    assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
-  }
-
-  @override
-  BoolState greaterThan(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value > rightValue.toDouble());
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value > rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  BoolState greaterThanOrEqual(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value >= rightValue.toDouble());
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value >= rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  IntState integerDivide(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      return IntState.UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return IntState.UNKNOWN_VALUE;
-      }
-      double result = value / rightValue.toDouble();
-      return new IntState(result.toInt());
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return IntState.UNKNOWN_VALUE;
-      }
-      double result = value / rightValue;
-      return new IntState(result.toInt());
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return IntState.UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  BoolState isIdentical(InstanceState rightOperand) {
-    if (value == null) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value == rightValue);
-    } else if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value == rightValue.toDouble());
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    return BoolState.FALSE_STATE;
-  }
-
-  @override
-  BoolState lessThan(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value < rightValue.toDouble());
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value < rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  BoolState lessThanOrEqual(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value <= rightValue.toDouble());
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value <= rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  NumState minus(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return new DoubleState(value - rightValue.toDouble());
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return new DoubleState(value - rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  NumState negated() {
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    return new DoubleState(-(value));
-  }
-
-  @override
-  NumState remainder(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return new DoubleState(value % rightValue.toDouble());
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return new DoubleState(value % rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  NumState times(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return new DoubleState(value * rightValue.toDouble());
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return new DoubleState(value * rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  String toString() => value == null ? "-unknown-" : value.toString();
-}
-
-/**
- * The state of an object representing a Dart object for which there is no type
- * information.
- */
-class DynamicState extends InstanceState {
-  /**
-   * The unique instance of this class.
-   */
-  static DynamicState DYNAMIC_STATE = new DynamicState();
-
-  @override
-  bool get isBool => true;
-
-  @override
-  bool get isBoolNumStringOrNull => true;
-
-  @override
-  String get typeName => "dynamic";
-
-  @override
-  NumState add(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return _unknownNum(rightOperand);
-  }
-
-  @override
-  IntState bitAnd(InstanceState rightOperand) {
-    assertIntOrNull(rightOperand);
-    return IntState.UNKNOWN_VALUE;
-  }
-
-  @override
-  IntState bitNot() => IntState.UNKNOWN_VALUE;
-
-  @override
-  IntState bitOr(InstanceState rightOperand) {
-    assertIntOrNull(rightOperand);
-    return IntState.UNKNOWN_VALUE;
-  }
-
-  @override
-  IntState bitXor(InstanceState rightOperand) {
-    assertIntOrNull(rightOperand);
-    return IntState.UNKNOWN_VALUE;
-  }
-
-  @override
-  StringState concatenate(InstanceState rightOperand) {
-    assertString(rightOperand);
-    return StringState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState convertToBool() => BoolState.UNKNOWN_VALUE;
-
-  @override
-  StringState convertToString() => StringState.UNKNOWN_VALUE;
-
-  @override
-  NumState divide(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return _unknownNum(rightOperand);
-  }
-
-  @override
-  BoolState equalEqual(InstanceState rightOperand) {
-    assertBoolNumStringOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState greaterThan(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState greaterThanOrEqual(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  IntState integerDivide(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return IntState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState isIdentical(InstanceState rightOperand) {
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState lessThan(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState lessThanOrEqual(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState logicalAnd(InstanceState rightOperand) {
-    assertBool(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState logicalNot() => BoolState.UNKNOWN_VALUE;
-
-  @override
-  BoolState logicalOr(InstanceState rightOperand) {
-    assertBool(rightOperand);
-    return rightOperand.convertToBool();
-  }
-
-  @override
-  NumState minus(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return _unknownNum(rightOperand);
-  }
-
-  @override
-  NumState negated() => NumState.UNKNOWN_VALUE;
-
-  @override
-  NumState remainder(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return _unknownNum(rightOperand);
-  }
-
-  @override
-  IntState shiftLeft(InstanceState rightOperand) {
-    assertIntOrNull(rightOperand);
-    return IntState.UNKNOWN_VALUE;
-  }
-
-  @override
-  IntState shiftRight(InstanceState rightOperand) {
-    assertIntOrNull(rightOperand);
-    return IntState.UNKNOWN_VALUE;
-  }
-
-  @override
-  NumState times(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return _unknownNum(rightOperand);
-  }
-
-  /**
-   * Return an object representing an unknown numeric value whose type is based
-   * on the type of the [rightOperand].
-   */
-  NumState _unknownNum(InstanceState rightOperand) {
-    if (rightOperand is IntState) {
-      return IntState.UNKNOWN_VALUE;
-    } else if (rightOperand is DoubleState) {
-      return DoubleState.UNKNOWN_VALUE;
-    }
-    return NumState.UNKNOWN_VALUE;
-  }
-}
-
-/**
- * A run-time exception that would be thrown during the evaluation of Dart code.
- */
-class EvaluationException extends JavaException {
-  /**
-   * The error code associated with the exception.
-   */
-  final ErrorCode errorCode;
-
-  /**
-   * Initialize a newly created exception to have the given [errorCode].
-   */
-  EvaluationException(this.errorCode);
-}
-
-/**
- * The result of attempting to evaluate an expression.
- */
-class EvaluationResult {
-  /**
-   * The value of the expression.
-   */
-  final DartObject value;
-
-  /**
-   * The errors that should be reported for the expression(s) that were
-   * evaluated.
-   */
-  final List<AnalysisError> _errors;
-
-  /**
-   * Initialize a newly created result object with the given [value] and set of
-   * [_errors]. Clients should use one of the factory methods: [forErrors] and
-   * [forValue].
-   */
-  EvaluationResult(this.value, this._errors);
-
-  /**
-   * Return a list containing the errors that should be reported for the
-   * expression(s) that were evaluated. If there are no such errors, the list
-   * will be empty. The list can be empty even if the expression is not a valid
-   * compile time constant if the errors would have been reported by other parts
-   * of the analysis engine.
-   */
-  List<AnalysisError> get errors =>
-      _errors == null ? AnalysisError.NO_ERRORS : _errors;
-
-  /**
-   * Return `true` if the expression is a compile-time constant expression that
-   * would not throw an exception when evaluated.
-   */
-  bool get isValid => _errors == null;
-
-  /**
-   * Return an evaluation result representing the result of evaluating an
-   * expression that is not a compile-time constant because of the given
-   * [errors].
-   */
-  static EvaluationResult forErrors(List<AnalysisError> errors) =>
-      new EvaluationResult(null, errors);
-
-  /**
-   * Return an evaluation result representing the result of evaluating an
-   * expression that is a compile-time constant that evaluates to the given
-   * [value].
-   */
-  static EvaluationResult forValue(DartObject value) =>
-      new EvaluationResult(value, null);
-}
-
-/**
- * The result of attempting to evaluate a expression.
- */
-class EvaluationResultImpl {
-  /**
-   * The errors encountered while trying to evaluate the compile time constant.
-   * These errors may or may not have prevented the expression from being a
-   * valid compile time constant.
-   */
-  List<AnalysisError> _errors;
-
-  /**
-   * The value of the expression, or `null` if the value couldn't be computed
-   * due to errors.
-   */
-  final DartObjectImpl value;
-
-  EvaluationResultImpl(this.value, [List<AnalysisError> errors]) {
-    this._errors = errors == null ? <AnalysisError>[] : errors;
-  }
-
-  List<AnalysisError> get errors => _errors;
-
-  bool equalValues(TypeProvider typeProvider, EvaluationResultImpl result) {
-    if (this.value != null) {
-      if (result.value == null) {
-        return false;
-      }
-      return value == result.value;
-    } else {
-      return false;
-    }
-  }
-
-  @override
-  String toString() {
-    if (value == null) {
-      return "error";
-    }
-    return value.toString();
-  }
-}
-
-/**
- * The state of an object representing a function.
- */
-class FunctionState extends InstanceState {
-  /**
-   * The element representing the function being modeled.
-   */
-  final ExecutableElement _element;
-
-  /**
-   * Initialize a newly created state to represent the function with the given
-   * [element].
-   */
-  FunctionState(this._element);
-
-  @override
-  int get hashCode => _element == null ? 0 : _element.hashCode;
-
-  @override
-  String get typeName => "Function";
-
-  @override
-  bool operator ==(Object object) =>
-      object is FunctionState && (_element == object._element);
-
-  @override
-  StringState convertToString() {
-    if (_element == null) {
-      return StringState.UNKNOWN_VALUE;
-    }
-    return new StringState(_element.name);
-  }
-
-  @override
-  BoolState equalEqual(InstanceState rightOperand) {
-    return isIdentical(rightOperand);
-  }
-
-  @override
-  BoolState isIdentical(InstanceState rightOperand) {
-    if (_element == null) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    if (rightOperand is FunctionState) {
-      ExecutableElement rightElement = rightOperand._element;
-      if (rightElement == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(_element == rightElement);
-    } else if (rightOperand is DynamicState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    return BoolState.FALSE_STATE;
-  }
-
-  @override
-  String toString() => _element == null ? "-unknown-" : _element.name;
-}
-
-/**
- * The state of an object representing a Dart object for which there is no more
- * specific state.
- */
-class GenericState extends InstanceState {
-  /**
-   * Pseudo-field that we use to represent fields in the superclass.
-   */
-  static String SUPERCLASS_FIELD = "(super)";
-
-  /**
-   * A state that can be used to represent an object whose state is not known.
-   */
-  static GenericState UNKNOWN_VALUE =
-      new GenericState(new HashMap<String, DartObjectImpl>());
-
-  /**
-   * The values of the fields of this instance.
-   */
-  final HashMap<String, DartObjectImpl> _fieldMap;
-
-  /**
-   * Initialize a newly created state to represent a newly created object. The
-   * [fieldMap] contains the values of the fields of the instance.
-   */
-  GenericState(this._fieldMap);
-
-  @override
-  HashMap<String, DartObjectImpl> get fields => _fieldMap;
-
-  @override
-  int get hashCode {
-    int hashCode = 0;
-    for (DartObjectImpl value in _fieldMap.values) {
-      hashCode += value.hashCode;
-    }
-    return hashCode;
-  }
-
-  @override
-  bool get isUnknown => identical(this, UNKNOWN_VALUE);
-
-  @override
-  String get typeName => "user defined type";
-
-  @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;
-      }
-      otherFields.remove(fieldName);
-    }
-    for (String fieldName in otherFields) {
-      if (state._fieldMap[fieldName] != _fieldMap[fieldName]) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  @override
-  StringState convertToString() => StringState.UNKNOWN_VALUE;
-
-  @override
-  BoolState equalEqual(InstanceState rightOperand) {
-    assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
-  }
-
-  @override
-  BoolState isIdentical(InstanceState rightOperand) {
-    if (rightOperand is DynamicState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    return BoolState.from(this == rightOperand);
-  }
-
-  @override
-  String toString() {
-    StringBuffer buffer = new StringBuffer();
-    List<String> fieldNames = _fieldMap.keys.toList();
-    fieldNames.sort();
-    bool first = true;
-    for (String fieldName in fieldNames) {
-      if (first) {
-        first = false;
-      } else {
-        buffer.write('; ');
-      }
-      buffer.write(fieldName);
-      buffer.write(' = ');
-      buffer.write(_fieldMap[fieldName]);
-    }
-    return buffer.toString();
-  }
-}
-
-/**
- * The state of an object representing a Dart object.
- */
-abstract class InstanceState {
-  /**
-   * If this represents a generic dart object, return a map from its field names
-   * to their values. Otherwise return null.
-   */
-  HashMap<String, DartObjectImpl> get fields => null;
-
-  /**
-   * Return `true` if this object represents an object whose type is 'bool'.
-   */
-  bool get isBool => false;
-
-  /**
-   * Return `true` if this object represents an object whose type is either
-   * 'bool', 'num', 'String', or 'Null'.
-   */
-  bool get isBoolNumStringOrNull => false;
-
-  /**
-   * Return `true` if this object represents an unknown value.
-   */
-  bool get isUnknown => false;
-
-  /**
-   * Return the name of the type of this value.
-   */
-  String get typeName;
-
-  /**
-   * Return the result of invoking the '+' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  InstanceState add(InstanceState rightOperand) {
-    if (this is StringState && rightOperand is StringState) {
-      return concatenate(rightOperand);
-    }
-    assertNumOrNull(this);
-    assertNumOrNull(rightOperand);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Throw an exception if the given [state] does not represent a boolean value.
-   */
-  void assertBool(InstanceState state) {
-    if (!(state is BoolState || state is DynamicState)) {
-      throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
-    }
-  }
-
-  /**
-   * Throw an exception if the given [state] does not represent a boolean,
-   * numeric, string or null value.
-   */
-  void assertBoolNumStringOrNull(InstanceState state) {
-    if (!(state is BoolState ||
-        state is DoubleState ||
-        state is IntState ||
-        state is NumState ||
-        state is StringState ||
-        state is NullState ||
-        state is DynamicState)) {
-      throw new EvaluationException(
-          CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
-    }
-  }
-
-  /**
-   * Throw an exception if the given [state] does not represent an integer or
-   * null value.
-   */
-  void assertIntOrNull(InstanceState state) {
-    if (!(state is IntState ||
-        state is NumState ||
-        state is NullState ||
-        state is DynamicState)) {
-      throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
-    }
-  }
-
-  /**
-   * Throw an exception if the given [state] does not represent a boolean,
-   * numeric, string or null value.
-   */
-  void assertNumOrNull(InstanceState state) {
-    if (!(state is DoubleState ||
-        state is IntState ||
-        state is NumState ||
-        state is NullState ||
-        state is DynamicState)) {
-      throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
-    }
-  }
-
-  /**
-   * Throw an exception if the given [state] does not represent a String value.
-   */
-  void assertString(InstanceState state) {
-    if (!(state is StringState || state is DynamicState)) {
-      throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
-    }
-  }
-
-  /**
-   * Return the result of invoking the '&' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  IntState bitAnd(InstanceState rightOperand) {
-    assertIntOrNull(this);
-    assertIntOrNull(rightOperand);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Return the result of invoking the '~' operator on this object.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  IntState bitNot() {
-    assertIntOrNull(this);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Return the result of invoking the '|' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  IntState bitOr(InstanceState rightOperand) {
-    assertIntOrNull(this);
-    assertIntOrNull(rightOperand);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Return the result of invoking the '^' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  IntState bitXor(InstanceState rightOperand) {
-    assertIntOrNull(this);
-    assertIntOrNull(rightOperand);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Return the result of invoking the ' ' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  StringState concatenate(InstanceState rightOperand) {
-    assertString(rightOperand);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Return the result of applying boolean conversion to this object.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  BoolState convertToBool() => BoolState.FALSE_STATE;
-
-  /**
-   * Return the result of converting this object to a String.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  StringState convertToString();
-
-  /**
-   * Return the result of invoking the '/' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  NumState divide(InstanceState rightOperand) {
-    assertNumOrNull(this);
-    assertNumOrNull(rightOperand);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Return the result of invoking the '==' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  BoolState equalEqual(InstanceState rightOperand);
-
-  /**
-   * Return the result of invoking the '&gt;' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  BoolState greaterThan(InstanceState rightOperand) {
-    assertNumOrNull(this);
-    assertNumOrNull(rightOperand);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Return the result of invoking the '&gt;=' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  BoolState greaterThanOrEqual(InstanceState rightOperand) {
-    assertNumOrNull(this);
-    assertNumOrNull(rightOperand);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Return the result of invoking the '~/' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  IntState integerDivide(InstanceState rightOperand) {
-    assertNumOrNull(this);
-    assertNumOrNull(rightOperand);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Return the result of invoking the identical function on this object with
-   * the [rightOperand].
-   */
-  BoolState isIdentical(InstanceState rightOperand);
-
-  /**
-   * Return the result of invoking the '&lt;' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  BoolState lessThan(InstanceState rightOperand) {
-    assertNumOrNull(this);
-    assertNumOrNull(rightOperand);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Return the result of invoking the '&lt;=' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  BoolState lessThanOrEqual(InstanceState rightOperand) {
-    assertNumOrNull(this);
-    assertNumOrNull(rightOperand);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Return the result of invoking the '&&' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  BoolState logicalAnd(InstanceState rightOperand) {
-    assertBool(this);
-    assertBool(rightOperand);
-    return BoolState.FALSE_STATE;
-  }
-
-  /**
-   * Return the result of invoking the '!' operator on this object.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  BoolState logicalNot() {
-    assertBool(this);
-    return BoolState.TRUE_STATE;
-  }
-
-  /**
-   * Return the result of invoking the '||' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  BoolState logicalOr(InstanceState rightOperand) {
-    assertBool(this);
-    assertBool(rightOperand);
-    return rightOperand.convertToBool();
-  }
-
-  /**
-   * Return the result of invoking the '-' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  NumState minus(InstanceState rightOperand) {
-    assertNumOrNull(this);
-    assertNumOrNull(rightOperand);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Return the result of invoking the '-' operator on this object.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  NumState negated() {
-    assertNumOrNull(this);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Return the result of invoking the '%' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  NumState remainder(InstanceState rightOperand) {
-    assertNumOrNull(this);
-    assertNumOrNull(rightOperand);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Return the result of invoking the '&lt;&lt;' operator on this object with
-   * the [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  IntState shiftLeft(InstanceState rightOperand) {
-    assertIntOrNull(this);
-    assertIntOrNull(rightOperand);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Return the result of invoking the '&gt;&gt;' operator on this object with
-   * the [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  IntState shiftRight(InstanceState rightOperand) {
-    assertIntOrNull(this);
-    assertIntOrNull(rightOperand);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Return the result of invoking the 'length' getter on this object.
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  IntState stringLength() {
-    assertString(this);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-
-  /**
-   * Return the result of invoking the '*' operator on this object with the
-   * [rightOperand].
-   *
-   * Throws an [EvaluationException] if the operator is not appropriate for an
-   * object of this kind.
-   */
-  NumState times(InstanceState rightOperand) {
-    assertNumOrNull(this);
-    assertNumOrNull(rightOperand);
-    throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
-  }
-}
-
-/**
- * The state of an object representing an int.
- */
-class IntState extends NumState {
-  /**
-   * A state that can be used to represent an int whose value is not known.
-   */
-  static IntState UNKNOWN_VALUE = new IntState(null);
-
-  /**
-   * The value of this instance.
-   */
-  final int value;
-
-  /**
-   * Initialize a newly created state to represent an int with the given
-   * [value].
-   */
-  IntState(this.value);
-
-  @override
-  int get hashCode => value == null ? 0 : value.hashCode;
-
-  @override
-  bool get isBoolNumStringOrNull => true;
-
-  @override
-  bool get isUnknown => value == null;
-
-  @override
-  String get typeName => "int";
-
-  @override
-  bool operator ==(Object object) =>
-      object is IntState && (value == object.value);
-
-  @override
-  NumState add(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      if (rightOperand is DoubleState) {
-        return DoubleState.UNKNOWN_VALUE;
-      }
-      return UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return new IntState(value + rightValue);
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return DoubleState.UNKNOWN_VALUE;
-      }
-      return new DoubleState(value.toDouble() + rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  IntState bitAnd(InstanceState rightOperand) {
-    assertIntOrNull(rightOperand);
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return new IntState(value & rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  IntState bitNot() {
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    return new IntState(~value);
-  }
-
-  @override
-  IntState bitOr(InstanceState rightOperand) {
-    assertIntOrNull(rightOperand);
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return new IntState(value | rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  IntState bitXor(InstanceState rightOperand) {
-    assertIntOrNull(rightOperand);
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return new IntState(value ^ rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  StringState convertToString() {
-    if (value == null) {
-      return StringState.UNKNOWN_VALUE;
-    }
-    return new StringState(value.toString());
-  }
-
-  @override
-  NumState divide(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      return DoubleState.UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return DoubleState.UNKNOWN_VALUE;
-      } else {
-        return new DoubleState(value.toDouble() / rightValue.toDouble());
-      }
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return DoubleState.UNKNOWN_VALUE;
-      }
-      return new DoubleState(value.toDouble() / rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return DoubleState.UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  BoolState equalEqual(InstanceState rightOperand) {
-    assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
-  }
-
-  @override
-  BoolState greaterThan(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value.compareTo(rightValue) > 0);
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value.toDouble() > rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  BoolState greaterThanOrEqual(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value.compareTo(rightValue) >= 0);
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value.toDouble() >= rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  IntState integerDivide(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      } else if (rightValue == 0) {
-        throw new EvaluationException(
-            CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE);
-      }
-      return new IntState(value ~/ rightValue);
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      double result = value.toDouble() / rightValue;
-      return new IntState(result.toInt());
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  BoolState isIdentical(InstanceState rightOperand) {
-    if (value == null) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value == rightValue);
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(rightValue == value.toDouble());
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    return BoolState.FALSE_STATE;
-  }
-
-  @override
-  BoolState lessThan(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value.compareTo(rightValue) < 0);
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value.toDouble() < rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  BoolState lessThanOrEqual(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value.compareTo(rightValue) <= 0);
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value.toDouble() <= rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  NumState minus(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      if (rightOperand is DoubleState) {
-        return DoubleState.UNKNOWN_VALUE;
-      }
-      return UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return new IntState(value - rightValue);
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return DoubleState.UNKNOWN_VALUE;
-      }
-      return new DoubleState(value.toDouble() - rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  NumState negated() {
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    return new IntState(-value);
-  }
-
-  @override
-  NumState remainder(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      if (rightOperand is DoubleState) {
-        return DoubleState.UNKNOWN_VALUE;
-      }
-      return UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      } else if (rightValue == 0) {
-        return new DoubleState(value.toDouble() % rightValue.toDouble());
-      }
-      return new IntState(value.remainder(rightValue));
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return DoubleState.UNKNOWN_VALUE;
-      }
-      return new DoubleState(value.toDouble() % rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  IntState shiftLeft(InstanceState rightOperand) {
-    assertIntOrNull(rightOperand);
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      } else if (rightValue.bitLength > 31) {
-        return UNKNOWN_VALUE;
-      }
-      return new IntState(value << rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  IntState shiftRight(InstanceState rightOperand) {
-    assertIntOrNull(rightOperand);
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      } else if (rightValue.bitLength > 31) {
-        return UNKNOWN_VALUE;
-      }
-      return new IntState(value >> rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  NumState times(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (value == null) {
-      if (rightOperand is DoubleState) {
-        return DoubleState.UNKNOWN_VALUE;
-      }
-      return UNKNOWN_VALUE;
-    }
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return new IntState(value * rightValue);
-    } else if (rightOperand is DoubleState) {
-      double rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return DoubleState.UNKNOWN_VALUE;
-      }
-      return new DoubleState(value.toDouble() * rightValue);
-    } else if (rightOperand is DynamicState || rightOperand is NumState) {
-      return UNKNOWN_VALUE;
-    }
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  String toString() => value == null ? "-unknown-" : value.toString();
-}
-
-/**
- * The state of an object representing a list.
- */
-class ListState extends InstanceState {
-  /**
-   * The elements of the list.
-   */
-  final List<DartObjectImpl> _elements;
-
-  /**
-   * Initialize a newly created state to represent a list with the given
-   * [elements].
-   */
-  ListState(this._elements);
-
-  @override
-  int get hashCode {
-    int value = 0;
-    int count = _elements.length;
-    for (int i = 0; i < count; i++) {
-      value = (value << 3) ^ _elements[i].hashCode;
-    }
-    return value;
-  }
-
-  @override
-  String get typeName => "List";
-
-  @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) {
-      return true;
-    }
-    for (int i = 0; i < count; i++) {
-      if (_elements[i] != otherElements[i]) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  @override
-  StringState convertToString() => StringState.UNKNOWN_VALUE;
-
-  @override
-  BoolState equalEqual(InstanceState rightOperand) {
-    assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
-  }
-
-  @override
-  BoolState isIdentical(InstanceState rightOperand) {
-    if (rightOperand is DynamicState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    return BoolState.from(this == rightOperand);
-  }
-
-  @override
-  String toString() {
-    StringBuffer buffer = new StringBuffer();
-    buffer.write('[');
-    bool first = true;
-    _elements.forEach((DartObjectImpl element) {
-      if (first) {
-        first = false;
-      } else {
-        buffer.write(', ');
-      }
-      buffer.write(element);
-    });
-    buffer.write(']');
-    return buffer.toString();
-  }
-}
-
-/**
- * The state of an object representing a map.
- */
-class MapState extends InstanceState {
-  /**
-   * The entries in the map.
-   */
-  final HashMap<DartObjectImpl, DartObjectImpl> _entries;
-
-  /**
-   * Initialize a newly created state to represent a map with the given
-   * [entries].
-   */
-  MapState(this._entries);
-
-  @override
-  int get hashCode {
-    int value = 0;
-    for (DartObjectImpl key in _entries.keys.toSet()) {
-      value = (value << 3) ^ key.hashCode;
-    }
-    return value;
-  }
-
-  @override
-  String get typeName => "Map";
-
-  @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) {
-      return true;
-    }
-    for (DartObjectImpl key in _entries.keys) {
-      DartObjectImpl value = _entries[key];
-      DartObjectImpl otherValue = otherElements[key];
-      if (value != otherValue) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  @override
-  StringState convertToString() => StringState.UNKNOWN_VALUE;
-
-  @override
-  BoolState equalEqual(InstanceState rightOperand) {
-    assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
-  }
-
-  @override
-  BoolState isIdentical(InstanceState rightOperand) {
-    if (rightOperand is DynamicState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    return BoolState.from(this == rightOperand);
-  }
-
-  @override
-  String toString() {
-    StringBuffer buffer = new StringBuffer();
-    buffer.write('{');
-    bool first = true;
-    _entries.forEach((DartObjectImpl key, DartObjectImpl value) {
-      if (first) {
-        first = false;
-      } else {
-        buffer.write(', ');
-      }
-      buffer.write(key);
-      buffer.write(' = ');
-      buffer.write(value);
-    });
-    buffer.write('}');
-    return buffer.toString();
-  }
-}
-
-/**
- * The state of an object representing the value 'null'.
- */
-class NullState extends InstanceState {
-  /**
-   * An instance representing the boolean value 'null'.
-   */
-  static NullState NULL_STATE = new NullState();
-
-  @override
-  int get hashCode => 0;
-
-  @override
-  bool get isBoolNumStringOrNull => true;
-
-  @override
-  String get typeName => "Null";
-
-  @override
-  bool operator ==(Object object) => object is NullState;
-
-  @override
-  BoolState convertToBool() {
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  StringState convertToString() => new StringState("null");
-
-  @override
-  BoolState equalEqual(InstanceState rightOperand) {
-    assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
-  }
-
-  @override
-  BoolState isIdentical(InstanceState rightOperand) {
-    if (rightOperand is DynamicState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    return BoolState.from(rightOperand is NullState);
-  }
-
-  @override
-  BoolState logicalNot() {
-    throw new EvaluationException(
-        CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
-  }
-
-  @override
-  String toString() => "null";
-}
-
-/**
- * The state of an object representing a number of an unknown type (a 'num').
- */
-class NumState extends InstanceState {
-  /**
-   * A state that can be used to represent a number whose value is not known.
-   */
-  static NumState UNKNOWN_VALUE = new NumState();
-
-  @override
-  int get hashCode => 7;
-
-  @override
-  bool get isBoolNumStringOrNull => true;
-
-  @override
-  bool get isUnknown => identical(this, UNKNOWN_VALUE);
-
-  @override
-  String get typeName => "num";
-
-  @override
-  bool operator ==(Object object) => object is NumState;
-
-  @override
-  NumState add(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return UNKNOWN_VALUE;
-  }
-
-  @override
-  StringState convertToString() => StringState.UNKNOWN_VALUE;
-
-  @override
-  NumState divide(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return DoubleState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState equalEqual(InstanceState rightOperand) {
-    assertBoolNumStringOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState greaterThan(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState greaterThanOrEqual(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  IntState integerDivide(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    if (rightOperand is IntState) {
-      int rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return IntState.UNKNOWN_VALUE;
-      } else if (rightValue == 0) {
-        throw new EvaluationException(
-            CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE);
-      }
-    } else if (rightOperand is DynamicState) {
-      return IntState.UNKNOWN_VALUE;
-    }
-    return IntState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState isIdentical(InstanceState rightOperand) {
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState lessThan(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  BoolState lessThanOrEqual(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return BoolState.UNKNOWN_VALUE;
-  }
-
-  @override
-  NumState minus(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return UNKNOWN_VALUE;
-  }
-
-  @override
-  NumState negated() => UNKNOWN_VALUE;
-
-  @override
-  NumState remainder(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return UNKNOWN_VALUE;
-  }
-
-  @override
-  NumState times(InstanceState rightOperand) {
-    assertNumOrNull(rightOperand);
-    return UNKNOWN_VALUE;
-  }
-
-  @override
-  String toString() => "-unknown-";
-}
-
-/**
- * An object used to add reference information for a given variable to the
- * bi-directional mapping used to order the evaluation of constants.
- */
-class ReferenceFinder extends RecursiveAstVisitor<Object> {
-  /**
-   * The callback which should be used to report any dependencies that were
-   * found.
-   */
-  final ReferenceFinderCallback _callback;
-
-  /**
-   * Initialize a newly created reference finder to find references from a given
-   * variable to other variables and to add those references to the given graph.
-   * The [_callback] will be invoked for every dependency found.
-   */
-  ReferenceFinder(this._callback);
-
-  @override
-  Object visitInstanceCreationExpression(InstanceCreationExpression node) {
-    if (node.isConst) {
-      ConstructorElement constructor = _getConstructorImpl(node.staticElement);
-      if (constructor != null) {
-        _callback(constructor);
-      }
-    }
-    return super.visitInstanceCreationExpression(node);
-  }
-
-  @override
-  Object visitLabel(Label node) {
-    // We are visiting the "label" part of a named expression in a function
-    // call (presumably a constructor call), e.g. "const C(label: ...)".  We
-    // don't want to visit the SimpleIdentifier for the label because that's a
-    // reference to a function parameter that needs to be filled in; it's not a
-    // constant whose value we depend on.
-    return null;
-  }
-
-  @override
-  Object visitRedirectingConstructorInvocation(
-      RedirectingConstructorInvocation node) {
-    super.visitRedirectingConstructorInvocation(node);
-    ConstructorElement target = _getConstructorImpl(node.staticElement);
-    if (target != null) {
-      _callback(target);
-    }
-    return null;
-  }
-
-  @override
-  Object visitSimpleIdentifier(SimpleIdentifier node) {
-    Element element = node.staticElement;
-    if (element is PropertyAccessorElement) {
-      element = (element as PropertyAccessorElement).variable;
-    }
-    if (element is VariableElement && element.isConst) {
-      _callback(element);
-    }
-    return null;
-  }
-
-  @override
-  Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
-    super.visitSuperConstructorInvocation(node);
-    ConstructorElement constructor = _getConstructorImpl(node.staticElement);
-    if (constructor != null) {
-      _callback(constructor);
-    }
-    return null;
-  }
-}
-
-/**
- * The state of an object representing a string.
- */
-class StringState extends InstanceState {
-  /**
-   * A state that can be used to represent a double whose value is not known.
-   */
-  static StringState UNKNOWN_VALUE = new StringState(null);
-
-  /**
-   * The value of this instance.
-   */
-  final String value;
-
-  /**
-   * Initialize a newly created state to represent the given [value].
-   */
-  StringState(this.value);
-
-  @override
-  int get hashCode => value == null ? 0 : value.hashCode;
-
-  @override
-  bool get isBoolNumStringOrNull => true;
-
-  @override
-  bool get isUnknown => value == null;
-
-  @override
-  String get typeName => "String";
-
-  @override
-  bool operator ==(Object object) =>
-      object is StringState && (value == object.value);
-
-  @override
-  StringState concatenate(InstanceState rightOperand) {
-    if (value == null) {
-      return UNKNOWN_VALUE;
-    }
-    if (rightOperand is StringState) {
-      String rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return UNKNOWN_VALUE;
-      }
-      return new StringState("$value$rightValue");
-    } else if (rightOperand is DynamicState) {
-      return UNKNOWN_VALUE;
-    }
-    return super.concatenate(rightOperand);
-  }
-
-  @override
-  StringState convertToString() => this;
-
-  @override
-  BoolState equalEqual(InstanceState rightOperand) {
-    assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
-  }
-
-  @override
-  BoolState isIdentical(InstanceState rightOperand) {
-    if (value == null) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    if (rightOperand is StringState) {
-      String rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value == rightValue);
-    } else if (rightOperand is DynamicState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    return BoolState.FALSE_STATE;
-  }
-
-  @override
-  IntState stringLength() {
-    if (value == null) {
-      return IntState.UNKNOWN_VALUE;
-    }
-    return new IntState(value.length);
-  }
-
-  @override
-  String toString() => value == null ? "-unknown-" : "'$value'";
-}
-
-/**
- * The state of an object representing a symbol.
- */
-class SymbolState extends InstanceState {
-  /**
-   * The value of this instance.
-   */
-  final String value;
-
-  /**
-   * Initialize a newly created state to represent the given [value].
-   */
-  SymbolState(this.value);
-
-  @override
-  int get hashCode => value == null ? 0 : value.hashCode;
-
-  @override
-  String get typeName => "Symbol";
-
-  @override
-  bool operator ==(Object object) =>
-      object is SymbolState && (value == object.value);
-
-  @override
-  StringState convertToString() {
-    if (value == null) {
-      return StringState.UNKNOWN_VALUE;
-    }
-    return new StringState(value);
-  }
-
-  @override
-  BoolState equalEqual(InstanceState rightOperand) {
-    assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
-  }
-
-  @override
-  BoolState isIdentical(InstanceState rightOperand) {
-    if (value == null) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    if (rightOperand is SymbolState) {
-      String rightValue = rightOperand.value;
-      if (rightValue == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(value == rightValue);
-    } else if (rightOperand is DynamicState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    return BoolState.FALSE_STATE;
-  }
-
-  @override
-  String toString() => value == null ? "-unknown-" : "#$value";
-}
-
-/**
- * The state of an object representing a type.
- */
-class TypeState extends InstanceState {
-  /**
-   * The element representing the type being modeled.
-   */
-  final Element _element;
-
-  /**
-   * Initialize a newly created state to represent the given [value].
-   */
-  TypeState(this._element);
-
-  @override
-  int get hashCode => _element == null ? 0 : _element.hashCode;
-
-  @override
-  String get typeName => "Type";
-
-  @override
-  bool operator ==(Object object) =>
-      object is TypeState && (_element == object._element);
-
-  @override
-  StringState convertToString() {
-    if (_element == null) {
-      return StringState.UNKNOWN_VALUE;
-    }
-    return new StringState(_element.name);
-  }
-
-  @override
-  BoolState equalEqual(InstanceState rightOperand) {
-    assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
-  }
-
-  @override
-  BoolState isIdentical(InstanceState rightOperand) {
-    if (_element == null) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    if (rightOperand is TypeState) {
-      Element rightElement = rightOperand._element;
-      if (rightElement == null) {
-        return BoolState.UNKNOWN_VALUE;
-      }
-      return BoolState.from(_element == rightElement);
-    } else if (rightOperand is DynamicState) {
-      return BoolState.UNKNOWN_VALUE;
-    }
-    return BoolState.FALSE_STATE;
-  }
-
-  @override
-  String toString() => _element == null ? "-unknown-" : _element.name;
-}
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index a9a3881..9945d4e 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -2586,7 +2586,7 @@
   Element get staticElement => null;
 
   @override
-  accept(AstVisitor visitor) => null;
+  dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) => null;
 
   @override
   void visitChildren(AstVisitor visitor) {}
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 60b1acf..846b27b 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -1082,6 +1082,11 @@
   bool get enableSuperMixins;
 
   /**
+   * Return `true` if timing data should be gathered during execution.
+   */
+  bool get enableTiming;
+
+  /**
    * Return `true` if errors, warnings and hints should be generated for sources
    * that are implicitly being analyzed. The default value is `true`.
    */
@@ -1215,6 +1220,9 @@
    */
   bool enableSuperMixins = false;
 
+  @override
+  bool enableTiming = false;
+
   /**
    * A flag indicating whether errors, warnings and hints should be generated
    * for sources that are implicitly being analyzed.
@@ -1293,6 +1301,7 @@
     enableStrictCallChecks = options.enableStrictCallChecks;
     enableGenericMethods = options.enableGenericMethods;
     enableSuperMixins = options.enableSuperMixins;
+    enableTiming = options.enableTiming;
     generateImplicitErrors = options.generateImplicitErrors;
     generateSdkErrors = options.generateSdkErrors;
     hint = options.hint;
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index 0219d7e..4b67db5 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -26,7 +26,7 @@
  * The descriptor used to associate error processors with analysis contexts in
  * configuration data.
  */
-final ListResultDescriptor<List<ErrorProcessor>> CONFIGURED_ERROR_PROCESSORS =
+final ListResultDescriptor<ErrorProcessor> CONFIGURED_ERROR_PROCESSORS =
     new ListResultDescriptorImpl('configured.errors', const <ErrorProcessor>[]);
 
 /**
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index efd0f93..28d02ec 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -5694,6 +5694,15 @@
     iterableType = iterableType.resolveToBound(_typeProvider.objectType);
     DartType bestIterableType =
         _typeSystem.mostSpecificTypeArgument(iterableType, loopType);
+
+    // Allow it to be a supertype of Iterable<T> (basically just Object) and do
+    // an implicit downcast to Iterable<dynamic>.
+    if (bestIterableType == null) {
+      if (_typeSystem.isSubtypeOf(loopType, iterableType)) {
+        bestIterableType = DynamicTypeImpl.instance;
+      }
+    }
+
     if (bestIterableType == null) {
       _errorReporter.reportTypeErrorForNode(
           StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE,
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index 9f4e419..61c8570 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -878,7 +878,7 @@
 
   @override
   DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
-      ResultDescriptor descriptor) {
+      ResultDescriptor descriptor, Object value) {
     // A body change delta should never leak outside its source.
     // It can cause invalidation of results (e.g. hints) in other sources,
     // but only when a result in the updated source is INVALIDATE_NO_DELTA.
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index adf9a73..d537f0c 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -128,7 +128,9 @@
   'expectKeyword_1': new MethodTrampoline(
       1, (Parser target, arg0) => target._expectKeyword(arg0)),
   'findRange_2': new MethodTrampoline(
-      2, (Parser target, arg0, arg1) => target._findRange(arg0, arg1)),
+      2,
+      (Parser target, List<List<int>> arg0, int arg1) =>
+          target._findRange(arg0, arg1)),
   'getCodeBlockRanges_1': new MethodTrampoline(
       1, (Parser target, arg0) => target._getCodeBlockRanges(arg0)),
   'getEndToken_1': new MethodTrampoline(
@@ -202,7 +204,9 @@
   'parseCommentReference_2': new MethodTrampoline(2,
       (Parser target, arg0, arg1) => target._parseCommentReference(arg0, arg1)),
   'parseCommentReferences_1': new MethodTrampoline(
-      1, (Parser target, arg0) => target._parseCommentReferences(arg0)),
+      1,
+      (Parser target, List<DocumentationCommentToken> arg0) =>
+          target._parseCommentReferences(arg0)),
   'parseCompilationUnitMember_1': new MethodTrampoline(
       1, (Parser target, arg0) => target._parseCompilationUnitMember(arg0)),
   'parseConfiguration_0':
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 92814ba..4849014 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -36,26 +36,6 @@
 export 'package:analyzer/src/generated/type_system.dart';
 
 /**
- * Throw an [ElementMismatchException] to report that the element model and the
- * AST do not match. The [message] will have the path to the given [node]
- * appended to it.
- */
-void _mismatch(String message, AstNode node) {
-  StringBuffer buffer = new StringBuffer();
-  buffer.writeln(message);
-  buffer.write('Path to root:');
-  String separator = ' ';
-  AstNode parent = node;
-  while (parent != null) {
-    buffer.write(separator);
-    buffer.write(parent.runtimeType.toString());
-    separator = ', ';
-    parent = parent.parent;
-  }
-  throw new ElementMismatchException(buffer.toString());
-}
-
-/**
  * Instances of the class `BestPracticesVerifier` traverse an AST structure looking for
  * violations of Dart best practices.
  */
@@ -1877,14 +1857,14 @@
             _errorReporter.reportErrorForNode(
                 HintCode.DEAD_CODE, node.rightOperand);
             // only visit the LHS:
-            _safelyVisit(lhsCondition);
+            lhsCondition?.accept(this);
             return null;
           } else if (lhsResult.value.toBoolValue() == false && isAmpAmp) {
             // report error on if block: false && !e!
             _errorReporter.reportErrorForNode(
                 HintCode.DEAD_CODE, node.rightOperand);
             // only visit the LHS:
-            _safelyVisit(lhsCondition);
+            lhsCondition?.accept(this);
             return null;
           }
         }
@@ -1898,13 +1878,13 @@
 //                // report error on else block: !e! || true
 //                errorReporter.reportError(HintCode.DEAD_CODE, node.getRightOperand());
 //                // only visit the RHS:
-//                safelyVisit(rhsCondition);
+//                rhsCondition?.accept(this);
 //                return null;
 //              } else if (rhsResult == ValidResult.RESULT_FALSE && isAmpAmp) {
 //                // report error on if block: !e! && false
 //                errorReporter.reportError(HintCode.DEAD_CODE, node.getRightOperand());
 //                // only visit the RHS:
-//                safelyVisit(rhsCondition);
+//                rhsCondition?.accept(this);
 //                return null;
 //              }
 //            }
@@ -1928,7 +1908,7 @@
   @override
   Object visitConditionalExpression(ConditionalExpression node) {
     Expression conditionExpression = node.condition;
-    _safelyVisit(conditionExpression);
+    conditionExpression?.accept(this);
     if (!_isDebugConstant(conditionExpression)) {
       EvaluationResultImpl result =
           _getConstantBooleanValue(conditionExpression);
@@ -1937,13 +1917,13 @@
           // report error on else block: true ? 1 : !2!
           _errorReporter.reportErrorForNode(
               HintCode.DEAD_CODE, node.elseExpression);
-          _safelyVisit(node.thenExpression);
+          node.thenExpression?.accept(this);
           return null;
         } else {
           // report error on if block: false ? !1! : 2
           _errorReporter.reportErrorForNode(
               HintCode.DEAD_CODE, node.thenExpression);
-          _safelyVisit(node.elseExpression);
+          node.elseExpression?.accept(this);
           return null;
         }
       }
@@ -1954,7 +1934,7 @@
   @override
   Object visitIfStatement(IfStatement node) {
     Expression conditionExpression = node.condition;
-    _safelyVisit(conditionExpression);
+    conditionExpression?.accept(this);
     if (!_isDebugConstant(conditionExpression)) {
       EvaluationResultImpl result =
           _getConstantBooleanValue(conditionExpression);
@@ -1965,14 +1945,14 @@
           if (elseStatement != null) {
             _errorReporter.reportErrorForNode(
                 HintCode.DEAD_CODE, elseStatement);
-            _safelyVisit(node.thenStatement);
+            node.thenStatement?.accept(this);
             return null;
           }
         } else {
           // report error on if block: if (false) {!} else {}
           _errorReporter.reportErrorForNode(
               HintCode.DEAD_CODE, node.thenStatement);
-          _safelyVisit(node.elseStatement);
+          node.elseStatement?.accept(this);
           return null;
         }
       }
@@ -1994,8 +1974,8 @@
 
   @override
   Object visitTryStatement(TryStatement node) {
-    _safelyVisit(node.body);
-    _safelyVisit(node.finallyBlock);
+    node.body?.accept(this);
+    node.finallyBlock?.accept(this);
     NodeList<CatchClause> catchClauses = node.catchClauses;
     int numOfCatchClauses = catchClauses.length;
     List<DartType> visitedTypes = new List<DartType>();
@@ -2012,7 +1992,7 @@
             // this is equivalent to having a catch clause that doesn't have an
             // exception type, visit the block, but generate an error on any
             // following catch clauses (and don't visit them).
-            _safelyVisit(catchClause);
+            catchClause?.accept(this);
             if (i + 1 != numOfCatchClauses) {
               // this catch clause is not the last in the try statement
               CatchClause nextCatchClause = catchClauses[i + 1];
@@ -2039,12 +2019,12 @@
           }
           visitedTypes.add(currentType);
         }
-        _safelyVisit(catchClause);
+        catchClause?.accept(this);
       } else {
         // Found catch clause clause that doesn't have an exception type,
         // visit the block, but generate an error on any following catch clauses
         // (and don't visit them).
-        _safelyVisit(catchClause);
+        catchClause?.accept(this);
         if (i + 1 != numOfCatchClauses) {
           // this catch clause is not the last in the try statement
           CatchClause nextCatchClause = catchClauses[i + 1];
@@ -2063,7 +2043,7 @@
   @override
   Object visitWhileStatement(WhileStatement node) {
     Expression conditionExpression = node.condition;
-    _safelyVisit(conditionExpression);
+    conditionExpression?.accept(this);
     if (!_isDebugConstant(conditionExpression)) {
       EvaluationResultImpl result =
           _getConstantBooleanValue(conditionExpression);
@@ -2075,7 +2055,7 @@
         }
       }
     }
-    _safelyVisit(node.body);
+    node.body?.accept(this);
     return null;
   }
 
@@ -2090,7 +2070,7 @@
     int size = statements.length;
     for (int i = 0; i < size; i++) {
       Statement currentStatement = statements[i];
-      _safelyVisit(currentStatement);
+      currentStatement?.accept(this);
       bool returnOrBreakingStatement = currentStatement is ReturnStatement ||
           (currentStatement is BreakStatement &&
               currentStatement.label == null) ||
@@ -2162,17 +2142,6 @@
     }
     return false;
   }
-
-  /**
-   * If the given node is not `null`, visit this instance of the dead code verifier.
-   *
-   * @param node the node to be visited
-   */
-  void _safelyVisit(AstNode node) {
-    if (node != null) {
-      node.accept(this);
-    }
-  }
 }
 
 /**
@@ -2184,7 +2153,8 @@
  * This class must not assume that the [CompilationUnitElement] passed to it is
  * any more complete than a [COMPILATION_UNIT_ELEMENT].
  */
-class DeclarationResolver extends RecursiveAstVisitor<Object> {
+class DeclarationResolver extends RecursiveAstVisitor<Object>
+    with ExistingElementResolver {
   /**
    * The analysis context containing the sources to be analyzed.
    */
@@ -2197,11 +2167,6 @@
   Set<Element> _expectedElements;
 
   /**
-   * The compilation unit containing the AST nodes being visited.
-   */
-  CompilationUnitElementImpl _enclosingUnit;
-
-  /**
    * The function type alias containing the AST nodes being visited, or `null`
    * if we are not in the scope of a function type alias.
    */
@@ -2833,9 +2798,7 @@
  * The resulting AST must have everything resolved that would have been resolved
  * by a [DirectiveElementBuilder].
  */
-class DirectiveResolver extends SimpleAstVisitor {
-  CompilationUnitElementImpl _enclosingUnit;
-
+class DirectiveResolver extends SimpleAstVisitor with ExistingElementResolver {
   @override
   void visitCompilationUnit(CompilationUnit node) {
     _enclosingUnit = node.element;
@@ -3494,6 +3457,41 @@
 }
 
 /**
+ * A mixin for classes that use an existing element model to resolve a portion
+ * of an AST structure.
+ */
+class ExistingElementResolver {
+  /**
+   * The compilation unit containing the AST nodes being visited.
+   */
+  CompilationUnitElementImpl _enclosingUnit;
+
+  /**
+   * Throw an [ElementMismatchException] to report that the element model and the
+   * AST do not match. The [message] will have the path to the given [node]
+   * appended to it.
+   */
+  void _mismatch(String message, AstNode node) {
+    StringBuffer buffer = new StringBuffer();
+    buffer.write('Mismatch in ');
+    buffer.write(runtimeType);
+    buffer.write(' while resolving ');
+    buffer.writeln(_enclosingUnit?.source?.fullName);
+    buffer.writeln(message);
+    buffer.write('Path to root:');
+    String separator = ' ';
+    AstNode parent = node;
+    while (parent != null) {
+      buffer.write(separator);
+      buffer.write(parent.runtimeType.toString());
+      separator = ', ';
+      parent = parent.parent;
+    }
+    throw new ElementMismatchException(buffer.toString());
+  }
+}
+
+/**
  * Instances of the class `ExitDetector` determine whether the visited AST node is guaranteed
  * to terminate by executing a `return` statement, `throw` expression, `rethrow`
  * expression, or simple infinite loop such as `while(true)`.
@@ -6611,10 +6609,9 @@
       //
       return Namespace.EMPTY;
     }
-    HashMap<String, Element> definedNames =
-        _createExportMapping(exportedLibrary, new HashSet<LibraryElement>());
-    definedNames = _applyCombinators(definedNames, element.combinators);
-    return new Namespace(definedNames);
+    HashMap<String, Element> exportedNames = _getExportMapping(exportedLibrary);
+    exportedNames = _applyCombinators(exportedNames, element.combinators);
+    return new Namespace(exportedNames);
   }
 
   /**
@@ -6623,9 +6620,10 @@
    * @param library the library whose export namespace is to be created
    * @return the export namespace that was created
    */
-  Namespace createExportNamespaceForLibrary(LibraryElement library) =>
-      new Namespace(
-          _createExportMapping(library, new HashSet<LibraryElement>()));
+  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.
@@ -6642,11 +6640,10 @@
       //
       return Namespace.EMPTY;
     }
-    HashMap<String, Element> definedNames =
-        _createExportMapping(importedLibrary, new HashSet<LibraryElement>());
-    definedNames = _applyCombinators(definedNames, element.combinators);
-    definedNames = _applyPrefix(definedNames, element.prefix);
-    return new Namespace(definedNames);
+    HashMap<String, Element> exportedNames = _getExportMapping(importedLibrary);
+    exportedNames = _applyCombinators(exportedNames, element.combinators);
+    exportedNames = _applyPrefix(exportedNames, element.prefix);
+    return new Namespace(exportedNames);
   }
 
   /**
@@ -6770,7 +6767,7 @@
    *          be added by another library
    * @return the mapping table that was created
    */
-  HashMap<String, Element> _createExportMapping(
+  HashMap<String, Element> _computeExportMapping(
       LibraryElement library, HashSet<LibraryElement> visitedElements) {
     visitedElements.add(library);
     try {
@@ -6784,7 +6781,7 @@
           // valid library.
           //
           HashMap<String, Element> exportedNames =
-              _createExportMapping(exportedLibrary, visitedElements);
+              _computeExportMapping(exportedLibrary, visitedElements);
           exportedNames = _applyCombinators(exportedNames, element.combinators);
           definedNames.addAll(exportedNames);
         }
@@ -6799,6 +6796,20 @@
     }
   }
 
+  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].
@@ -7682,13 +7693,13 @@
         identical(parent, _enclosingFunctionTypeAlias)) {
       return null;
     }
-    safelyVisit(node.name);
-    safelyVisit(node.constructorName);
+    node.name?.accept(this);
+    node.constructorName?.accept(this);
     Element element = node.element;
     if (element is ExecutableElement) {
       InferenceContext.setType(node.arguments, element.type);
     }
-    safelyVisit(node.arguments);
+    node.arguments?.accept(this);
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
     ElementAnnotationImpl elementAnnotationImpl = node.elementAnnotation;
@@ -7766,14 +7777,14 @@
 
   @override
   Object visitAssignmentExpression(AssignmentExpression node) {
-    safelyVisit(node.leftHandSide);
+    node.leftHandSide?.accept(this);
     TokenType operator = node.operator.type;
     if (operator == TokenType.EQ ||
         operator == TokenType.QUESTION_QUESTION_EQ) {
       InferenceContext.setType(
           node.rightHandSide, node.leftHandSide.staticType);
     }
-    safelyVisit(node.rightHandSide);
+    node.rightHandSide?.accept(this);
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
     return null;
@@ -7798,7 +7809,7 @@
     Expression leftOperand = node.leftOperand;
     Expression rightOperand = node.rightOperand;
     if (operatorType == TokenType.AMPERSAND_AMPERSAND) {
-      safelyVisit(leftOperand);
+      leftOperand?.accept(this);
       if (rightOperand != null) {
         _overrideManager.enterScope();
         try {
@@ -7821,7 +7832,7 @@
         }
       }
     } else if (operatorType == TokenType.BAR_BAR) {
-      safelyVisit(leftOperand);
+      leftOperand?.accept(this);
       if (rightOperand != null) {
         _overrideManager.enterScope();
         try {
@@ -7838,8 +7849,8 @@
         InferenceContext.setTypeFromNode(leftOperand, node);
         InferenceContext.setTypeFromNode(rightOperand, node);
       }
-      safelyVisit(leftOperand);
-      safelyVisit(rightOperand);
+      leftOperand?.accept(this);
+      rightOperand?.accept(this);
     }
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
@@ -7993,7 +8004,7 @@
   @override
   Object visitConditionalExpression(ConditionalExpression node) {
     Expression condition = node.condition;
-    safelyVisit(condition);
+    condition?.accept(this);
     Expression thenExpression = node.thenExpression;
     if (thenExpression != null) {
       _overrideManager.enterScope();
@@ -8075,7 +8086,7 @@
     //
     FieldElement fieldElement = enclosingClass.getField(node.fieldName.name);
     InferenceContext.setType(node.expression, fieldElement?.type);
-    safelyVisit(node.expression);
+    node.expression?.accept(this);
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
     return null;
@@ -8226,9 +8237,9 @@
       InferenceContext.setType(
           iterable, targetType.instantiate([loopVariable.type.type]));
     }
-    safelyVisit(iterable);
-    safelyVisit(loopVariable);
-    safelyVisit(identifier);
+    iterable?.accept(this);
+    loopVariable?.accept(this);
+    identifier?.accept(this);
     Statement body = node.body;
     if (body != null) {
       _overrideManager.enterScope();
@@ -8278,9 +8289,9 @@
 
   @override
   void visitForStatementInScope(ForStatement node) {
-    safelyVisit(node.variables);
-    safelyVisit(node.initialization);
-    safelyVisit(node.condition);
+    node.variables?.accept(this);
+    node.initialization?.accept(this);
+    node.condition?.accept(this);
     _overrideManager.enterScope();
     try {
       _propagateTrueState(node.condition);
@@ -8350,11 +8361,11 @@
 
   @override
   Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
-    safelyVisit(node.function);
+    node.function?.accept(this);
     node.accept(elementResolver);
     _inferFunctionExpressionsParametersTypes(node.argumentList);
     _inferArgumentTypesFromContext(node);
-    safelyVisit(node.argumentList);
+    node.argumentList?.accept(this);
     node.accept(typeAnalyzer);
     return null;
   }
@@ -8387,7 +8398,7 @@
   @override
   Object visitIfStatement(IfStatement node) {
     Expression condition = node.condition;
-    safelyVisit(condition);
+    condition?.accept(this);
     Map<VariableElement, DartType> thenOverrides =
         new HashMap<VariableElement, DartType>();
     Statement thenStatement = node.thenStatement;
@@ -8467,12 +8478,12 @@
         }
       }
     }
-    safelyVisit(node.constructorName);
+    node.constructorName?.accept(this);
     FunctionType constructorType = node.constructorName.staticElement?.type;
     if (constructorType != null) {
       InferenceContext.setType(node.argumentList, constructorType);
     }
-    safelyVisit(node.argumentList);
+    node.argumentList?.accept(this);
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
     return null;
@@ -8566,12 +8577,12 @@
     // We visit the target and argument list, but do not visit the method name
     // because it needs to be visited in the context of the invocation.
     //
-    safelyVisit(node.target);
-    safelyVisit(node.typeArguments);
+    node.target?.accept(this);
+    node.typeArguments?.accept(this);
     node.accept(elementResolver);
     _inferFunctionExpressionsParametersTypes(node.argumentList);
     _inferArgumentTypesFromContext(node);
-    safelyVisit(node.argumentList);
+    node.argumentList?.accept(this);
     node.accept(typeAnalyzer);
     return null;
   }
@@ -8602,7 +8613,7 @@
     // We visit the prefix, but do not visit the identifier because it needs to
     // be visited in the context of the prefix.
     //
-    safelyVisit(node.prefix);
+    node.prefix?.accept(this);
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
     return null;
@@ -8614,7 +8625,7 @@
     // We visit the target, but do not visit the property name because it needs
     // to be visited in the context of the property access node.
     //
-    safelyVisit(node.target);
+    node.target?.accept(this);
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
     return null;
@@ -8629,7 +8640,7 @@
     // invocation.
     //
     InferenceContext.setType(node.argumentList, node.staticElement?.type);
-    safelyVisit(node.argumentList);
+    node.argumentList?.accept(this);
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
     return null;
@@ -8663,7 +8674,7 @@
     // invocation.
     //
     InferenceContext.setType(node.argumentList, node.staticElement?.type);
-    safelyVisit(node.argumentList);
+    node.argumentList?.accept(this);
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
     return null;
@@ -8748,7 +8759,7 @@
     try {
       _implicitLabelScope = _implicitLabelScope.nest(node);
       Expression condition = node.condition;
-      safelyVisit(condition);
+      condition?.accept(this);
       Statement body = node.body;
       if (body != null) {
         _overrideManager.enterScope();
@@ -9680,17 +9691,6 @@
         source, token.offset, token.length, errorCode, arguments));
   }
 
-  /**
-   * Visit the given AST node if it is not null.
-   *
-   * @param node the node to be visited
-   */
-  void safelyVisit(AstNode node) {
-    if (node != null) {
-      node.accept(this);
-    }
-  }
-
   @override
   Object visitBlock(Block node) {
     Scope outerScope = nameScope;
@@ -9768,16 +9768,16 @@
   }
 
   void visitClassDeclarationInScope(ClassDeclaration node) {
-    safelyVisit(node.name);
-    safelyVisit(node.typeParameters);
-    safelyVisit(node.extendsClause);
-    safelyVisit(node.withClause);
-    safelyVisit(node.implementsClause);
-    safelyVisit(node.nativeClause);
+    node.name?.accept(this);
+    node.typeParameters?.accept(this);
+    node.extendsClause?.accept(this);
+    node.withClause?.accept(this);
+    node.implementsClause?.accept(this);
+    node.nativeClause?.accept(this);
   }
 
   void visitClassMembersInScope(ClassDeclaration node) {
-    safelyVisit(node.documentationComment);
+    node.documentationComment?.accept(this);
     node.metadata.accept(this);
     node.members.accept(this);
   }
@@ -9843,7 +9843,7 @@
     try {
       _implicitLabelScope = _implicitLabelScope.nest(node);
       visitStatementInScope(node.body);
-      safelyVisit(node.condition);
+      node.condition?.accept(this);
     } finally {
       _implicitLabelScope = outerImplicitScope;
     }
@@ -9877,7 +9877,7 @@
   }
 
   void visitEnumMembersInScope(EnumDeclaration node) {
-    safelyVisit(node.documentationComment);
+    node.documentationComment?.accept(this);
     node.metadata.accept(this);
     node.constants.accept(this);
   }
@@ -9909,9 +9909,9 @@
     // We visit the iterator before the loop variable because the loop variable
     // cannot be in scope while visiting the iterator.
     //
-    safelyVisit(node.identifier);
-    safelyVisit(node.iterable);
-    safelyVisit(node.loopVariable);
+    node.identifier?.accept(this);
+    node.iterable?.accept(this);
+    node.loopVariable?.accept(this);
     visitStatementInScope(node.body);
   }
 
@@ -9955,9 +9955,9 @@
    * @param node the statement to be visited
    */
   void visitForStatementInScope(ForStatement node) {
-    safelyVisit(node.variables);
-    safelyVisit(node.initialization);
-    safelyVisit(node.condition);
+    node.variables?.accept(this);
+    node.initialization?.accept(this);
+    node.condition?.accept(this);
     node.updaters.accept(this);
     visitStatementInScope(node.body);
   }
@@ -10067,7 +10067,7 @@
 
   @override
   Object visitIfStatement(IfStatement node) {
-    safelyVisit(node.condition);
+    node.condition?.accept(this);
     visitStatementInScope(node.thenStatement);
     visitStatementInScope(node.elseStatement);
     return null;
@@ -10191,7 +10191,7 @@
 
   @override
   Object visitWhileStatement(WhileStatement node) {
-    safelyVisit(node.condition);
+    node.condition?.accept(this);
     ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
     try {
       _implicitLabelScope = _implicitLabelScope.nest(node);
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
index d8d44f4..6983cc8 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
@@ -869,6 +869,28 @@
           parameters,
           body);
 
+  static MethodDeclaration methodDeclaration4(
+          {bool external: false,
+          Keyword modifier,
+          TypeName returnType,
+          Keyword property,
+          bool operator: false,
+          String name,
+          FormalParameterList parameters,
+          FunctionBody body}) =>
+      new MethodDeclaration(
+          null,
+          null,
+          external ? TokenFactory.tokenFromKeyword(Keyword.EXTERNAL) : null,
+          modifier == null ? null : TokenFactory.tokenFromKeyword(modifier),
+          returnType,
+          property == null ? null : TokenFactory.tokenFromKeyword(property),
+          operator ? TokenFactory.tokenFromKeyword(Keyword.OPERATOR) : null,
+          identifier3(name),
+          null,
+          parameters,
+          body);
+
   static MethodInvocation methodInvocation(Expression target, String methodName,
           [List<Expression> arguments,
           TokenType operator = TokenType.PERIOD]) =>
diff --git a/pkg/analyzer/lib/src/generated/utilities_general.dart b/pkg/analyzer/lib/src/generated/utilities_general.dart
index e0600dc..b9dca93 100644
--- a/pkg/analyzer/lib/src/generated/utilities_general.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_general.dart
@@ -145,7 +145,7 @@
    * Make this the current tag for the isolate, run [f], and restore the
    * previous tag. Returns the result of invoking [f].
    */
-  makeCurrentWhile(f());
+  dynamic/*=E*/ makeCurrentWhile/*<E>*/(dynamic/*=E*/ f());
 
   /**
    * Reset the total time tracked by all [PerformanceTag]s to zero.
@@ -206,7 +206,7 @@
     return previous;
   }
 
-  makeCurrentWhile(f()) {
+  dynamic/*=E*/ makeCurrentWhile/*<E>*/(dynamic/*=E*/ f()) {
     PerformanceTag prevTag = makeCurrent();
     try {
       return f();
diff --git a/pkg/analyzer/lib/src/plugin/options_plugin.dart b/pkg/analyzer/lib/src/plugin/options_plugin.dart
index 6fba649..9a4fc01 100644
--- a/pkg/analyzer/lib/src/plugin/options_plugin.dart
+++ b/pkg/analyzer/lib/src/plugin/options_plugin.dart
@@ -34,11 +34,13 @@
 
   /// All contributed options processors.
   List<OptionsProcessor> get optionsProcessors =>
-      optionsProcessorExtensionPoint?.extensions ?? const [];
+      optionsProcessorExtensionPoint?.extensions as List<OptionsProcessor> ??
+      const <OptionsProcessor>[];
 
   /// All contributed options validators.
   List<OptionsValidator> get optionsValidators =>
-      optionsValidatorExtensionPoint?.extensions ?? const [];
+      optionsValidatorExtensionPoint?.extensions as List<OptionsValidator> ??
+      const <OptionsValidator>[];
 
   @override
   String get uniqueIdentifier => UNIQUE_IDENTIFIER;
diff --git a/pkg/analyzer/lib/src/services/lint.dart b/pkg/analyzer/lib/src/services/lint.dart
index 3eea1b7..3b36457 100644
--- a/pkg/analyzer/lib/src/services/lint.dart
+++ b/pkg/analyzer/lib/src/services/lint.dart
@@ -25,7 +25,8 @@
 /// Return lints associated with this [context], or an empty list if there are
 /// none.
 List<Linter> getLints(AnalysisContext context) =>
-    context.getConfigurationData(CONFIGURED_LINTS_KEY) ?? _noLints;
+    context.getConfigurationData(CONFIGURED_LINTS_KEY) as List<Linter> ??
+    _noLints;
 
 /// Associate these [lints] with the given [context].
 void setLints(AnalysisContext context, List<Linter> lints) {
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index bf4a78a..e8f16bf 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -11,6 +11,19 @@
 import 'idl.dart' as idl;
 import 'dart:convert' as convert;
 
+class _CacheSourceKindReader extends fb.Reader<idl.CacheSourceKind> {
+  const _CacheSourceKindReader() : super();
+
+  @override
+  int get size => 1;
+
+  @override
+  idl.CacheSourceKind read(fb.BufferPointer bp) {
+    int index = const fb.Uint8Reader().read(bp);
+    return index < idl.CacheSourceKind.values.length ? idl.CacheSourceKind.values[index] : idl.CacheSourceKind.library;
+  }
+}
+
 class _IndexNameKindReader extends fb.Reader<idl.IndexNameKind> {
   const _IndexNameKindReader() : super();
 
@@ -115,6 +128,174 @@
   }
 }
 
+class CacheSourceContentBuilder extends Object with _CacheSourceContentMixin implements idl.CacheSourceContent {
+  bool _finished = false;
+
+  List<String> _exportedUris;
+  List<String> _importedUris;
+  idl.CacheSourceKind _kind;
+  List<String> _partUris;
+
+  @override
+  List<String> get exportedUris => _exportedUris ??= <String>[];
+
+  /**
+   * The list of exported URIs, e.g. `dart:core`, or `foo/bar.dart`,
+   * or `package:foo/bar.dart`.  Empty if [kind] is [CacheSourceKind.part].
+   */
+  void set exportedUris(List<String> _value) {
+    assert(!_finished);
+    _exportedUris = _value;
+  }
+
+  @override
+  List<String> get importedUris => _importedUris ??= <String>[];
+
+  /**
+   * The list of explicitly imported URIs, e.g. `dart:core`, or `foo/bar.dart`,
+   * or `package:foo/bar.dart`.  Empty if [kind] is [CacheSourceKind.part].
+   */
+  void set importedUris(List<String> _value) {
+    assert(!_finished);
+    _importedUris = _value;
+  }
+
+  @override
+  idl.CacheSourceKind get kind => _kind ??= idl.CacheSourceKind.library;
+
+  /**
+   * The kind of the source.
+   */
+  void set kind(idl.CacheSourceKind _value) {
+    assert(!_finished);
+    _kind = _value;
+  }
+
+  @override
+  List<String> get partUris => _partUris ??= <String>[];
+
+  /**
+   * The list of part URIs, e.g. `foo/bar.dart`.  Empty if [kind] is
+   * [CacheSourceKind.part].
+   */
+  void set partUris(List<String> _value) {
+    assert(!_finished);
+    _partUris = _value;
+  }
+
+  CacheSourceContentBuilder({List<String> exportedUris, List<String> importedUris, idl.CacheSourceKind kind, List<String> partUris})
+    : _exportedUris = exportedUris,
+      _importedUris = importedUris,
+      _kind = kind,
+      _partUris = partUris;
+
+  List<int> toBuffer() {
+    fb.Builder fbBuilder = new fb.Builder();
+    return fbBuilder.finish(finish(fbBuilder), "CaSS");
+  }
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    assert(!_finished);
+    _finished = true;
+    fb.Offset offset_exportedUris;
+    fb.Offset offset_importedUris;
+    fb.Offset offset_partUris;
+    if (!(_exportedUris == null || _exportedUris.isEmpty)) {
+      offset_exportedUris = fbBuilder.writeList(_exportedUris.map((b) => fbBuilder.writeString(b)).toList());
+    }
+    if (!(_importedUris == null || _importedUris.isEmpty)) {
+      offset_importedUris = fbBuilder.writeList(_importedUris.map((b) => fbBuilder.writeString(b)).toList());
+    }
+    if (!(_partUris == null || _partUris.isEmpty)) {
+      offset_partUris = fbBuilder.writeList(_partUris.map((b) => fbBuilder.writeString(b)).toList());
+    }
+    fbBuilder.startTable();
+    if (offset_exportedUris != null) {
+      fbBuilder.addOffset(2, offset_exportedUris);
+    }
+    if (offset_importedUris != null) {
+      fbBuilder.addOffset(1, offset_importedUris);
+    }
+    if (_kind != null && _kind != idl.CacheSourceKind.library) {
+      fbBuilder.addUint8(0, _kind.index);
+    }
+    if (offset_partUris != null) {
+      fbBuilder.addOffset(3, offset_partUris);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+idl.CacheSourceContent readCacheSourceContent(List<int> buffer) {
+  fb.BufferPointer rootRef = new fb.BufferPointer.fromBytes(buffer);
+  return const _CacheSourceContentReader().read(rootRef);
+}
+
+class _CacheSourceContentReader extends fb.TableReader<_CacheSourceContentImpl> {
+  const _CacheSourceContentReader();
+
+  @override
+  _CacheSourceContentImpl createObject(fb.BufferPointer bp) => new _CacheSourceContentImpl(bp);
+}
+
+class _CacheSourceContentImpl extends Object with _CacheSourceContentMixin implements idl.CacheSourceContent {
+  final fb.BufferPointer _bp;
+
+  _CacheSourceContentImpl(this._bp);
+
+  List<String> _exportedUris;
+  List<String> _importedUris;
+  idl.CacheSourceKind _kind;
+  List<String> _partUris;
+
+  @override
+  List<String> get exportedUris {
+    _exportedUris ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 2, const <String>[]);
+    return _exportedUris;
+  }
+
+  @override
+  List<String> get importedUris {
+    _importedUris ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 1, const <String>[]);
+    return _importedUris;
+  }
+
+  @override
+  idl.CacheSourceKind get kind {
+    _kind ??= const _CacheSourceKindReader().vTableGet(_bp, 0, idl.CacheSourceKind.library);
+    return _kind;
+  }
+
+  @override
+  List<String> get partUris {
+    _partUris ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 3, const <String>[]);
+    return _partUris;
+  }
+}
+
+abstract class _CacheSourceContentMixin implements idl.CacheSourceContent {
+  @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (exportedUris.isNotEmpty) _result["exportedUris"] = exportedUris;
+    if (importedUris.isNotEmpty) _result["importedUris"] = importedUris;
+    if (kind != idl.CacheSourceKind.library) _result["kind"] = kind.toString().split('.')[1];
+    if (partUris.isNotEmpty) _result["partUris"] = partUris;
+    return _result;
+  }
+
+  @override
+  Map<String, Object> toMap() => {
+    "exportedUris": exportedUris,
+    "importedUris": importedUris,
+    "kind": kind,
+    "partUris": partUris,
+  };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
+}
+
 class CodeRangeBuilder extends Object with _CodeRangeMixin implements idl.CodeRange {
   bool _finished = false;
 
@@ -1905,10 +2086,10 @@
   List<int> _usedElementLengths;
   List<int> _usedElementOffsets;
   List<int> _usedElements;
+  List<bool> _usedNameIsQualifiedFlags;
   List<idl.IndexRelationKind> _usedNameKinds;
   List<int> _usedNameOffsets;
   List<int> _usedNames;
-  List<bool> _usedNameIsQualifiedFlags;
 
   @override
   List<idl.IndexNameKind> get definedNameKinds => _definedNameKinds ??= <idl.IndexNameKind>[];
@@ -2025,6 +2206,18 @@
   }
 
   @override
+  List<bool> get usedNameIsQualifiedFlags => _usedNameIsQualifiedFlags ??= <bool>[];
+
+  /**
+   * Each item of this list is the `true` if the corresponding name usage
+   * is qualified with some prefix.
+   */
+  void set usedNameIsQualifiedFlags(List<bool> _value) {
+    assert(!_finished);
+    _usedNameIsQualifiedFlags = _value;
+  }
+
+  @override
   List<idl.IndexRelationKind> get usedNameKinds => _usedNameKinds ??= <idl.IndexRelationKind>[];
 
   /**
@@ -2062,19 +2255,7 @@
     _usedNames = _value;
   }
 
-  @override
-  List<bool> get usedNameIsQualifiedFlags => _usedNameIsQualifiedFlags ??= <bool>[];
-
-  /**
-   * Each item of this list is the `true` if the corresponding name usage
-   * is qualified with some prefix.
-   */
-  void set usedNameIsQualifiedFlags(List<bool> _value) {
-    assert(!_finished);
-    _usedNameIsQualifiedFlags = _value;
-  }
-
-  UnitIndexBuilder({List<idl.IndexNameKind> definedNameKinds, List<int> definedNameOffsets, List<int> definedNames, int unit, List<bool> usedElementIsQualifiedFlags, List<idl.IndexRelationKind> usedElementKinds, List<int> usedElementLengths, List<int> usedElementOffsets, List<int> usedElements, List<idl.IndexRelationKind> usedNameKinds, List<int> usedNameOffsets, List<int> usedNames, List<bool> usedNameIsQualifiedFlags})
+  UnitIndexBuilder({List<idl.IndexNameKind> definedNameKinds, List<int> definedNameOffsets, List<int> definedNames, int unit, List<bool> usedElementIsQualifiedFlags, List<idl.IndexRelationKind> usedElementKinds, List<int> usedElementLengths, List<int> usedElementOffsets, List<int> usedElements, List<bool> usedNameIsQualifiedFlags, List<idl.IndexRelationKind> usedNameKinds, List<int> usedNameOffsets, List<int> usedNames})
     : _definedNameKinds = definedNameKinds,
       _definedNameOffsets = definedNameOffsets,
       _definedNames = definedNames,
@@ -2084,10 +2265,10 @@
       _usedElementLengths = usedElementLengths,
       _usedElementOffsets = usedElementOffsets,
       _usedElements = usedElements,
+      _usedNameIsQualifiedFlags = usedNameIsQualifiedFlags,
       _usedNameKinds = usedNameKinds,
       _usedNameOffsets = usedNameOffsets,
-      _usedNames = usedNames,
-      _usedNameIsQualifiedFlags = usedNameIsQualifiedFlags;
+      _usedNames = usedNames;
 
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
@@ -2100,10 +2281,10 @@
     fb.Offset offset_usedElementLengths;
     fb.Offset offset_usedElementOffsets;
     fb.Offset offset_usedElements;
+    fb.Offset offset_usedNameIsQualifiedFlags;
     fb.Offset offset_usedNameKinds;
     fb.Offset offset_usedNameOffsets;
     fb.Offset offset_usedNames;
-    fb.Offset offset_usedNameIsQualifiedFlags;
     if (!(_definedNameKinds == null || _definedNameKinds.isEmpty)) {
       offset_definedNameKinds = fbBuilder.writeListUint8(_definedNameKinds.map((b) => b.index).toList());
     }
@@ -2128,6 +2309,9 @@
     if (!(_usedElements == null || _usedElements.isEmpty)) {
       offset_usedElements = fbBuilder.writeListUint32(_usedElements);
     }
+    if (!(_usedNameIsQualifiedFlags == null || _usedNameIsQualifiedFlags.isEmpty)) {
+      offset_usedNameIsQualifiedFlags = fbBuilder.writeListBool(_usedNameIsQualifiedFlags);
+    }
     if (!(_usedNameKinds == null || _usedNameKinds.isEmpty)) {
       offset_usedNameKinds = fbBuilder.writeListUint8(_usedNameKinds.map((b) => b.index).toList());
     }
@@ -2137,9 +2321,6 @@
     if (!(_usedNames == null || _usedNames.isEmpty)) {
       offset_usedNames = fbBuilder.writeListUint32(_usedNames);
     }
-    if (!(_usedNameIsQualifiedFlags == null || _usedNameIsQualifiedFlags.isEmpty)) {
-      offset_usedNameIsQualifiedFlags = fbBuilder.writeListBool(_usedNameIsQualifiedFlags);
-    }
     fbBuilder.startTable();
     if (offset_definedNameKinds != null) {
       fbBuilder.addOffset(6, offset_definedNameKinds);
@@ -2168,6 +2349,9 @@
     if (offset_usedElements != null) {
       fbBuilder.addOffset(3, offset_usedElements);
     }
+    if (offset_usedNameIsQualifiedFlags != null) {
+      fbBuilder.addOffset(12, offset_usedNameIsQualifiedFlags);
+    }
     if (offset_usedNameKinds != null) {
       fbBuilder.addOffset(10, offset_usedNameKinds);
     }
@@ -2177,9 +2361,6 @@
     if (offset_usedNames != null) {
       fbBuilder.addOffset(8, offset_usedNames);
     }
-    if (offset_usedNameIsQualifiedFlags != null) {
-      fbBuilder.addOffset(12, offset_usedNameIsQualifiedFlags);
-    }
     return fbBuilder.endTable();
   }
 }
@@ -2205,10 +2386,10 @@
   List<int> _usedElementLengths;
   List<int> _usedElementOffsets;
   List<int> _usedElements;
+  List<bool> _usedNameIsQualifiedFlags;
   List<idl.IndexRelationKind> _usedNameKinds;
   List<int> _usedNameOffsets;
   List<int> _usedNames;
-  List<bool> _usedNameIsQualifiedFlags;
 
   @override
   List<idl.IndexNameKind> get definedNameKinds {
@@ -2265,6 +2446,12 @@
   }
 
   @override
+  List<bool> get usedNameIsQualifiedFlags {
+    _usedNameIsQualifiedFlags ??= const fb.BoolListReader().vTableGet(_bp, 12, const <bool>[]);
+    return _usedNameIsQualifiedFlags;
+  }
+
+  @override
   List<idl.IndexRelationKind> get usedNameKinds {
     _usedNameKinds ??= const fb.ListReader<idl.IndexRelationKind>(const _IndexRelationKindReader()).vTableGet(_bp, 10, const <idl.IndexRelationKind>[]);
     return _usedNameKinds;
@@ -2281,12 +2468,6 @@
     _usedNames ??= const fb.Uint32ListReader().vTableGet(_bp, 8, const <int>[]);
     return _usedNames;
   }
-
-  @override
-  List<bool> get usedNameIsQualifiedFlags {
-    _usedNameIsQualifiedFlags ??= const fb.BoolListReader().vTableGet(_bp, 12, const <bool>[]);
-    return _usedNameIsQualifiedFlags;
-  }
 }
 
 abstract class _UnitIndexMixin implements idl.UnitIndex {
@@ -2302,10 +2483,10 @@
     if (usedElementLengths.isNotEmpty) _result["usedElementLengths"] = usedElementLengths;
     if (usedElementOffsets.isNotEmpty) _result["usedElementOffsets"] = usedElementOffsets;
     if (usedElements.isNotEmpty) _result["usedElements"] = usedElements;
+    if (usedNameIsQualifiedFlags.isNotEmpty) _result["usedNameIsQualifiedFlags"] = usedNameIsQualifiedFlags;
     if (usedNameKinds.isNotEmpty) _result["usedNameKinds"] = usedNameKinds.map((_value) => _value.toString().split('.')[1]).toList();
     if (usedNameOffsets.isNotEmpty) _result["usedNameOffsets"] = usedNameOffsets;
     if (usedNames.isNotEmpty) _result["usedNames"] = usedNames;
-    if (usedNameIsQualifiedFlags.isNotEmpty) _result["usedNameIsQualifiedFlags"] = usedNameIsQualifiedFlags;
     return _result;
   }
 
@@ -2320,10 +2501,10 @@
     "usedElementLengths": usedElementLengths,
     "usedElementOffsets": usedElementOffsets,
     "usedElements": usedElements,
+    "usedNameIsQualifiedFlags": usedNameIsQualifiedFlags,
     "usedNameKinds": usedNameKinds,
     "usedNameOffsets": usedNameOffsets,
     "usedNames": usedNames,
-    "usedNameIsQualifiedFlags": usedNameIsQualifiedFlags,
   };
 
   @override
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index a653a52..9c6cf83 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -7,6 +7,15 @@
 
 
 /**
+ * Kind of a source in the cache.
+ */
+enum CacheSourceKind : byte {
+  library,
+
+  part
+}
+
+/**
  * Enum used to indicate the kind of a name in index.
  */
 enum IndexNameKind : byte {
@@ -106,6 +115,11 @@
   constructor,
 
   /**
+   * The synthetic field element.
+   */
+  field,
+
+  /**
    * The synthetic getter of a property introducing element.
    */
   getter,
@@ -560,6 +574,34 @@
 }
 
 /**
+ * Information about a source that depends only on its content.
+ */
+table CacheSourceContent {
+  /**
+   * The list of exported URIs, e.g. `dart:core`, or `foo/bar.dart`,
+   * or `package:foo/bar.dart`.  Empty if [kind] is [CacheSourceKind.part].
+   */
+  exportedUris:[string] (id: 2);
+
+  /**
+   * The list of explicitly imported URIs, e.g. `dart:core`, or `foo/bar.dart`,
+   * or `package:foo/bar.dart`.  Empty if [kind] is [CacheSourceKind.part].
+   */
+  importedUris:[string] (id: 1);
+
+  /**
+   * The kind of the source.
+   */
+  kind:CacheSourceKind (id: 0);
+
+  /**
+   * The list of part URIs, e.g. `foo/bar.dart`.  Empty if [kind] is
+   * [CacheSourceKind.part].
+   */
+  partUris:[string] (id: 3);
+}
+
+/**
  * Information about an element code range.
  */
 table CodeRange {
@@ -1017,6 +1059,12 @@
   usedElements:[uint] (id: 3);
 
   /**
+   * Each item of this list is the `true` if the corresponding name usage
+   * is qualified with some prefix.
+   */
+  usedNameIsQualifiedFlags:[ubyte] (id: 12);
+
+  /**
    * Each item of this list is the kind of the name usage.
    */
   usedNameKinds:[IndexRelationKind] (id: 10);
@@ -1033,12 +1081,6 @@
    * quickly find name uses in this [UnitIndex].
    */
   usedNames:[uint] (id: 8);
-
-  /**
-   * Each item of this list is the `true` if the corresponding name usage
-   * is qualified with some prefix.
-   */
-  usedNameIsQualifiedFlags:[ubyte] (id: 12);
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index f15ba03..4453056 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -53,6 +53,47 @@
 const informative = null;
 
 /**
+ * Information about a source that depends only on its content.
+ */
+@TopLevel('CaSS')
+abstract class CacheSourceContent extends base.SummaryClass {
+  factory CacheSourceContent.fromBuffer(List<int> buffer) =>
+      generated.readCacheSourceContent(buffer);
+
+  /**
+   * The list of exported URIs, e.g. `dart:core`, or `foo/bar.dart`,
+   * or `package:foo/bar.dart`.  Empty if [kind] is [CacheSourceKind.part].
+   */
+  @Id(2)
+  List<String> get exportedUris;
+
+  /**
+   * The list of explicitly imported URIs, e.g. `dart:core`, or `foo/bar.dart`,
+   * or `package:foo/bar.dart`.  Empty if [kind] is [CacheSourceKind.part].
+   */
+  @Id(1)
+  List<String> get importedUris;
+
+  /**
+   * The kind of the source.
+   */
+  @Id(0)
+  CacheSourceKind get kind;
+
+  /**
+   * The list of part URIs, e.g. `foo/bar.dart`.  Empty if [kind] is
+   * [CacheSourceKind.part].
+   */
+  @Id(3)
+  List<String> get partUris;
+}
+
+/**
+ * Kind of a source in the cache.
+ */
+enum CacheSourceKind { library, part }
+
+/**
  * Information about an element code range.
  */
 abstract class CodeRange extends base.SummaryClass {
@@ -265,6 +306,11 @@
   constructor,
 
   /**
+   * The synthetic field element.
+   */
+  field,
+
+  /**
    * The synthetic getter of a property introducing element.
    */
   getter,
@@ -773,6 +819,13 @@
   List<int> get usedElements;
 
   /**
+   * Each item of this list is the `true` if the corresponding name usage
+   * is qualified with some prefix.
+   */
+  @Id(12)
+  List<bool> get usedNameIsQualifiedFlags;
+
+  /**
    * Each item of this list is the kind of the name usage.
    */
   @Id(10)
@@ -792,13 +845,6 @@
    */
   @Id(8)
   List<int> get usedNames;
-
-  /**
-   * Each item of this list is the `true` if the corresponding name usage
-   * is qualified with some prefix.
-   */
-  @Id(12)
-  List<bool> get usedNameIsQualifiedFlags;
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/summary/incremental_cache.dart b/pkg/analyzer/lib/src/summary/incremental_cache.dart
new file mode 100644
index 0000000..9900773
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary/incremental_cache.dart
@@ -0,0 +1,420 @@
+// 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' show UTF8;
+import 'dart:core' hide Resource;
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary/summarize_elements.dart';
+import 'package:crypto/crypto.dart';
+
+/**
+ * Storage for cache data.
+ */
+abstract class CacheStorage {
+  /**
+   * Return bytes for the given [key], `null` if [key] is not in the storage.
+   */
+  List<int> get(String key);
+
+  /**
+   * Associate the [key] with the given [bytes].
+   *
+   * If the [key] was already in the storage, its associated value is changed.
+   * Otherwise the key-value pair is added to the storage.
+   *
+   * It is not guaranteed that data will always be accessible using [get], in
+   * some implementations association may silently fail or become inaccessible
+   * after some time.
+   */
+  void put(String key, List<int> bytes);
+}
+
+/**
+ * A [Folder] based implementation of [CacheStorage].
+ */
+class FolderCacheStorage implements CacheStorage {
+  /**
+   * The folder to read and write files.
+   */
+  final Folder folder;
+
+  /**
+   * To ensure that operations of writing files are atomic we create a temporary
+   * file with this name in the [folder] and then rename it once we are
+   * done writing.
+   */
+  final String tempFileName;
+
+  FolderCacheStorage(this.folder, this.tempFileName);
+
+  @override
+  List<int> get(String key) {
+    Resource file = folder.getChild(key);
+    if (file is File) {
+      try {
+        return file.readAsBytesSync();
+      } on FileSystemException {}
+    }
+    return null;
+  }
+
+  @override
+  void put(String key, List<int> bytes) {
+    String absPath = folder.getChild(key).path;
+    File tempFile = folder.getChild(tempFileName);
+    tempFile.writeAsBytesSync(bytes);
+    try {
+      tempFile.renameSync(absPath);
+    } catch (e) {}
+  }
+}
+
+/**
+ * Cache of information to support incremental analysis.
+ *
+ * Note that currently this class is not intended for interactive use.
+ */
+class IncrementalCache {
+  /**
+   * The storage for the cache data.
+   */
+  final CacheStorage storage;
+
+  /**
+   * The context in which this cache is used.
+   */
+  final AnalysisContext context;
+
+  /**
+   * Opaque data that reflects the current configuration, such as the [context]
+   * options, and is mixed into the hashes.
+   */
+  final List<int> configSalt;
+
+  final Map<Source, CacheSourceContent> _sourceContentMap =
+      <Source, CacheSourceContent>{};
+  final Map<Source, List<Source>> _libraryClosureMap = <Source, List<Source>>{};
+  final Map<Source, List<int>> _libraryClosureHashMap = <Source, List<int>>{};
+  final Map<Source, List<int>> _sourceContentHashMap = <Source, List<int>>{};
+
+  /**
+   * Mapping from a library closure key to its [PackageBundle].
+   */
+  final Map<String, PackageBundle> _bundleMap = <String, PackageBundle>{};
+
+  final Map<String, Source> _absoluteUriMap = <String, Source>{};
+
+  IncrementalCache(this.storage, this.context, this.configSalt);
+
+  /**
+   * Clear internal caches so that we read from file system again.
+   */
+  void clearInternalCaches() {
+    _sourceContentMap.clear();
+    _libraryClosureMap.clear();
+    _sourceContentHashMap.clear();
+    _bundleMap.clear();
+  }
+
+  /**
+   * Return all summaries that are required to provide results about the library
+   * with the given [librarySource] from its summary.  It includes all of the
+   * bundles in the import/export closure of the library.  If any of the
+   * bundles are not in the cache, then `null` is returned.  If any of the
+   * [LibraryBundleWithId]s were already returned as a part of the closure of
+   * another library, they are still included - it is up to the client to
+   * decide whether a bundle should be used or not, but it is easy to do
+   * using [LibraryBundleWithId.id].
+   */
+  List<LibraryBundleWithId> getLibraryClosureBundles(Source librarySource) {
+    try {
+      List<Source> closureSources = _getLibraryClosure(librarySource);
+      List<LibraryBundleWithId> closureBundles = <LibraryBundleWithId>[];
+      for (Source source in closureSources) {
+        if (source.isInSystemLibrary) {
+          continue;
+        }
+        if (getSourceKind(source) == SourceKind.PART) {
+          continue;
+        }
+        String key = _getLibraryBundleKey(source);
+        PackageBundle bundle = _getLibraryBundle(key);
+        if (bundle == null) {
+          return null;
+        }
+        closureBundles.add(new LibraryBundleWithId(source, key, bundle));
+      }
+      return closureBundles;
+    } catch (e) {
+      return null;
+    }
+  }
+
+  /**
+   * Return the kind of the given [source], or `null` if unknown.
+   */
+  SourceKind getSourceKind(Source source) {
+    try {
+      CacheSourceContent contentSource = _getCacheSourceContent(source);
+      if (contentSource != null) {
+        if (contentSource.kind == CacheSourceKind.library) {
+          return SourceKind.LIBRARY;
+        }
+        if (contentSource.kind == CacheSourceKind.part) {
+          return SourceKind.PART;
+        }
+      }
+    } catch (e) {}
+    return null;
+  }
+
+  /**
+   * Write information about the [libraryElement] into the cache.
+   */
+  void putLibrary(LibraryElement libraryElement) {
+    _writeCacheSourceContents(libraryElement);
+    String key = _getLibraryBundleKey(libraryElement.source);
+    PackageBundleAssembler assembler = new PackageBundleAssembler();
+    assembler.serializeLibraryElement(libraryElement);
+    List<int> bytes = assembler.assemble().toBuffer();
+    storage.put(key, bytes);
+  }
+
+  /**
+   * Fill the whole source closure of the library with the given
+   * [librarySource]. It includes defining units and parts of the library and
+   * all its directly or indirectly imported or exported libraries.
+   */
+  void _appendLibraryClosure(Set<Source> closure, Source librarySource) {
+    if (closure.add(librarySource)) {
+      CacheSourceContent contentSource = _getCacheSourceContent(librarySource);
+      if (contentSource == null) {
+        throw new StateError('No structure for $librarySource');
+      }
+      // Append parts.
+      for (String partUri in contentSource.partUris) {
+        Source partSource = _resolveUri(librarySource, partUri);
+        if (partSource == null) {
+          throw new StateError('Unable to resolve $partUri in $librarySource');
+        }
+        closure.add(partSource);
+      }
+      // Append imports and exports.
+      void appendLibrarySources(String refUri) {
+        Source refSource = _resolveUri(librarySource, refUri);
+        if (refSource == null) {
+          throw new StateError('Unable to resolve $refUri in $librarySource');
+        }
+        _appendLibraryClosure(closure, refSource);
+      }
+      contentSource.importedUris.forEach(appendLibrarySources);
+      contentSource.exportedUris.forEach(appendLibrarySources);
+    }
+  }
+
+  /**
+   * Get the content based information about the given [source], maybe `null`
+   * if the information is not in the cache.
+   */
+  CacheSourceContent _getCacheSourceContent(Source source) {
+    CacheSourceContent content = _sourceContentMap[source];
+    if (content == null) {
+      String key = _getCacheSourceContentKey(source);
+      List<int> bytes = storage.get(key);
+      if (bytes == null) {
+        return null;
+      }
+      content = new CacheSourceContent.fromBuffer(bytes);
+      _sourceContentMap[source] = content;
+    }
+    return content;
+  }
+
+  /**
+   * Return the key of the content based [source] information.
+   */
+  String _getCacheSourceContentKey(Source source) {
+    List<int> hash = _getSourceContentHash(source);
+    String hashStr = CryptoUtils.bytesToHex(hash);
+    return '$hashStr.content';
+  }
+
+  /**
+   * Get the bundle for the given key.
+   */
+  PackageBundle _getLibraryBundle(String key) {
+    PackageBundle bundle = _bundleMap[key];
+    if (bundle == null) {
+      List<int> bytes = storage.get(key);
+      if (bytes == null) {
+        return null;
+      }
+      bundle = new PackageBundle.fromBuffer(bytes);
+      _bundleMap[key] = bundle;
+    }
+    return bundle;
+  }
+
+  /**
+   * Return the key of the bundle of the [librarySource].
+   */
+  String _getLibraryBundleKey(Source librarySource) {
+    List<int> hash = _getLibraryClosureHash(librarySource);
+    String hashStr = CryptoUtils.bytesToHex(hash);
+    return '$hashStr.summary';
+  }
+
+  /**
+   * Return the whole source closure of the library with the given
+   * [librarySource]. It includes defining units and parts of the library and
+   * of all its directly or indirectly imported or exported libraries.
+   */
+  List<Source> _getLibraryClosure(Source librarySource) {
+    return _libraryClosureMap.putIfAbsent(librarySource, () {
+      Set<Source> closure = new Set<Source>();
+      _appendLibraryClosure(closure, librarySource);
+      return closure.toList();
+    });
+  }
+
+  /**
+   * Return the [context]-specific hash of the closure of the library with
+   * the given [librarySource].
+   */
+  List<int> _getLibraryClosureHash(Source librarySource) {
+    return _libraryClosureHashMap.putIfAbsent(librarySource, () {
+      List<Source> closure = _getLibraryClosure(librarySource);
+      MD5 md5 = new MD5();
+      for (Source source in closure) {
+        List<int> sourceHash = _getSourceContentHash(source);
+        md5.add(sourceHash);
+      }
+      md5.add(configSalt);
+      return md5.close();
+    });
+  }
+
+  /**
+   * Compute a hash of the given [source] contents.
+   */
+  List<int> _getSourceContentHash(Source source) {
+    return _sourceContentHashMap.putIfAbsent(source, () {
+      String sourceText = source.contents.data;
+      List<int> sourceBytes = UTF8.encode(sourceText);
+      return (new MD5()..add(sourceBytes)).close();
+    });
+  }
+
+  /**
+   * Return a source representing the URI that results from resolving the given
+   * (possibly relative) [containedUri] against the URI associated with the
+   * [containingSource], whether or not the resulting source exists, or `null`
+   * if either the [containedUri] is invalid or if it cannot be resolved against
+   * the [containingSource]'s URI.
+   */
+  Source _resolveUri(Source containingSource, String containedUri) {
+    // Cache absolute URIs.
+    if (containedUri.startsWith('dart:') ||
+        containedUri.startsWith('package:')) {
+      return _absoluteUriMap.putIfAbsent(containedUri, () {
+        return context.sourceFactory.resolveUri(containingSource, containedUri);
+      });
+    }
+    // Resolve relative URIs without caching.
+    return context.sourceFactory.resolveUri(containingSource, containedUri);
+  }
+
+  /**
+   * Write the content based information about the given [source].
+   */
+  void _writeCacheSourceContent(Source source, CacheSourceContentBuilder b) {
+    String key = _getCacheSourceContentKey(source);
+    List<int> bytes = b.toBuffer();
+    storage.put(key, bytes);
+    // Put into the cache to avoid reading it later.
+    _sourceContentMap[source] = new CacheSourceContent.fromBuffer(bytes);
+  }
+
+  /**
+   * Write [CacheSourceContent] for every unit of the given [library] and its
+   * direct and indirect imports/exports.
+   */
+  void _writeCacheSourceContents(LibraryElement library,
+      [Set<LibraryElement> writtenLibraries]) {
+    Source librarySource = library.source;
+    // Do nothing if already cached.
+    if (_sourceContentMap.containsKey(librarySource)) {
+      return;
+    }
+    // Stop recursion cycle.
+    writtenLibraries ??= new Set<LibraryElement>();
+    if (!writtenLibraries.add(library)) {
+      return;
+    }
+    // Write parts.
+    List<String> partUris = <String>[];
+    for (CompilationUnitElement part in library.parts) {
+      partUris.add(part.uri);
+      Source partSource = part.source;
+      if (context.getKindOf(partSource) == SourceKind.PART) {
+        _writeCacheSourceContent(partSource,
+            new CacheSourceContentBuilder(kind: CacheSourceKind.part));
+      }
+    }
+    // Write imports.
+    List<String> importUris = <String>[];
+    for (ImportElement element in library.imports) {
+      String uri = element.uri;
+      if (uri != null) {
+        importUris.add(uri);
+        _writeCacheSourceContents(element.importedLibrary, writtenLibraries);
+      }
+    }
+    // Write exports.
+    List<String> exportUris = <String>[];
+    for (ExportElement element in library.exports) {
+      String uri = element.uri;
+      if (uri != null) {
+        exportUris.add(uri);
+        _writeCacheSourceContents(element.exportedLibrary, writtenLibraries);
+      }
+    }
+    // Write the library.
+    _writeCacheSourceContent(
+        librarySource,
+        new CacheSourceContentBuilder(
+            kind: CacheSourceKind.library,
+            importedUris: importUris,
+            exportedUris: exportUris,
+            partUris: partUris));
+  }
+}
+
+/**
+ * The bundle for a source in the context.
+ */
+class LibraryBundleWithId {
+  /**
+   * The source of the library this bundle is for.
+   */
+  final Source source;
+
+  /**
+   * The unique ID of the [bundle] of the [source] in the context.
+   */
+  final String id;
+
+  /**
+   * The payload bundle.
+   */
+  final PackageBundle bundle;
+
+  LibraryBundleWithId(this.source, this.id, this.bundle);
+}
diff --git a/pkg/analyzer/lib/src/summary/index_unit.dart b/pkg/analyzer/lib/src/summary/index_unit.dart
index a29c88b..b239d5c 100644
--- a/pkg/analyzer/lib/src/summary/index_unit.dart
+++ b/pkg/analyzer/lib/src/summary/index_unit.dart
@@ -207,6 +207,11 @@
       } else if (element is FunctionElement && element.name == 'loadLibrary') {
         kind = IndexSyntheticElementKind.loadLibrary;
         element = element.library;
+      } else if (element is FieldElement) {
+        FieldElement field = element;
+        kind = IndexSyntheticElementKind.field;
+        element = field.getter;
+        element ??= field.setter;
       } else if (element is PropertyAccessorElement) {
         PropertyAccessorElement accessor = element;
         Element enclosing = element.enclosingElement;
@@ -504,6 +509,9 @@
   }
 
   @override
+  visitLibraryIdentifier(LibraryIdentifier node) {}
+
+  @override
   visitMethodInvocation(MethodInvocation node) {
     SimpleIdentifier name = node.methodName;
     Element element = name.bestElement;
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart
index cd6c52e..6ebb3f4 100644
--- a/pkg/analyzer/lib/src/summary/summary_sdk.dart
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -93,6 +93,18 @@
       if (target.library == null || !target.library.isInSystemLibrary) {
         return false;
       }
+      if (result == CREATED_RESOLVED_UNIT1 ||
+          result == CREATED_RESOLVED_UNIT2 ||
+          result == CREATED_RESOLVED_UNIT3 ||
+          result == CREATED_RESOLVED_UNIT4 ||
+          result == CREATED_RESOLVED_UNIT5 ||
+          result == CREATED_RESOLVED_UNIT6 ||
+          result == CREATED_RESOLVED_UNIT7 ||
+          result == CREATED_RESOLVED_UNIT8 ||
+          result == CREATED_RESOLVED_UNIT9) {
+        entry.setValue(result, true, TargetedResult.EMPTY_LIST);
+        return true;
+      }
       if (result == COMPILATION_UNIT_ELEMENT) {
         String libraryUri = target.library.uri.toString();
         String unitUri = target.unit.uri.toString();
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 408db9e..b366e13 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -2231,7 +2231,7 @@
 
   @override
   DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
-      ResultDescriptor descriptor) {
+      ResultDescriptor descriptor, Object value) {
     if (hasDirectiveChange) {
       return DeltaResult.INVALIDATE;
     }
@@ -2259,6 +2259,10 @@
         return DeltaResult.KEEP_CONTINUE;
       }
       if (BuildLibraryElementTask.DESCRIPTOR.results.contains(descriptor)) {
+        // Invalidate cached results.
+        if (value is LibraryElementImpl) {
+          value.exportNamespace = null;
+        }
         return DeltaResult.KEEP_CONTINUE;
       }
       return DeltaResult.INVALIDATE;
@@ -2815,13 +2819,16 @@
     //
     List<AstVisitor> visitors = <AstVisitor>[];
 
+    bool timeVisits = analysisOptions.enableTiming;
     List<Linter> linters = getLints(context);
     for (Linter linter in linters) {
       AstVisitor visitor = linter.getVisitor();
       if (visitor != null) {
         linter.reporter = errorReporter;
-        visitors
-            .add(new TimedAstVisitor(visitor, lintRegistry.getTimer(linter)));
+        if (timeVisits) {
+          visitor = new TimedAstVisitor(visitor, lintRegistry.getTimer(linter));
+        }
+        visitors.add(visitor);
       }
     }
 
diff --git a/pkg/analyzer/lib/src/task/driver.dart b/pkg/analyzer/lib/src/task/driver.dart
index cb4da98..7ff8287 100644
--- a/pkg/analyzer/lib/src/task/driver.dart
+++ b/pkg/analyzer/lib/src/task/driver.dart
@@ -165,6 +165,9 @@
         state == CacheState.IN_PROCESS) {
       return null;
     }
+    if (context.aboutToComputeResult(entry, result)) {
+      return null;
+    }
     TaskDescriptor taskDescriptor = taskManager.findTask(target, result);
     if (taskDescriptor == null) {
       return null;
diff --git a/pkg/analyzer/lib/src/task/inputs.dart b/pkg/analyzer/lib/src/task/inputs.dart
index 1134a58..7553e15 100644
--- a/pkg/analyzer/lib/src/task/inputs.dart
+++ b/pkg/analyzer/lib/src/task/inputs.dart
@@ -89,29 +89,27 @@
  */
 abstract class ListTaskInputMixin<E> implements ListTaskInput<E> {
   @override
-  ListTaskInput /*<V>*/ toFlattenListOf /*<V>*/ (
-      ListResultDescriptor /*<V>*/ subListResult) {
-    return new ListToFlattenListTaskInput<E, dynamic /*=V*/ >(
+  ListTaskInput/*<V>*/ toFlattenListOf/*<V>*/(
+      ListResultDescriptor/*<V>*/ subListResult) {
+    return new ListToFlattenListTaskInput<E, dynamic/*=V*/ >(
         this, subListResult.of as dynamic);
   }
 
-  ListTaskInput /*<V>*/ toList /*<V>*/ (
-      UnaryFunction<E, dynamic /*<=V>*/ > mapper) {
-    return new ListToListTaskInput<E, dynamic /*=V*/ >(this, mapper);
+  ListTaskInput/*<V>*/ toList/*<V>*/(UnaryFunction<E, dynamic/*=V*/ > mapper) {
+    return new ListToListTaskInput<E, dynamic/*=V*/ >(this, mapper);
   }
 
-  ListTaskInput /*<V>*/ toListOf /*<V>*/ (
-      ResultDescriptor /*<V>*/ valueResult) {
+  ListTaskInput/*<V>*/ toListOf/*<V>*/(ResultDescriptor/*<V>*/ valueResult) {
     return (this as ListTaskInput<AnalysisTarget>).toList(valueResult.of);
   }
 
-  MapTaskInput<E, dynamic /*=V*/ > toMap /*<V>*/ (
-      UnaryFunction<E, dynamic /*<=V>*/ > mapper) {
-    return new ListToMapTaskInput<E, dynamic /*=V*/ >(this, mapper);
+  MapTaskInput<E, dynamic/*=V*/ > toMap/*<V>*/(
+      UnaryFunction<E, dynamic/*=V*/ > mapper) {
+    return new ListToMapTaskInput<E, dynamic/*=V*/ >(this, mapper);
   }
 
-  MapTaskInput<AnalysisTarget, dynamic /*=V*/ > toMapOf /*<V>*/ (
-      ResultDescriptor /*<V>*/ valueResult) {
+  MapTaskInput<AnalysisTarget, dynamic/*=V*/ > toMapOf/*<V>*/(
+      ResultDescriptor/*<V>*/ valueResult) {
     return (this as ListTaskInputImpl<AnalysisTarget>).toMap(valueResult.of);
   }
 }
@@ -279,10 +277,10 @@
  * A mixin-ready implementation of [MapTaskInput].
  */
 abstract class MapTaskInputMixin<K, V> implements MapTaskInput<K, V> {
-  TaskInput<List /*<E>*/ > toFlattenList /*<E>*/ (
-      BinaryFunction<K, dynamic /*element of V*/, dynamic /*<=E>*/ > mapper) {
+  TaskInput<List/*<E>*/ > toFlattenList/*<E>*/(
+      BinaryFunction<K, dynamic /*element of V*/, dynamic/*=E*/ > mapper) {
     return new MapToFlattenListTaskInput<K, dynamic /*element of V*/,
-        dynamic /*=E*/ >(this as MapTaskInput<K, List /*<element of V>*/ >, mapper);
+        dynamic/*=E*/ >(this as MapTaskInput<K, List /*element of V*/ >, mapper);
   }
 }
 
@@ -441,23 +439,22 @@
       new ObjectToListTaskInputBuilder<E>(this);
 
   @override
-  ListTaskInput /*<V>*/ toFlattenListOf /*<V>*/ (
-      ListResultDescriptor /*<V>*/ subListResult) {
-    return new ListToFlattenListTaskInput<E, dynamic /*=V*/ >(
+  ListTaskInput/*<V>*/ toFlattenListOf/*<V>*/(
+      ListResultDescriptor/*<V>*/ subListResult) {
+    return new ListToFlattenListTaskInput<E, dynamic/*=V*/ >(
         this, subListResult.of as dynamic);
   }
 
   @override
-  ListTaskInput /*<V>*/ toListOf /*<V>*/ (
-      ResultDescriptor /*<V>*/ valueResult) {
-    return new ListToListTaskInput<E, dynamic /*=V*/ >(
+  ListTaskInput/*<V>*/ toListOf/*<V>*/(ResultDescriptor/*<V>*/ valueResult) {
+    return new ListToListTaskInput<E, dynamic/*=V*/ >(
         this, valueResult.of as dynamic);
   }
 
   @override
-  MapTaskInput<AnalysisTarget, dynamic /*=V*/ > toMapOf /*<V>*/ (
-      ResultDescriptor /*<V>*/ valueResult) {
-    return new ListToMapTaskInput<AnalysisTarget, dynamic /*=V*/ >(
+  MapTaskInput<AnalysisTarget, dynamic/*=V*/ > toMapOf/*<V>*/(
+      ResultDescriptor/*<V>*/ valueResult) {
+    return new ListToMapTaskInput<AnalysisTarget, dynamic/*=V*/ >(
         this as dynamic, valueResult.of);
   }
 }
@@ -696,7 +693,7 @@
 
 abstract class TaskInputImpl<V> implements TaskInput<V> {
   @override
-  ListTaskInput /*<E>*/ mappedToList /*<E>*/ (List /*<E>*/ mapper(V value)) {
+  ListTaskInput/*<E>*/ mappedToList/*<E>*/(List/*<E>*/ mapper(V value)) {
     return new ObjectToListTaskInput(this, mapper);
   }
 }
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 53164a3..79da6a8 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -327,19 +327,43 @@
 
   @override
   void visitForEachStatement(ForEachStatement node) {
-    // Check that the expression is an Iterable.
-    var expr = node.iterable;
-    var iterableType = node.awaitKeyword != null
-        ? typeProvider.streamType
-        : typeProvider.iterableType;
     var loopVariable = node.identifier != null
         ? node.identifier
         : node.loopVariable?.identifier;
+
+    // Safely handle malformed statements.
     if (loopVariable != null) {
-      var iteratorType = loopVariable.staticType;
-      var checkedType = iterableType.instantiate([iteratorType]);
-      checkAssignment(expr, checkedType);
+      // Find the element type of the sequence.
+      var sequenceInterface = node.awaitKeyword != null
+          ? typeProvider.streamType
+          : typeProvider.iterableType;
+      var iterableType = _getStaticType(node.iterable);
+      var elementType =
+          rules.mostSpecificTypeArgument(iterableType, sequenceInterface);
+
+      // If the sequence is not an Iterable (or Stream for await for) but is a
+      // supertype of it, do an implicit downcast to Iterable<dynamic>. Then
+      // we'll do a separate cast of the dynamic element to the variable's type.
+      if (elementType == null) {
+        var sequenceType = sequenceInterface.instantiate([DynamicTypeImpl.instance]);
+
+        if (rules.isSubtypeOf(sequenceType, iterableType)) {
+          _recordMessage(DownCast.create(
+              rules, node.iterable, iterableType, sequenceType));
+          elementType = DynamicTypeImpl.instance;
+        }
+      }
+
+      // If the sequence doesn't implement the interface at all, [ErrorVerifier]
+      // will report the error, so ignore it here.
+      if (elementType != null) {
+        // Insert a cast from the sequence's element type to the loop variable's
+        // if needed.
+        _checkDowncast(loopVariable, _getStaticType(loopVariable),
+            from: elementType);
+      }
     }
+
     node.visitChildren(this);
   }
 
@@ -595,8 +619,8 @@
             rules.isSubtypeOf(lhsType, rhsType)) {
           // This is also slightly different from spec, but allows us to keep
           // compound operators in the int += num and num += dynamic cases.
-          staticInfo = DownCast.create(
-              rules, expr.rightHandSide, rhsType, lhsType);
+          staticInfo =
+              DownCast.create(rules, expr.rightHandSide, rhsType, lhsType);
           rhsType = lhsType;
         } else {
           staticInfo = new StaticTypeError(rules, expr, lhsType);
@@ -663,18 +687,22 @@
     }
   }
 
-  /// Records a [DownCast] of [expr] to [toT], if there is one.
+  /// Records a [DownCast] of [expr] from [from] to [to], if there is one.
   ///
-  /// If [expr] does not require a downcast because it is not related to [toT]
+  /// If [from] is omitted, uses the static type of [expr].
+  ///
+  /// If [expr] does not require a downcast because it is not related to [to]
   /// or is already a subtype of it, does nothing.
-  void _checkDowncast(Expression expr, DartType toT) {
-    DartType fromT = _getStaticType(expr);
+  void _checkDowncast(Expression expr, DartType to, {DartType from}) {
+    if (from == null) {
+      from = _getStaticType(expr);
+    }
 
     // We can use anything as void.
-    if (toT.isVoid) return;
+    if (to.isVoid) return;
 
     // fromT <: toT, no coercion needed.
-    if (rules.isSubtypeOf(fromT, toT)) return;
+    if (rules.isSubtypeOf(from, to)) return;
 
     // TODO(vsm): We can get rid of the second clause if we disallow
     // all sideways casts - see TODO below.
@@ -682,14 +710,14 @@
     // Note: a function type is never assignable to a class per the Dart
     // spec - even if it has a compatible call method.  We disallow as
     // well for consistency.
-    if ((fromT is FunctionType && rules.getCallMethodType(toT) != null) ||
-        (toT is FunctionType && rules.getCallMethodType(fromT) != null)) {
+    if ((from is FunctionType && rules.getCallMethodType(to) != null) ||
+        (to is FunctionType && rules.getCallMethodType(from) != null)) {
       return;
     }
 
     // Downcast if toT <: fromT
-    if (rules.isSubtypeOf(toT, fromT)) {
-      _recordMessage(DownCast.create(rules, expr, fromT, toT));
+    if (rules.isSubtypeOf(to, from)) {
+      _recordMessage(DownCast.create(rules, expr, from, to));
       return;
     }
 
@@ -703,8 +731,8 @@
     // are likely to succeed.  The canonical example is List<dynamic> and
     // Iterable<T> for some concrete T (e.g. Object).  These are unrelated
     // in the restricted system, but List<dynamic> <: Iterable<T> in dart.
-    if (fromT.isAssignableTo(toT)) {
-      _recordMessage(DownCast.create(rules, expr, fromT, toT));
+    if (from.isAssignableTo(to)) {
+      _recordMessage(DownCast.create(rules, expr, from, to));
     }
   }
 
diff --git a/pkg/analyzer/lib/src/task/strong/info.dart b/pkg/analyzer/lib/src/task/strong/info.dart
index 2aaa4c6..b8f09ea 100644
--- a/pkg/analyzer/lib/src/task/strong/info.dart
+++ b/pkg/analyzer/lib/src/task/strong/info.dart
@@ -67,24 +67,24 @@
 
   DownCast._internal(
       TypeSystem rules, Expression expression, this._fromType, this._toType)
-      : super(rules, expression) {
-    assert(_toType != baseType &&
-        _fromType == baseType &&
-        (baseType.isDynamic ||
-            // Call methods make the following non-redundant.
-            _toType.isSubtypeOf(baseType) ||
-            baseType.isAssignableTo(_toType)));
-  }
+      : super(rules, expression);
 
   @override
   List<Object> get arguments => [baseType, convertedType];
 
+  /// The type being cast from.
+  ///
+  /// This is usually the static type of the associated expression, but may not
+  /// be if the cast is attached to a variable in a for-in loop.
+  @override
+  DartType get baseType => _fromType;
+
   DartType get convertedType => _toType;
 
   @override
   String get message => 'Unsound implicit cast from {0} to {1}';
 
-  // Factory to create correct DownCast variant.
+  /// Factory to create correct DownCast variant.
   static StaticInfo create(StrongTypeSystemImpl rules, Expression expression,
       DartType fromType, DartType toType) {
     // toT <:_R fromT => to <: fromT
diff --git a/pkg/analyzer/lib/task/model.dart b/pkg/analyzer/lib/task/model.dart
index 8144f17..b80cca2 100644
--- a/pkg/analyzer/lib/task/model.dart
+++ b/pkg/analyzer/lib/task/model.dart
@@ -381,7 +381,7 @@
    * Return a task input that can be used to compute a list whose elements are
    * the result of passing the elements of this input to the [mapper] function.
    */
-  ListTaskInput/*<V>*/ toList/*<V>*/(UnaryFunction<E, dynamic/*<=V>*/ > mapper);
+  ListTaskInput/*<V>*/ toList/*<V>*/(UnaryFunction<E, dynamic/*=V*/ > mapper);
 
   /**
    * Return a task input that can be used to compute a list whose elements are
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 15dc4c0..e902923 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.27.3-alpha.2
+version: 0.27.3-alpha.4
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
diff --git a/pkg/analyzer/test/context/declared_variables_test.dart b/pkg/analyzer/test/context/declared_variables_test.dart
new file mode 100644
index 0000000..3a33003
--- /dev/null
+++ b/pkg/analyzer/test/context/declared_variables_test.dart
@@ -0,0 +1,116 @@
+// 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 analyzer.test.context.declared_variables_test;
+
+import 'package:analyzer/context/declared_variables.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/generated/constant.dart';
+import 'package:analyzer/src/generated/testing/test_type_provider.dart';
+import 'package:unittest/unittest.dart';
+
+import '../generated/test_support.dart';
+import '../reflective_tests.dart';
+import '../utils.dart';
+
+main() {
+  initializeTestEnvironment();
+  runReflectiveTests(DeclaredVariablesTest);
+}
+
+@reflectiveTest
+class DeclaredVariablesTest extends EngineTestCase {
+  void test_getBool_false() {
+    TestTypeProvider typeProvider = new TestTypeProvider();
+    String variableName = "var";
+    DeclaredVariables variables = new DeclaredVariables();
+    variables.define(variableName, "false");
+    DartObject object = variables.getBool(typeProvider, variableName);
+    expect(object, isNotNull);
+    expect(object.toBoolValue(), false);
+  }
+
+  void test_getBool_invalid() {
+    TestTypeProvider typeProvider = new TestTypeProvider();
+    String variableName = "var";
+    DeclaredVariables variables = new DeclaredVariables();
+    variables.define(variableName, "not true");
+    _assertNullDartObject(
+        typeProvider, variables.getBool(typeProvider, variableName));
+  }
+
+  void test_getBool_true() {
+    TestTypeProvider typeProvider = new TestTypeProvider();
+    String variableName = "var";
+    DeclaredVariables variables = new DeclaredVariables();
+    variables.define(variableName, "true");
+    DartObject object = variables.getBool(typeProvider, variableName);
+    expect(object, isNotNull);
+    expect(object.toBoolValue(), true);
+  }
+
+  void test_getBool_undefined() {
+    TestTypeProvider typeProvider = new TestTypeProvider();
+    String variableName = "var";
+    DeclaredVariables variables = new DeclaredVariables();
+    _assertUnknownDartObject(
+        typeProvider.boolType, variables.getBool(typeProvider, variableName));
+  }
+
+  void test_getInt_invalid() {
+    TestTypeProvider typeProvider = new TestTypeProvider();
+    String variableName = "var";
+    DeclaredVariables variables = new DeclaredVariables();
+    variables.define(variableName, "four score and seven years");
+    _assertNullDartObject(
+        typeProvider, variables.getInt(typeProvider, variableName));
+  }
+
+  void test_getInt_undefined() {
+    TestTypeProvider typeProvider = new TestTypeProvider();
+    String variableName = "var";
+    DeclaredVariables variables = new DeclaredVariables();
+    _assertUnknownDartObject(
+        typeProvider.intType, variables.getInt(typeProvider, variableName));
+  }
+
+  void test_getInt_valid() {
+    TestTypeProvider typeProvider = new TestTypeProvider();
+    String variableName = "var";
+    DeclaredVariables variables = new DeclaredVariables();
+    variables.define(variableName, "23");
+    DartObject object = variables.getInt(typeProvider, variableName);
+    expect(object, isNotNull);
+    expect(object.toIntValue(), 23);
+  }
+
+  void test_getString_defined() {
+    TestTypeProvider typeProvider = new TestTypeProvider();
+    String variableName = "var";
+    String value = "value";
+    DeclaredVariables variables = new DeclaredVariables();
+    variables.define(variableName, value);
+    DartObject object = variables.getString(typeProvider, variableName);
+    expect(object, isNotNull);
+    expect(object.toStringValue(), value);
+  }
+
+  void test_getString_undefined() {
+    TestTypeProvider typeProvider = new TestTypeProvider();
+    String variableName = "var";
+    DeclaredVariables variables = new DeclaredVariables();
+    _assertUnknownDartObject(typeProvider.stringType,
+        variables.getString(typeProvider, variableName));
+  }
+
+  void _assertNullDartObject(TestTypeProvider typeProvider, DartObject result) {
+    expect(result.type, typeProvider.nullType);
+  }
+
+  void _assertUnknownDartObject(
+      ParameterizedType expectedType, DartObject result) {
+    expect((result as DartObjectImpl).isUnknown, isTrue);
+    expect(result.type, expectedType);
+  }
+}
diff --git a/pkg/analyzer/test/context/test_all.dart b/pkg/analyzer/test/context/test_all.dart
new file mode 100644
index 0000000..b5387ba
--- /dev/null
+++ b/pkg/analyzer/test/context/test_all.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.test.context.test_all;
+
+import 'package:unittest/unittest.dart';
+
+import '../utils.dart';
+import 'declared_variables_test.dart' as declared_variables;
+
+/// Utility for manually running all tests.
+main() {
+  initializeTestEnvironment();
+  group('context tests', () {
+    declared_variables.main();
+  });
+}
diff --git a/pkg/analyzer/test/dart/ast/ast_test.dart b/pkg/analyzer/test/dart/ast/ast_test.dart
index 7be2b72..6cd446d 100644
--- a/pkg/analyzer/test/dart/ast/ast_test.dart
+++ b/pkg/analyzer/test/dart/ast/ast_test.dart
@@ -23,6 +23,7 @@
   runReflectiveTests(ConstructorDeclarationTest);
   runReflectiveTests(FieldFormalParameterTest);
   runReflectiveTests(IndexExpressionTest);
+  runReflectiveTests(MethodDeclarationTest);
   runReflectiveTests(NodeListTest);
   runReflectiveTests(SimpleIdentifierTest);
   runReflectiveTests(SimpleStringLiteralTest);
@@ -305,6 +306,44 @@
 }
 
 @reflectiveTest
+class MethodDeclarationTest extends EngineTestCase {
+  void test_firstTokenAfterCommentAndMetadata_external() {
+    MethodDeclaration declaration =
+        AstFactory.methodDeclaration4(external: true, name: 'm');
+    expect(declaration.firstTokenAfterCommentAndMetadata,
+        declaration.externalKeyword);
+  }
+
+  void test_firstTokenAfterCommentAndMetadata_external_getter() {
+    MethodDeclaration declaration = AstFactory.methodDeclaration4(
+        external: true, property: Keyword.GET, name: 'm');
+    expect(declaration.firstTokenAfterCommentAndMetadata,
+        declaration.externalKeyword);
+  }
+
+  void test_firstTokenAfterCommentAndMetadata_external_operator() {
+    MethodDeclaration declaration = AstFactory.methodDeclaration4(
+        external: true, operator: true, name: 'm');
+    expect(declaration.firstTokenAfterCommentAndMetadata,
+        declaration.externalKeyword);
+  }
+
+  void test_firstTokenAfterCommentAndMetadata_getter() {
+    MethodDeclaration declaration =
+        AstFactory.methodDeclaration4(property: Keyword.GET, name: 'm');
+    expect(declaration.firstTokenAfterCommentAndMetadata,
+        declaration.propertyKeyword);
+  }
+
+  void test_firstTokenAfterCommentAndMetadata_operator() {
+    MethodDeclaration declaration =
+        AstFactory.methodDeclaration4(operator: true, name: 'm');
+    expect(declaration.firstTokenAfterCommentAndMetadata,
+        declaration.operatorKeyword);
+  }
+}
+
+@reflectiveTest
 class NodeListTest extends EngineTestCase {
   void test_add() {
     AstNode parent = AstFactory.argumentList();
diff --git a/pkg/analyzer/test/enum_test.dart b/pkg/analyzer/test/enum_test.dart
index 0ba5a98..93f8a4f 100644
--- a/pkg/analyzer/test/enum_test.dart
+++ b/pkg/analyzer/test/enum_test.dart
@@ -136,7 +136,7 @@
       if (_ignoreGetters.contains(name)) {
         return;
       }
-      C value = reflectedClass.getField(symbol).reflectee;
+      C value = reflectedClass.getField(symbol).reflectee as C;
       result[name] = value;
     });
     return result;
@@ -148,7 +148,7 @@
    */
   void check_explicit_values() {
     ClassMirror reflectedClass = reflectClass(C);
-    List<C> values = reflectedClass.getField(#values).reflectee;
+    List<C> values = reflectedClass.getField(#values).reflectee as List<C>;
     Map<C, int> reverseMap = <C, int>{};
 
     // Check that "values" is a list of values of type C, with no duplicates.
diff --git a/pkg/analyzer/test/file_system/memory_file_system_test.dart b/pkg/analyzer/test/file_system/memory_file_system_test.dart
index d00d2d4..759362b 100644
--- a/pkg/analyzer/test/file_system/memory_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/memory_file_system_test.dart
@@ -123,6 +123,19 @@
     expect(parent.path, equals('/foo/bar'));
   }
 
+  void test_readAsBytesSync_doesNotExist() {
+    File file = provider.getResource('/test.bin');
+    expect(() {
+      file.readAsBytesSync();
+    }, throwsA(_isFileSystemException));
+  }
+
+  void test_readAsBytesSync_exists() {
+    List<int> bytes = <int>[1, 2, 3, 4, 5];
+    File file = provider.newFileWithBytes('/file.bin', bytes);
+    expect(file.readAsBytesSync(), bytes);
+  }
+
   void test_readAsStringSync_doesNotExist() {
     File file = provider.getResource('/test.txt');
     expect(() {
@@ -135,6 +148,43 @@
     expect(file.readAsStringSync(), 'abc');
   }
 
+  void test_renameSync_newDoesNotExist() {
+    String oldPath = '/foo/bar/file.txt';
+    String newPath = '/foo/bar/new-file.txt';
+    File file = provider.newFile(oldPath, 'text');
+    File newFile = file.renameSync(newPath);
+    expect(file.path, oldPath);
+    expect(file.exists, isFalse);
+    expect(newFile.path, newPath);
+    expect(newFile.exists, isTrue);
+    expect(newFile.readAsStringSync(), 'text');
+  }
+
+  void test_renameSync_newExists_file() {
+    String oldPath = '/foo/bar/file.txt';
+    String newPath = '/foo/bar/new-file.txt';
+    File file = provider.newFile(oldPath, 'text');
+    provider.newFile(newPath, 'new text');
+    File newFile = file.renameSync(newPath);
+    expect(file.path, oldPath);
+    expect(file.exists, isFalse);
+    expect(newFile.path, newPath);
+    expect(newFile.exists, isTrue);
+    expect(newFile.readAsStringSync(), 'text');
+  }
+
+  void test_renameSync_newExists_folder() {
+    String oldPath = '/foo/bar/file.txt';
+    String newPath = '/foo/bar/baz';
+    File file = provider.newFile(oldPath, 'text');
+    provider.newFolder(newPath);
+    expect(() {
+      file.renameSync(newPath);
+    }, throwsA(_isFileSystemException));
+    expect(file.path, oldPath);
+    expect(file.exists, isTrue);
+  }
+
   void test_shortName() {
     File file = provider.getResource('/foo/bar/file.txt');
     expect(file.shortName, 'file.txt');
@@ -144,6 +194,23 @@
     File file = provider.getResource('/foo/bar/file.txt');
     expect(file.toString(), '/foo/bar/file.txt');
   }
+
+  void test_writeAsBytesSync_existing() {
+    File file = provider.newFileWithBytes('/foo/file.bin', <int>[1, 2]);
+    expect(file.readAsBytesSync(), <int>[1, 2]);
+    // write new bytes
+    file.writeAsBytesSync(<int>[10, 20]);
+    expect(file.readAsBytesSync(), <int>[10, 20]);
+  }
+
+  void test_writeAsBytesSync_new() {
+    File file = provider.getFile('/foo/file.bin');
+    expect(file.exists, false);
+    // write new bytes
+    file.writeAsBytesSync(<int>[10, 20]);
+    expect(file.exists, true);
+    expect(file.readAsBytesSync(), <int>[10, 20]);
+  }
 }
 
 @reflectiveTest
@@ -467,14 +534,24 @@
     expect(source.contents.data, equals('contents 2'));
   }
 
-  void test_newFolder_aleadyExists_asFile() {
+  void test_newFileWithBytes() {
+    String path = '/my/file';
+    List<int> bytes = <int>[1, 2, 3, 4, 5];
+    provider.newFileWithBytes(path, bytes);
+    File file = provider.getResource(path);
+    expect(file, isNotNull);
+    expect(file.exists, isTrue);
+    expect(file.readAsBytesSync(), bytes);
+  }
+
+  void test_newFolder_alreadyExists_asFile() {
     provider.newFile('/my/file', 'qwerty');
     expect(() {
       provider.newFolder('/my/file');
     }, throwsA(new isInstanceOf<ArgumentError>()));
   }
 
-  void test_newFolder_aleadyExists_asFolder() {
+  void test_newFolder_alreadyExists_asFolder() {
     Folder folder = provider.newFolder('/my/folder');
     Folder newFolder = provider.newFolder('/my/folder');
     expect(newFolder, folder);
diff --git a/pkg/analyzer/test/file_system/physical_resource_provider_test.dart b/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
index 850bbcf..5bf3256 100644
--- a/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
+++ b/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
@@ -20,9 +20,11 @@
 
 main() {
   initializeTestEnvironment();
-  runReflectiveTests(PhysicalResourceProviderTest);
-  runReflectiveTests(FileTest);
-  runReflectiveTests(FolderTest);
+  if (!new bool.fromEnvironment('skipPhysicalResourceProviderTests')) {
+    runReflectiveTests(PhysicalResourceProviderTest);
+    runReflectiveTests(FileTest);
+    runReflectiveTests(FolderTest);
+  }
 }
 
 var _isFile = new isInstanceOf<File>();
@@ -104,6 +106,19 @@
     expect(parent.path, equals(tempPath));
   }
 
+  void test_readAsBytesSync_doesNotExist() {
+    File file = PhysicalResourceProvider.INSTANCE.getResource('/test.bin');
+    expect(() {
+      file.readAsBytesSync();
+    }, throwsA(_isFileSystemException));
+  }
+
+  void test_readAsBytesSync_exists() {
+    List<int> bytes = <int>[1, 2, 3, 4, 5];
+    new io.File(path).writeAsBytesSync(bytes);
+    expect(file.readAsBytesSync(), bytes);
+  }
+
   void test_readAsStringSync_doesNotExist() {
     File file = PhysicalResourceProvider.INSTANCE.getResource(path);
     expect(() {
@@ -117,6 +132,46 @@
     expect(file.readAsStringSync(), 'abc');
   }
 
+  void test_renameSync_newDoesNotExist() {
+    String oldPath = '$tempPath/file.txt';
+    String newPath = '$tempPath/new-file.txt';
+    new io.File(oldPath).writeAsStringSync('text');
+    File file = PhysicalResourceProvider.INSTANCE.getResource(oldPath);
+    File newFile = file.renameSync(newPath);
+    expect(file.path, oldPath);
+    expect(file.exists, isFalse);
+    expect(newFile.path, newPath);
+    expect(newFile.exists, isTrue);
+    expect(newFile.readAsStringSync(), 'text');
+  }
+
+  test_renameSync_newExists_file() async {
+    String oldPath = '$tempPath/file.txt';
+    String newPath = '$tempPath/new-file.txt';
+    new io.File(oldPath).writeAsStringSync('text');
+    new io.File(newPath).writeAsStringSync('new text');
+    File file = PhysicalResourceProvider.INSTANCE.getResource(oldPath);
+    File newFile = file.renameSync(newPath);
+    expect(file.path, oldPath);
+    expect(file.exists, isFalse);
+    expect(newFile.path, newPath);
+    expect(newFile.exists, isTrue);
+    expect(newFile.readAsStringSync(), 'text');
+  }
+
+  void test_renameSync_newExists_folder() {
+    String oldPath = '$tempPath/file.txt';
+    String newPath = '$tempPath/foo';
+    new io.File(oldPath).writeAsStringSync('text');
+    new io.Directory(newPath).createSync();
+    File file = PhysicalResourceProvider.INSTANCE.getResource(oldPath);
+    expect(() {
+      file.renameSync(newPath);
+    }, throwsA(_isFileSystemException));
+    expect(file.path, oldPath);
+    expect(file.exists, isTrue);
+  }
+
   void test_shortName() {
     expect(file.shortName, 'file.txt');
   }
@@ -124,6 +179,14 @@
   void test_toString() {
     expect(file.toString(), path);
   }
+
+  void test_writeAsBytesSync() {
+    new io.File(path).writeAsBytesSync(<int>[1, 2]);
+    expect(file.readAsBytesSync(), <int>[1, 2]);
+    // write new bytes
+    file.writeAsBytesSync(<int>[10, 20]);
+    expect(file.readAsBytesSync(), <int>[10, 20]);
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index dc95b3a..ac35f08 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -5,96 +5,21 @@
 library analyzer.test.constant_test;
 
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/constant.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
-import 'package:analyzer/src/generated/testing/ast_factory.dart';
-import 'package:analyzer/src/generated/testing/element_factory.dart';
-import 'package:analyzer/src/generated/testing/test_type_provider.dart';
-import 'package:analyzer/src/generated/utilities_collection.dart';
-import 'package:analyzer/src/task/dart.dart';
-import 'package:path/path.dart';
 import 'package:unittest/unittest.dart';
 
 import '../reflective_tests.dart';
 import '../utils.dart';
-import 'engine_test.dart';
 import 'resolver_test_case.dart';
 import 'test_support.dart';
 
 main() {
   initializeTestEnvironment();
   runReflectiveTests(ConstantEvaluatorTest);
-  runReflectiveTests(ConstantFinderTest);
-  runReflectiveTests(ConstantValueComputerTest);
-  runReflectiveTests(ConstantVisitorTest);
-  runReflectiveTests(DartObjectImplTest);
-  runReflectiveTests(DeclaredVariablesTest);
-  runReflectiveTests(ReferenceFinderTest);
-}
-
-const int LONG_MAX_VALUE = 0x7fffffffffffffff;
-
-/**
- * Implementation of [ConstantEvaluationValidator] used during unit tests;
- * verifies that any nodes referenced during constant evaluation are present in
- * the dependency graph.
- */
-class ConstantEvaluationValidator_ForTest
-    implements ConstantEvaluationValidator {
-  final InternalAnalysisContext context;
-  ConstantValueComputer computer;
-  ConstantEvaluationTarget _nodeBeingEvaluated;
-
-  ConstantEvaluationValidator_ForTest(this.context);
-
-  @override
-  void beforeComputeValue(ConstantEvaluationTarget constant) {
-    _nodeBeingEvaluated = constant;
-  }
-
-  @override
-  void beforeGetConstantInitializers(ConstructorElement constructor) =>
-      _checkPathTo(constructor);
-
-  @override
-  void beforeGetEvaluationResult(ConstantEvaluationTarget constant) =>
-      _checkPathTo(constant);
-
-  @override
-  void beforeGetFieldEvaluationResult(FieldElementImpl field) =>
-      _checkPathTo(field);
-
-  @override
-  void beforeGetParameterDefault(ParameterElement parameter) =>
-      _checkPathTo(parameter);
-
-  void _checkPathTo(ConstantEvaluationTarget target) {
-    if (computer.referenceGraph.containsPath(_nodeBeingEvaluated, target)) {
-      return; // pass
-    }
-    // print a nice error message on failure
-    StringBuffer out = new StringBuffer();
-    out.writeln("missing path in constant dependency graph");
-    out.writeln("from $_nodeBeingEvaluated to $target");
-    for (var s in context.analysisCache.sources) {
-      String text = context.getContents(s).data;
-      if (text != "") {
-        out.writeln('''
-=== ${s.shortName}
-$text''');
-      }
-    }
-    fail(out.toString());
-  }
 }
 
 @reflectiveTest
@@ -482,4060 +407,3 @@
     return evaluator.evaluate(variables[0].initializer);
   }
 }
-
-@reflectiveTest
-class ConstantFinderTest {
-  AstNode _node;
-  TypeProvider _typeProvider;
-  AnalysisContext _context;
-  Source _source;
-
-  void setUp() {
-    _typeProvider = new TestTypeProvider();
-    _context = new _TestAnalysisContext();
-    _source = new TestSource();
-  }
-
-  /**
-   * Test an annotation that consists solely of an identifier (and hence
-   * represents a reference to a compile-time constant variable).
-   */
-  void test_visitAnnotation_constantVariable() {
-    CompilationUnitElement compilationUnitElement =
-        ElementFactory.compilationUnit('/test.dart', _source)..source = _source;
-    ElementFactory.library(_context, 'L').definingCompilationUnit =
-        compilationUnitElement;
-    ElementAnnotationImpl elementAnnotation =
-        new ElementAnnotationImpl(compilationUnitElement);
-    _node = elementAnnotation.annotationAst = AstFactory.annotation(
-        AstFactory.identifier3('x'))..elementAnnotation = elementAnnotation;
-    expect(_findAnnotations(), contains(_node));
-  }
-
-  /**
-   * Test an annotation that represents the invocation of a constant
-   * constructor.
-   */
-  void test_visitAnnotation_invocation() {
-    CompilationUnitElement compilationUnitElement =
-        ElementFactory.compilationUnit('/test.dart', _source)..source = _source;
-    ElementFactory.library(_context, 'L').definingCompilationUnit =
-        compilationUnitElement;
-    ElementAnnotationImpl elementAnnotation =
-        new ElementAnnotationImpl(compilationUnitElement);
-    _node = elementAnnotation.annotationAst = AstFactory.annotation2(
-        AstFactory.identifier3('A'), null, AstFactory.argumentList())
-      ..elementAnnotation = elementAnnotation;
-    expect(_findAnnotations(), contains(_node));
-  }
-
-  void test_visitAnnotation_partOf() {
-    // Analyzer ignores annotations on "part of" directives.
-    Annotation annotation = AstFactory.annotation2(
-        AstFactory.identifier3('A'), null, AstFactory.argumentList());
-    _node = AstFactory.partOfDirective2(
-        <Annotation>[annotation], AstFactory.libraryIdentifier2(<String>['L']));
-    expect(_findConstants(), isEmpty);
-  }
-
-  void test_visitConstructorDeclaration_const() {
-    ConstructorElement element = _setupConstructorDeclaration("A", true);
-    expect(_findConstants(), contains(element));
-  }
-
-  void test_visitConstructorDeclaration_nonConst() {
-    _setupConstructorDeclaration("A", false);
-    expect(_findConstants(), isEmpty);
-  }
-
-  void test_visitVariableDeclaration_const() {
-    VariableElement element = _setupVariableDeclaration("v", true, true);
-    expect(_findConstants(), contains(element));
-  }
-
-  void test_visitVariableDeclaration_final_inClass() {
-    _setupFieldDeclaration('C', 'f', Keyword.FINAL);
-    expect(_findConstants(), isEmpty);
-  }
-
-  void test_visitVariableDeclaration_final_inClassWithConstConstructor() {
-    VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
-        hasConstConstructor: true);
-    expect(_findConstants(), contains(field.element));
-  }
-
-  void test_visitVariableDeclaration_final_outsideClass() {
-    _setupVariableDeclaration('v', false, true, isFinal: true);
-    expect(_findConstants(), isEmpty);
-  }
-
-  void test_visitVariableDeclaration_noInitializer() {
-    _setupVariableDeclaration("v", true, false);
-    expect(_findConstants(), isEmpty);
-  }
-
-  void test_visitVariableDeclaration_nonConst() {
-    _setupVariableDeclaration("v", false, true);
-    expect(_findConstants(), isEmpty);
-  }
-
-  void test_visitVariableDeclaration_static_const_inClass() {
-    VariableDeclaration field =
-        _setupFieldDeclaration('C', 'f', Keyword.CONST, isStatic: true);
-    expect(_findConstants(), contains(field.element));
-  }
-
-  void
-      test_visitVariableDeclaration_static_const_inClassWithConstConstructor() {
-    VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.CONST,
-        isStatic: true, hasConstConstructor: true);
-    expect(_findConstants(), contains(field.element));
-  }
-
-  void
-      test_visitVariableDeclaration_static_final_inClassWithConstConstructor() {
-    VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
-        isStatic: true, hasConstConstructor: true);
-    expect(_findConstants(), isNot(contains(field.element)));
-  }
-
-  void
-      test_visitVariableDeclaration_uninitialized_final_inClassWithConstConstructor() {
-    VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
-        isInitialized: false, hasConstConstructor: true);
-    expect(_findConstants(), isNot(contains(field.element)));
-  }
-
-  void test_visitVariableDeclaration_uninitialized_static_const_inClass() {
-    _setupFieldDeclaration('C', 'f', Keyword.CONST,
-        isStatic: true, isInitialized: false);
-    expect(_findConstants(), isEmpty);
-  }
-
-  List<Annotation> _findAnnotations() {
-    Set<Annotation> annotations = new Set<Annotation>();
-    for (ConstantEvaluationTarget target in _findConstants()) {
-      if (target is ElementAnnotationImpl) {
-        expect(target.context, same(_context));
-        expect(target.source, same(_source));
-        annotations.add(target.annotationAst);
-      }
-    }
-    return new List<Annotation>.from(annotations);
-  }
-
-  List<ConstantEvaluationTarget> _findConstants() {
-    ConstantFinder finder = new ConstantFinder(_context, _source, _source);
-    _node.accept(finder);
-    List<ConstantEvaluationTarget> constants = finder.constantsToCompute;
-    expect(constants, isNotNull);
-    return constants;
-  }
-
-  ConstructorElement _setupConstructorDeclaration(String name, bool isConst) {
-    Keyword constKeyword = isConst ? Keyword.CONST : null;
-    ConstructorDeclaration constructorDeclaration =
-        AstFactory.constructorDeclaration2(
-            constKeyword,
-            null,
-            null,
-            name,
-            AstFactory.formalParameterList(),
-            null,
-            AstFactory.blockFunctionBody2());
-    ClassElement classElement = ElementFactory.classElement2(name);
-    ConstructorElement element =
-        ElementFactory.constructorElement(classElement, name, isConst);
-    constructorDeclaration.element = element;
-    _node = constructorDeclaration;
-    return element;
-  }
-
-  VariableDeclaration _setupFieldDeclaration(
-      String className, String fieldName, Keyword keyword,
-      {bool isInitialized: true,
-      bool isStatic: false,
-      bool hasConstConstructor: false}) {
-    VariableDeclaration variableDeclaration = isInitialized
-        ? AstFactory.variableDeclaration2(fieldName, AstFactory.integer(0))
-        : AstFactory.variableDeclaration(fieldName);
-    VariableElement fieldElement = ElementFactory.fieldElement(
-        fieldName,
-        isStatic,
-        keyword == Keyword.FINAL,
-        keyword == Keyword.CONST,
-        _typeProvider.intType);
-    variableDeclaration.name.staticElement = fieldElement;
-    FieldDeclaration fieldDeclaration = AstFactory.fieldDeclaration2(
-        isStatic, keyword, <VariableDeclaration>[variableDeclaration]);
-    ClassDeclaration classDeclaration =
-        AstFactory.classDeclaration(null, className, null, null, null, null);
-    classDeclaration.members.add(fieldDeclaration);
-    _node = classDeclaration;
-    ClassElementImpl classElement = ElementFactory.classElement2(className);
-    classElement.fields = <FieldElement>[fieldElement];
-    classDeclaration.name.staticElement = classElement;
-    if (hasConstConstructor) {
-      ConstructorDeclaration constructorDeclaration =
-          AstFactory.constructorDeclaration2(
-              Keyword.CONST,
-              null,
-              AstFactory.identifier3(className),
-              null,
-              AstFactory.formalParameterList(),
-              null,
-              AstFactory.blockFunctionBody2());
-      classDeclaration.members.add(constructorDeclaration);
-      ConstructorElement constructorElement =
-          ElementFactory.constructorElement(classElement, '', true);
-      constructorDeclaration.element = constructorElement;
-      classElement.constructors = <ConstructorElement>[constructorElement];
-    } else {
-      classElement.constructors = ConstructorElement.EMPTY_LIST;
-    }
-    return variableDeclaration;
-  }
-
-  VariableElement _setupVariableDeclaration(
-      String name, bool isConst, bool isInitialized,
-      {isFinal: false}) {
-    VariableDeclaration variableDeclaration = isInitialized
-        ? AstFactory.variableDeclaration2(name, AstFactory.integer(0))
-        : AstFactory.variableDeclaration(name);
-    SimpleIdentifier identifier = variableDeclaration.name;
-    VariableElement element = ElementFactory.localVariableElement(identifier);
-    identifier.staticElement = element;
-    Keyword keyword = isConst ? Keyword.CONST : isFinal ? Keyword.FINAL : null;
-    AstFactory.variableDeclarationList2(keyword, [variableDeclaration]);
-    _node = variableDeclaration;
-    return element;
-  }
-}
-
-@reflectiveTest
-class ConstantValueComputerTest extends ResolverTestCase {
-  void test_annotation_constConstructor() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A {
-  final int i;
-  const A(this.i);
-}
-
-class C {
-  @A(5)
-  f() {}
-}
-''');
-    EvaluationResultImpl result =
-        _evaluateAnnotation(compilationUnit, "C", "f");
-    Map<String, DartObjectImpl> annotationFields = _assertType(result, 'A');
-    _assertIntField(annotationFields, 'i', 5);
-  }
-
-  void test_annotation_constConstructor_named() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A {
-  final int i;
-  const A.named(this.i);
-}
-
-class C {
-  @A.named(5)
-  f() {}
-}
-''');
-    EvaluationResultImpl result =
-        _evaluateAnnotation(compilationUnit, "C", "f");
-    Map<String, DartObjectImpl> annotationFields = _assertType(result, 'A');
-    _assertIntField(annotationFields, 'i', 5);
-  }
-
-  void test_annotation_constConstructor_noArgs() {
-    // Failing to pass arguments to an annotation which is a constant
-    // constructor is illegal, but shouldn't crash analysis.
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A {
-  final int i;
-  const A(this.i);
-}
-
-class C {
-  @A
-  f() {}
-}
-''');
-    _evaluateAnnotation(compilationUnit, "C", "f");
-  }
-
-  void test_annotation_constConstructor_noArgs_named() {
-    // Failing to pass arguments to an annotation which is a constant
-    // constructor is illegal, but shouldn't crash analysis.
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A {
-  final int i;
-  const A.named(this.i);
-}
-
-class C {
-  @A.named
-  f() {}
-}
-''');
-    _evaluateAnnotation(compilationUnit, "C", "f");
-  }
-
-  void test_annotation_nonConstConstructor() {
-    // Calling a non-const constructor from an annotation that is illegal, but
-    // shouldn't crash analysis.
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A {
-  final int i;
-  A(this.i);
-}
-
-class C {
-  @A(5)
-  f() {}
-}
-''');
-    _evaluateAnnotation(compilationUnit, "C", "f");
-  }
-
-  void test_annotation_staticConst() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-class C {
-  static const int i = 5;
-
-  @i
-  f() {}
-}
-''');
-    EvaluationResultImpl result =
-        _evaluateAnnotation(compilationUnit, "C", "f");
-    expect(_assertValidInt(result), 5);
-  }
-
-  void test_annotation_staticConst_args() {
-    // Applying arguments to an annotation that is a static const is
-    // illegal, but shouldn't crash analysis.
-    CompilationUnit compilationUnit = resolveSource(r'''
-class C {
-  static const int i = 5;
-
-  @i(1)
-  f() {}
-}
-''');
-    _evaluateAnnotation(compilationUnit, "C", "f");
-  }
-
-  void test_annotation_staticConst_otherClass() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A {
-  static const int i = 5;
-}
-
-class C {
-  @A.i
-  f() {}
-}
-''');
-    EvaluationResultImpl result =
-        _evaluateAnnotation(compilationUnit, "C", "f");
-    expect(_assertValidInt(result), 5);
-  }
-
-  void test_annotation_staticConst_otherClass_args() {
-    // Applying arguments to an annotation that is a static const is
-    // illegal, but shouldn't crash analysis.
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A {
-  static const int i = 5;
-}
-
-class C {
-  @A.i(1)
-  f() {}
-}
-''');
-    _evaluateAnnotation(compilationUnit, "C", "f");
-  }
-
-  void test_annotation_topLevelVariable() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const int i = 5;
-class C {
-  @i
-  f() {}
-}
-''');
-    EvaluationResultImpl result =
-        _evaluateAnnotation(compilationUnit, "C", "f");
-    expect(_assertValidInt(result), 5);
-  }
-
-  void test_annotation_topLevelVariable_args() {
-    // Applying arguments to an annotation that is a top-level variable is
-    // illegal, but shouldn't crash analysis.
-    CompilationUnit compilationUnit = resolveSource(r'''
-const int i = 5;
-class C {
-  @i(1)
-  f() {}
-}
-''');
-    _evaluateAnnotation(compilationUnit, "C", "f");
-  }
-
-  void test_computeValues_cycle() {
-    TestLogger logger = new TestLogger();
-    AnalysisEngine.instance.logger = logger;
-    try {
-      Source source = addSource(r'''
-  const int a = c;
-  const int b = a;
-  const int c = b;''');
-      LibraryElement libraryElement = resolve2(source);
-      CompilationUnit unit =
-          analysisContext.resolveCompilationUnit(source, libraryElement);
-      analysisContext.computeErrors(source);
-      expect(unit, isNotNull);
-      ConstantValueComputer computer = _makeConstantValueComputer();
-      computer.add(unit, source, source);
-      computer.computeValues();
-      NodeList<CompilationUnitMember> members = unit.declarations;
-      expect(members, hasLength(3));
-      _validate(false, (members[0] as TopLevelVariableDeclaration).variables);
-      _validate(false, (members[1] as TopLevelVariableDeclaration).variables);
-      _validate(false, (members[2] as TopLevelVariableDeclaration).variables);
-    } finally {
-      AnalysisEngine.instance.logger = Logger.NULL;
-    }
-  }
-
-  void test_computeValues_dependentVariables() {
-    Source source = addSource(r'''
-const int b = a;
-const int a = 0;''');
-    LibraryElement libraryElement = resolve2(source);
-    CompilationUnit unit =
-        analysisContext.resolveCompilationUnit(source, libraryElement);
-    expect(unit, isNotNull);
-    ConstantValueComputer computer = _makeConstantValueComputer();
-    computer.add(unit, source, source);
-    computer.computeValues();
-    NodeList<CompilationUnitMember> members = unit.declarations;
-    expect(members, hasLength(2));
-    _validate(true, (members[0] as TopLevelVariableDeclaration).variables);
-    _validate(true, (members[1] as TopLevelVariableDeclaration).variables);
-  }
-
-  void test_computeValues_empty() {
-    ConstantValueComputer computer = _makeConstantValueComputer();
-    computer.computeValues();
-  }
-
-  void test_computeValues_multipleSources() {
-    Source librarySource = addNamedSource(
-        "/lib.dart",
-        r'''
-library lib;
-part 'part.dart';
-const int c = b;
-const int a = 0;''');
-    Source partSource = addNamedSource(
-        "/part.dart",
-        r'''
-part of lib;
-const int b = a;
-const int d = c;''');
-    LibraryElement libraryElement = resolve2(librarySource);
-    CompilationUnit libraryUnit =
-        analysisContext.resolveCompilationUnit(librarySource, libraryElement);
-    expect(libraryUnit, isNotNull);
-    CompilationUnit partUnit =
-        analysisContext.resolveCompilationUnit(partSource, libraryElement);
-    expect(partUnit, isNotNull);
-    ConstantValueComputer computer = _makeConstantValueComputer();
-    computer.add(libraryUnit, librarySource, librarySource);
-    computer.add(partUnit, partSource, librarySource);
-    computer.computeValues();
-    NodeList<CompilationUnitMember> libraryMembers = libraryUnit.declarations;
-    expect(libraryMembers, hasLength(2));
-    _validate(
-        true, (libraryMembers[0] as TopLevelVariableDeclaration).variables);
-    _validate(
-        true, (libraryMembers[1] as TopLevelVariableDeclaration).variables);
-    NodeList<CompilationUnitMember> partMembers = libraryUnit.declarations;
-    expect(partMembers, hasLength(2));
-    _validate(true, (partMembers[0] as TopLevelVariableDeclaration).variables);
-    _validate(true, (partMembers[1] as TopLevelVariableDeclaration).variables);
-  }
-
-  void test_computeValues_singleVariable() {
-    Source source = addSource("const int a = 0;");
-    LibraryElement libraryElement = resolve2(source);
-    CompilationUnit unit =
-        analysisContext.resolveCompilationUnit(source, libraryElement);
-    expect(unit, isNotNull);
-    ConstantValueComputer computer = _makeConstantValueComputer();
-    computer.add(unit, source, source);
-    computer.computeValues();
-    NodeList<CompilationUnitMember> members = unit.declarations;
-    expect(members, hasLength(1));
-    _validate(true, (members[0] as TopLevelVariableDeclaration).variables);
-  }
-
-  void test_computeValues_value_depends_on_enum() {
-    Source source = addSource('''
-enum E { id0, id1 }
-const E e = E.id0;
-''');
-    LibraryElement libraryElement = resolve2(source);
-    CompilationUnit unit =
-        analysisContext.resolveCompilationUnit(source, libraryElement);
-    expect(unit, isNotNull);
-    ConstantValueComputer computer = _makeConstantValueComputer();
-    computer.add(unit, source, source);
-    computer.computeValues();
-    TopLevelVariableDeclaration declaration = unit.declarations
-        .firstWhere((member) => member is TopLevelVariableDeclaration);
-    _validate(true, declaration.variables);
-  }
-
-  void test_dependencyOnConstructor() {
-    // x depends on "const A()"
-    _assertProperDependencies(r'''
-class A {
-  const A();
-}
-const x = const A();''');
-  }
-
-  void test_dependencyOnConstructorArgument() {
-    // "const A(x)" depends on x
-    _assertProperDependencies(r'''
-class A {
-  const A(this.next);
-  final A next;
-}
-const A x = const A(null);
-const A y = const A(x);''');
-  }
-
-  void test_dependencyOnConstructorArgument_unresolvedConstructor() {
-    // "const A.a(x)" depends on x even if the constructor A.a can't be found.
-    _assertProperDependencies(
-        r'''
-class A {
-}
-const int x = 1;
-const A y = const A.a(x);''',
-        [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR]);
-  }
-
-  void test_dependencyOnConstructorInitializer() {
-    // "const A()" depends on x
-    _assertProperDependencies(r'''
-const int x = 1;
-class A {
-  const A() : v = x;
-  final int v;
-}''');
-  }
-
-  void test_dependencyOnExplicitSuperConstructor() {
-    // b depends on B() depends on A()
-    _assertProperDependencies(r'''
-class A {
-  const A(this.x);
-  final int x;
-}
-class B extends A {
-  const B() : super(5);
-}
-const B b = const B();''');
-  }
-
-  void test_dependencyOnExplicitSuperConstructorParameters() {
-    // b depends on B() depends on i
-    _assertProperDependencies(r'''
-class A {
-  const A(this.x);
-  final int x;
-}
-class B extends A {
-  const B() : super(i);
-}
-const B b = const B();
-const int i = 5;''');
-  }
-
-  void test_dependencyOnFactoryRedirect() {
-    // a depends on A.foo() depends on A.bar()
-    _assertProperDependencies(r'''
-const A a = const A.foo();
-class A {
-  factory const A.foo() = A.bar;
-  const A.bar();
-}''');
-  }
-
-  void test_dependencyOnFactoryRedirectWithTypeParams() {
-    _assertProperDependencies(r'''
-class A {
-  const factory A(var a) = B<int>;
-}
-
-class B<T> implements A {
-  final T x;
-  const B(this.x);
-}
-
-const A a = const A(10);''');
-  }
-
-  void test_dependencyOnImplicitSuperConstructor() {
-    // b depends on B() depends on A()
-    _assertProperDependencies(r'''
-class A {
-  const A() : x = 5;
-  final int x;
-}
-class B extends A {
-  const B();
-}
-const B b = const B();''');
-  }
-
-  void test_dependencyOnInitializedFinal() {
-    // a depends on A() depends on A.x
-    _assertProperDependencies('''
-class A {
-  const A();
-  final int x = 1;
-}
-const A a = const A();
-''');
-  }
-
-  void test_dependencyOnInitializedNonStaticConst() {
-    // Even though non-static consts are not allowed by the language, we need
-    // to handle them for error recovery purposes.
-    // a depends on A() depends on A.x
-    _assertProperDependencies(
-        '''
-class A {
-  const A();
-  const int x = 1;
-}
-const A a = const A();
-''',
-        [CompileTimeErrorCode.CONST_INSTANCE_FIELD]);
-  }
-
-  void test_dependencyOnNonFactoryRedirect() {
-    // a depends on A.foo() depends on A.bar()
-    _assertProperDependencies(r'''
-const A a = const A.foo();
-class A {
-  const A.foo() : this.bar();
-  const A.bar();
-}''');
-  }
-
-  void test_dependencyOnNonFactoryRedirect_arg() {
-    // a depends on A.foo() depends on b
-    _assertProperDependencies(r'''
-const A a = const A.foo();
-const int b = 1;
-class A {
-  const A.foo() : this.bar(b);
-  const A.bar(x) : y = x;
-  final int y;
-}''');
-  }
-
-  void test_dependencyOnNonFactoryRedirect_defaultValue() {
-    // a depends on A.foo() depends on A.bar() depends on b
-    _assertProperDependencies(r'''
-const A a = const A.foo();
-const int b = 1;
-class A {
-  const A.foo() : this.bar();
-  const A.bar([x = b]) : y = x;
-  final int y;
-}''');
-  }
-
-  void test_dependencyOnNonFactoryRedirect_toMissing() {
-    // a depends on A.foo() which depends on nothing, since A.bar() is
-    // missing.
-    _assertProperDependencies(
-        r'''
-const A a = const A.foo();
-class A {
-  const A.foo() : this.bar();
-}''',
-        [CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR]);
-  }
-
-  void test_dependencyOnNonFactoryRedirect_toNonConst() {
-    // a depends on A.foo() which depends on nothing, since A.bar() is
-    // non-const.
-    _assertProperDependencies(r'''
-const A a = const A.foo();
-class A {
-  const A.foo() : this.bar();
-  A.bar();
-}''');
-  }
-
-  void test_dependencyOnNonFactoryRedirect_unnamed() {
-    // a depends on A.foo() depends on A()
-    _assertProperDependencies(r'''
-const A a = const A.foo();
-class A {
-  const A.foo() : this();
-  const A();
-}''');
-  }
-
-  void test_dependencyOnOptionalParameterDefault() {
-    // a depends on A() depends on B()
-    _assertProperDependencies(r'''
-class A {
-  const A([x = const B()]) : b = x;
-  final B b;
-}
-class B {
-  const B();
-}
-const A a = const A();''');
-  }
-
-  void test_dependencyOnVariable() {
-    // x depends on y
-    _assertProperDependencies(r'''
-const x = y + 1;
-const y = 2;''');
-  }
-
-  void test_final_initialized_at_declaration() {
-    CompilationUnit compilationUnit = resolveSource('''
-class A {
-  final int i = 123;
-  const A();
-}
-
-const A a = const A();
-''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, 'a');
-    Map<String, DartObjectImpl> fields = _assertType(result, "A");
-    expect(fields, hasLength(1));
-    _assertIntField(fields, "i", 123);
-  }
-
-  void test_fromEnvironment_bool_default_false() {
-    expect(_assertValidBool(_check_fromEnvironment_bool(null, "false")), false);
-  }
-
-  void test_fromEnvironment_bool_default_overridden() {
-    expect(
-        _assertValidBool(_check_fromEnvironment_bool("false", "true")), false);
-  }
-
-  void test_fromEnvironment_bool_default_parseError() {
-    expect(_assertValidBool(_check_fromEnvironment_bool("parseError", "true")),
-        true);
-  }
-
-  void test_fromEnvironment_bool_default_true() {
-    expect(_assertValidBool(_check_fromEnvironment_bool(null, "true")), true);
-  }
-
-  void test_fromEnvironment_bool_false() {
-    expect(_assertValidBool(_check_fromEnvironment_bool("false", null)), false);
-  }
-
-  void test_fromEnvironment_bool_parseError() {
-    expect(_assertValidBool(_check_fromEnvironment_bool("parseError", null)),
-        false);
-  }
-
-  void test_fromEnvironment_bool_true() {
-    expect(_assertValidBool(_check_fromEnvironment_bool("true", null)), true);
-  }
-
-  void test_fromEnvironment_bool_undeclared() {
-    _assertValidUnknown(_check_fromEnvironment_bool(null, null));
-  }
-
-  void test_fromEnvironment_int_default_overridden() {
-    expect(_assertValidInt(_check_fromEnvironment_int("234", "123")), 234);
-  }
-
-  void test_fromEnvironment_int_default_parseError() {
-    expect(
-        _assertValidInt(_check_fromEnvironment_int("parseError", "123")), 123);
-  }
-
-  void test_fromEnvironment_int_default_undeclared() {
-    expect(_assertValidInt(_check_fromEnvironment_int(null, "123")), 123);
-  }
-
-  void test_fromEnvironment_int_ok() {
-    expect(_assertValidInt(_check_fromEnvironment_int("234", null)), 234);
-  }
-
-  void test_fromEnvironment_int_parseError() {
-    _assertValidNull(_check_fromEnvironment_int("parseError", null));
-  }
-
-  void test_fromEnvironment_int_parseError_nullDefault() {
-    _assertValidNull(_check_fromEnvironment_int("parseError", "null"));
-  }
-
-  void test_fromEnvironment_int_undeclared() {
-    _assertValidUnknown(_check_fromEnvironment_int(null, null));
-  }
-
-  void test_fromEnvironment_int_undeclared_nullDefault() {
-    _assertValidNull(_check_fromEnvironment_int(null, "null"));
-  }
-
-  void test_fromEnvironment_string_default_overridden() {
-    expect(_assertValidString(_check_fromEnvironment_string("abc", "'def'")),
-        "abc");
-  }
-
-  void test_fromEnvironment_string_default_undeclared() {
-    expect(_assertValidString(_check_fromEnvironment_string(null, "'def'")),
-        "def");
-  }
-
-  void test_fromEnvironment_string_empty() {
-    expect(_assertValidString(_check_fromEnvironment_string("", null)), "");
-  }
-
-  void test_fromEnvironment_string_ok() {
-    expect(
-        _assertValidString(_check_fromEnvironment_string("abc", null)), "abc");
-  }
-
-  void test_fromEnvironment_string_undeclared() {
-    _assertValidUnknown(_check_fromEnvironment_string(null, null));
-  }
-
-  void test_fromEnvironment_string_undeclared_nullDefault() {
-    _assertValidNull(_check_fromEnvironment_string(null, "null"));
-  }
-
-  void test_instanceCreationExpression_computedField() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A(4, 5);
-class A {
-  const A(int i, int j) : k = 2 * i + j;
-  final int k;
-}''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "foo");
-    Map<String, DartObjectImpl> fields = _assertType(result, "A");
-    expect(fields, hasLength(1));
-    _assertIntField(fields, "k", 13);
-  }
-
-  void
-      test_instanceCreationExpression_computedField_namedOptionalWithDefault() {
-    _checkInstanceCreationOptionalParams(false, true, true);
-  }
-
-  void
-      test_instanceCreationExpression_computedField_namedOptionalWithoutDefault() {
-    _checkInstanceCreationOptionalParams(false, true, false);
-  }
-
-  void
-      test_instanceCreationExpression_computedField_unnamedOptionalWithDefault() {
-    _checkInstanceCreationOptionalParams(false, false, true);
-  }
-
-  void
-      test_instanceCreationExpression_computedField_unnamedOptionalWithoutDefault() {
-    _checkInstanceCreationOptionalParams(false, false, false);
-  }
-
-  void test_instanceCreationExpression_computedField_usesConstConstructor() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A(3);
-class A {
-  const A(int i) : b = const B(4);
-  final int b;
-}
-class B {
-  const B(this.k);
-  final int k;
-}''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "foo");
-    Map<String, DartObjectImpl> fieldsOfA = _assertType(result, "A");
-    expect(fieldsOfA, hasLength(1));
-    Map<String, DartObjectImpl> fieldsOfB =
-        _assertFieldType(fieldsOfA, "b", "B");
-    expect(fieldsOfB, hasLength(1));
-    _assertIntField(fieldsOfB, "k", 4);
-  }
-
-  void test_instanceCreationExpression_computedField_usesStaticConst() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A(3);
-class A {
-  const A(int i) : k = i + B.bar;
-  final int k;
-}
-class B {
-  static const bar = 4;
-}''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "foo");
-    Map<String, DartObjectImpl> fields = _assertType(result, "A");
-    expect(fields, hasLength(1));
-    _assertIntField(fields, "k", 7);
-  }
-
-  void test_instanceCreationExpression_computedField_usesTopLevelConst() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A(3);
-const bar = 4;
-class A {
-  const A(int i) : k = i + bar;
-  final int k;
-}''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "foo");
-    Map<String, DartObjectImpl> fields = _assertType(result, "A");
-    expect(fields, hasLength(1));
-    _assertIntField(fields, "k", 7);
-  }
-
-  void test_instanceCreationExpression_explicitSuper() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const B(4, 5);
-class A {
-  const A(this.x);
-  final int x;
-}
-class B extends A {
-  const B(int x, this.y) : super(x * 2);
-  final int y;
-}''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "foo");
-    Map<String, DartObjectImpl> fields = _assertType(result, "B");
-    expect(fields, hasLength(2));
-    _assertIntField(fields, "y", 5);
-    Map<String, DartObjectImpl> superclassFields =
-        _assertFieldType(fields, GenericState.SUPERCLASS_FIELD, "A");
-    expect(superclassFields, hasLength(1));
-    _assertIntField(superclassFields, "x", 8);
-  }
-
-  void test_instanceCreationExpression_fieldFormalParameter() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A(42);
-class A {
-  int x;
-  const A(this.x)
-}''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "foo");
-    Map<String, DartObjectImpl> fields = _assertType(result, "A");
-    expect(fields, hasLength(1));
-    _assertIntField(fields, "x", 42);
-  }
-
-  void
-      test_instanceCreationExpression_fieldFormalParameter_namedOptionalWithDefault() {
-    _checkInstanceCreationOptionalParams(true, true, true);
-  }
-
-  void
-      test_instanceCreationExpression_fieldFormalParameter_namedOptionalWithoutDefault() {
-    _checkInstanceCreationOptionalParams(true, true, false);
-  }
-
-  void
-      test_instanceCreationExpression_fieldFormalParameter_unnamedOptionalWithDefault() {
-    _checkInstanceCreationOptionalParams(true, false, true);
-  }
-
-  void
-      test_instanceCreationExpression_fieldFormalParameter_unnamedOptionalWithoutDefault() {
-    _checkInstanceCreationOptionalParams(true, false, false);
-  }
-
-  void test_instanceCreationExpression_implicitSuper() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const B(4);
-class A {
-  const A() : x = 3;
-  final int x;
-}
-class B extends A {
-  const B(this.y);
-  final int y;
-}''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "foo");
-    Map<String, DartObjectImpl> fields = _assertType(result, "B");
-    expect(fields, hasLength(2));
-    _assertIntField(fields, "y", 4);
-    Map<String, DartObjectImpl> superclassFields =
-        _assertFieldType(fields, GenericState.SUPERCLASS_FIELD, "A");
-    expect(superclassFields, hasLength(1));
-    _assertIntField(superclassFields, "x", 3);
-  }
-
-  void test_instanceCreationExpression_nonFactoryRedirect() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1();
-class A {
-  const A.a1() : this.a2();
-  const A.a2() : x = 5;
-  final int x;
-}''');
-    Map<String, DartObjectImpl> aFields =
-        _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
-    _assertIntField(aFields, 'x', 5);
-  }
-
-  void test_instanceCreationExpression_nonFactoryRedirect_arg() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1(1);
-class A {
-  const A.a1(x) : this.a2(x + 100);
-  const A.a2(x) : y = x + 10;
-  final int y;
-}''');
-    Map<String, DartObjectImpl> aFields =
-        _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
-    _assertIntField(aFields, 'y', 111);
-  }
-
-  void test_instanceCreationExpression_nonFactoryRedirect_cycle() {
-    // It is an error to have a cycle in non-factory redirects; however, we
-    // need to make sure that even if the error occurs, attempting to evaluate
-    // the constant will terminate.
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A();
-class A {
-  const A() : this.b();
-  const A.b() : this();
-}''');
-    _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
-  }
-
-  void test_instanceCreationExpression_nonFactoryRedirect_defaultArg() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1();
-class A {
-  const A.a1() : this.a2();
-  const A.a2([x = 100]) : y = x + 10;
-  final int y;
-}''');
-    Map<String, DartObjectImpl> aFields =
-        _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
-    _assertIntField(aFields, 'y', 110);
-  }
-
-  void test_instanceCreationExpression_nonFactoryRedirect_toMissing() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1();
-class A {
-  const A.a1() : this.a2();
-}''');
-    // We don't care what value foo evaluates to (since there is a compile
-    // error), but we shouldn't crash, and we should figure
-    // out that it evaluates to an instance of class A.
-    _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
-  }
-
-  void test_instanceCreationExpression_nonFactoryRedirect_toNonConst() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1();
-class A {
-  const A.a1() : this.a2();
-  A.a2();
-}''');
-    // We don't care what value foo evaluates to (since there is a compile
-    // error), but we shouldn't crash, and we should figure
-    // out that it evaluates to an instance of class A.
-    _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
-  }
-
-  void test_instanceCreationExpression_nonFactoryRedirect_unnamed() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1();
-class A {
-  const A.a1() : this();
-  const A() : x = 5;
-  final int x;
-}''');
-    Map<String, DartObjectImpl> aFields =
-        _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
-    _assertIntField(aFields, 'x', 5);
-  }
-
-  void test_instanceCreationExpression_redirect() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A();
-class A {
-  const factory A() = B;
-}
-class B implements A {
-  const B();
-}''');
-    _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "B");
-  }
-
-  void test_instanceCreationExpression_redirect_cycle() {
-    // It is an error to have a cycle in factory redirects; however, we need
-    // to make sure that even if the error occurs, attempting to evaluate the
-    // constant will terminate.
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A();
-class A {
-  const factory A() = A.b;
-  const factory A.b() = A;
-}''');
-    _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
-  }
-
-  void test_instanceCreationExpression_redirect_external() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A();
-class A {
-  external const factory A();
-}''');
-    _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
-  }
-
-  void test_instanceCreationExpression_redirect_nonConst() {
-    // It is an error for a const factory constructor redirect to a non-const
-    // constructor; however, we need to make sure that even if the error
-    // attempting to evaluate the constant won't cause a crash.
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A();
-class A {
-  const factory A() = A.b;
-  A.b();
-}''');
-    _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
-  }
-
-  void test_instanceCreationExpression_redirectWithTypeParams() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A {
-  const factory A(var a) = B<int>;
-}
-
-class B<T> implements A {
-  final T x;
-  const B(this.x);
-}
-
-const A a = const A(10);''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "a");
-    Map<String, DartObjectImpl> fields = _assertType(result, "B<int>");
-    expect(fields, hasLength(1));
-    _assertIntField(fields, "x", 10);
-  }
-
-  void test_instanceCreationExpression_redirectWithTypeSubstitution() {
-    // To evaluate the redirection of A<int>,
-    // A's template argument (T=int) must be substituted
-    // into B's template argument (B<U> where U=T) to get B<int>.
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A<T> {
-  const factory A(var a) = B<T>;
-}
-
-class B<U> implements A {
-  final U x;
-  const B(this.x);
-}
-
-const A<int> a = const A<int>(10);''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "a");
-    Map<String, DartObjectImpl> fields = _assertType(result, "B<int>");
-    expect(fields, hasLength(1));
-    _assertIntField(fields, "x", 10);
-  }
-
-  void test_instanceCreationExpression_symbol() {
-    CompilationUnit compilationUnit =
-        resolveSource("const foo = const Symbol('a');");
-    EvaluationResultImpl evaluationResult =
-        _evaluateTopLevelVariable(compilationUnit, "foo");
-    expect(evaluationResult.value, isNotNull);
-    DartObjectImpl value = evaluationResult.value;
-    expect(value.type, typeProvider.symbolType);
-    expect(value.toSymbolValue(), "a");
-  }
-
-  void test_instanceCreationExpression_withSupertypeParams_explicit() {
-    _checkInstanceCreation_withSupertypeParams(true);
-  }
-
-  void test_instanceCreationExpression_withSupertypeParams_implicit() {
-    _checkInstanceCreation_withSupertypeParams(false);
-  }
-
-  void test_instanceCreationExpression_withTypeParams() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-class C<E> {
-  const C();
-}
-const c_int = const C<int>();
-const c_num = const C<num>();''');
-    EvaluationResultImpl c_int =
-        _evaluateTopLevelVariable(compilationUnit, "c_int");
-    _assertType(c_int, "C<int>");
-    DartObjectImpl c_int_value = c_int.value;
-    EvaluationResultImpl c_num =
-        _evaluateTopLevelVariable(compilationUnit, "c_num");
-    _assertType(c_num, "C<num>");
-    DartObjectImpl c_num_value = c_num.value;
-    expect(c_int_value == c_num_value, isFalse);
-  }
-
-  void test_isValidSymbol() {
-    expect(ConstantEvaluationEngine.isValidPublicSymbol(""), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.bar"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo\$"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo\$bar"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("iff"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("gif"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("if\$"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("\$if"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo="), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.bar="), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.+"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("void"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("_foo"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("_foo.bar"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo._bar"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("if"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("if.foo"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.if"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo=.bar"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo."), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("+.foo"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("void.foo"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.void"), isFalse);
-  }
-
-  void test_length_of_improperly_typed_string_expression() {
-    // Since type annotations are ignored in unchecked mode, the improper
-    // types on s1 and s2 shouldn't prevent us from evaluating i to
-    // 'alpha'.length.
-    CompilationUnit compilationUnit = resolveSource('''
-const int s1 = 'alpha';
-const int s2 = 'beta';
-const int i = (true ? s1 : s2).length;
-''');
-    ConstTopLevelVariableElementImpl element =
-        findTopLevelDeclaration(compilationUnit, 'i').element;
-    EvaluationResultImpl result = element.evaluationResult;
-    expect(_assertValidInt(result), 5);
-  }
-
-  void test_length_of_improperly_typed_string_identifier() {
-    // Since type annotations are ignored in unchecked mode, the improper type
-    // on s shouldn't prevent us from evaluating i to 'alpha'.length.
-    CompilationUnit compilationUnit = resolveSource('''
-const int s = 'alpha';
-const int i = s.length;
-''');
-    ConstTopLevelVariableElementImpl element =
-        findTopLevelDeclaration(compilationUnit, 'i').element;
-    EvaluationResultImpl result = element.evaluationResult;
-    expect(_assertValidInt(result), 5);
-  }
-
-  void test_non_static_const_initialized_at_declaration() {
-    // Even though non-static consts are not allowed by the language, we need
-    // to handle them for error recovery purposes.
-    CompilationUnit compilationUnit = resolveSource('''
-class A {
-  const int i = 123;
-  const A();
-}
-
-const A a = const A();
-''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, 'a');
-    Map<String, DartObjectImpl> fields = _assertType(result, "A");
-    expect(fields, hasLength(1));
-    _assertIntField(fields, "i", 123);
-  }
-
-  void test_symbolLiteral_void() {
-    CompilationUnit compilationUnit =
-        resolveSource("const voidSymbol = #void;");
-    VariableDeclaration voidSymbol =
-        findTopLevelDeclaration(compilationUnit, "voidSymbol");
-    EvaluationResultImpl voidSymbolResult =
-        (voidSymbol.element as VariableElementImpl).evaluationResult;
-    DartObjectImpl value = voidSymbolResult.value;
-    expect(value.type, typeProvider.symbolType);
-    expect(value.toSymbolValue(), "void");
-  }
-
-  Map<String, DartObjectImpl> _assertFieldType(
-      Map<String, DartObjectImpl> fields,
-      String fieldName,
-      String expectedType) {
-    DartObjectImpl field = fields[fieldName];
-    expect(field.type.displayName, expectedType);
-    return field.fields;
-  }
-
-  void _assertIntField(
-      Map<String, DartObjectImpl> fields, String fieldName, int expectedValue) {
-    DartObjectImpl field = fields[fieldName];
-    expect(field.type.name, "int");
-    expect(field.toIntValue(), expectedValue);
-  }
-
-  void _assertNullField(Map<String, DartObjectImpl> fields, String fieldName) {
-    DartObjectImpl field = fields[fieldName];
-    expect(field.isNull, isTrue);
-  }
-
-  void _assertProperDependencies(String sourceText,
-      [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) {
-    Source source = addSource(sourceText);
-    LibraryElement element = resolve2(source);
-    CompilationUnit unit =
-        analysisContext.resolveCompilationUnit(source, element);
-    expect(unit, isNotNull);
-    ConstantValueComputer computer = _makeConstantValueComputer();
-    computer.add(unit, source, source);
-    computer.computeValues();
-    assertErrors(source, expectedErrorCodes);
-  }
-
-  Map<String, DartObjectImpl> _assertType(
-      EvaluationResultImpl result, String typeName) {
-    expect(result.value, isNotNull);
-    DartObjectImpl value = result.value;
-    expect(value.type.displayName, typeName);
-    return value.fields;
-  }
-
-  bool _assertValidBool(EvaluationResultImpl result) {
-    expect(result.value, isNotNull);
-    DartObjectImpl value = result.value;
-    expect(value.type, typeProvider.boolType);
-    bool boolValue = value.toBoolValue();
-    expect(boolValue, isNotNull);
-    return boolValue;
-  }
-
-  int _assertValidInt(EvaluationResultImpl result) {
-    expect(result, isNotNull);
-    expect(result.value, isNotNull);
-    DartObjectImpl value = result.value;
-    expect(value.type, typeProvider.intType);
-    return value.toIntValue();
-  }
-
-  void _assertValidNull(EvaluationResultImpl result) {
-    expect(result.value, isNotNull);
-    DartObjectImpl value = result.value;
-    expect(value.type, typeProvider.nullType);
-  }
-
-  String _assertValidString(EvaluationResultImpl result) {
-    expect(result.value, isNotNull);
-    DartObjectImpl value = result.value;
-    expect(value.type, typeProvider.stringType);
-    return value.toStringValue();
-  }
-
-  void _assertValidUnknown(EvaluationResultImpl result) {
-    expect(result.value, isNotNull);
-    DartObjectImpl value = result.value;
-    expect(value.isUnknown, isTrue);
-  }
-
-  EvaluationResultImpl _check_fromEnvironment_bool(
-      String valueInEnvironment, String defaultExpr) {
-    String envVarName = "x";
-    String varName = "foo";
-    if (valueInEnvironment != null) {
-      analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
-    }
-    String defaultArg =
-        defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
-    CompilationUnit compilationUnit = resolveSource(
-        "const $varName = const bool.fromEnvironment('$envVarName'$defaultArg);");
-    return _evaluateTopLevelVariable(compilationUnit, varName);
-  }
-
-  EvaluationResultImpl _check_fromEnvironment_int(
-      String valueInEnvironment, String defaultExpr) {
-    String envVarName = "x";
-    String varName = "foo";
-    if (valueInEnvironment != null) {
-      analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
-    }
-    String defaultArg =
-        defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
-    CompilationUnit compilationUnit = resolveSource(
-        "const $varName = const int.fromEnvironment('$envVarName'$defaultArg);");
-    return _evaluateTopLevelVariable(compilationUnit, varName);
-  }
-
-  EvaluationResultImpl _check_fromEnvironment_string(
-      String valueInEnvironment, String defaultExpr) {
-    String envVarName = "x";
-    String varName = "foo";
-    if (valueInEnvironment != null) {
-      analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
-    }
-    String defaultArg =
-        defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
-    CompilationUnit compilationUnit = resolveSource(
-        "const $varName = const String.fromEnvironment('$envVarName'$defaultArg);");
-    return _evaluateTopLevelVariable(compilationUnit, varName);
-  }
-
-  void _checkInstanceCreation_withSupertypeParams(bool isExplicit) {
-    String superCall = isExplicit ? " : super()" : "";
-    CompilationUnit compilationUnit = resolveSource("""
-class A<T> {
-  const A();
-}
-class B<T, U> extends A<T> {
-  const B()$superCall;
-}
-class C<T, U> extends A<U> {
-  const C()$superCall;
-}
-const b_int_num = const B<int, num>();
-const c_int_num = const C<int, num>();""");
-    EvaluationResultImpl b_int_num =
-        _evaluateTopLevelVariable(compilationUnit, "b_int_num");
-    Map<String, DartObjectImpl> b_int_num_fields =
-        _assertType(b_int_num, "B<int, num>");
-    _assertFieldType(b_int_num_fields, GenericState.SUPERCLASS_FIELD, "A<int>");
-    EvaluationResultImpl c_int_num =
-        _evaluateTopLevelVariable(compilationUnit, "c_int_num");
-    Map<String, DartObjectImpl> c_int_num_fields =
-        _assertType(c_int_num, "C<int, num>");
-    _assertFieldType(c_int_num_fields, GenericState.SUPERCLASS_FIELD, "A<num>");
-  }
-
-  void _checkInstanceCreationOptionalParams(
-      bool isFieldFormal, bool isNamed, bool hasDefault) {
-    String fieldName = "j";
-    String paramName = isFieldFormal ? fieldName : "i";
-    String formalParam =
-        "${isFieldFormal ? "this." : "int "}$paramName${hasDefault ? " = 3" : ""}";
-    CompilationUnit compilationUnit = resolveSource("""
-const x = const A();
-const y = const A(${isNamed ? '$paramName: ' : ''}10);
-class A {
-  const A(${isNamed ? "{$formalParam}" : "[$formalParam]"})${isFieldFormal ? "" : " : $fieldName = $paramName"};
-  final int $fieldName;
-}""");
-    EvaluationResultImpl x = _evaluateTopLevelVariable(compilationUnit, "x");
-    Map<String, DartObjectImpl> fieldsOfX = _assertType(x, "A");
-    expect(fieldsOfX, hasLength(1));
-    if (hasDefault) {
-      _assertIntField(fieldsOfX, fieldName, 3);
-    } else {
-      _assertNullField(fieldsOfX, fieldName);
-    }
-    EvaluationResultImpl y = _evaluateTopLevelVariable(compilationUnit, "y");
-    Map<String, DartObjectImpl> fieldsOfY = _assertType(y, "A");
-    expect(fieldsOfY, hasLength(1));
-    _assertIntField(fieldsOfY, fieldName, 10);
-  }
-
-  /**
-   * Search [compilationUnit] for a class named [className], containing a
-   * method [methodName], with exactly one annotation.  Return the constant
-   * value of the annotation.
-   */
-  EvaluationResultImpl _evaluateAnnotation(
-      CompilationUnit compilationUnit, String className, String memberName) {
-    for (CompilationUnitMember member in compilationUnit.declarations) {
-      if (member is ClassDeclaration && member.name.name == className) {
-        for (ClassMember classMember in member.members) {
-          if (classMember is MethodDeclaration &&
-              classMember.name.name == memberName) {
-            expect(classMember.metadata, hasLength(1));
-            ElementAnnotationImpl elementAnnotation =
-                classMember.metadata[0].elementAnnotation;
-            return elementAnnotation.evaluationResult;
-          }
-        }
-      }
-    }
-    fail('Class member not found');
-    return null;
-  }
-
-  EvaluationResultImpl _evaluateTopLevelVariable(
-      CompilationUnit compilationUnit, String name) {
-    VariableDeclaration varDecl =
-        findTopLevelDeclaration(compilationUnit, name);
-    ConstTopLevelVariableElementImpl varElement = varDecl.element;
-    return varElement.evaluationResult;
-  }
-
-  ConstantValueComputer _makeConstantValueComputer() {
-    ConstantEvaluationValidator_ForTest validator =
-        new ConstantEvaluationValidator_ForTest(analysisContext2);
-    validator.computer = new ConstantValueComputer(
-        analysisContext2,
-        analysisContext2.typeProvider,
-        analysisContext2.declaredVariables,
-        validator,
-        analysisContext2.typeSystem);
-    return validator.computer;
-  }
-
-  void _validate(bool shouldBeValid, VariableDeclarationList declarationList) {
-    for (VariableDeclaration declaration in declarationList.variables) {
-      VariableElementImpl element = declaration.element as VariableElementImpl;
-      expect(element, isNotNull);
-      EvaluationResultImpl result = element.evaluationResult;
-      if (shouldBeValid) {
-        expect(result.value, isNotNull);
-      } else {
-        expect(result.value, isNull);
-      }
-    }
-  }
-}
-
-@reflectiveTest
-class ConstantVisitorTest extends ResolverTestCase {
-  void test_visitBinaryExpression_questionQuestion_notNull_notNull() {
-    Expression left = AstFactory.string2('a');
-    Expression right = AstFactory.string2('b');
-    Expression expression =
-        AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right);
-
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    DartObjectImpl result = _evaluate(expression, errorReporter);
-    expect(result, isNotNull);
-    expect(result.isNull, isFalse);
-    expect(result.toStringValue(), 'a');
-    errorListener.assertNoErrors();
-  }
-
-  void test_visitBinaryExpression_questionQuestion_null_notNull() {
-    Expression left = AstFactory.nullLiteral();
-    Expression right = AstFactory.string2('b');
-    Expression expression =
-        AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right);
-
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    DartObjectImpl result = _evaluate(expression, errorReporter);
-    expect(result, isNotNull);
-    expect(result.isNull, isFalse);
-    expect(result.toStringValue(), 'b');
-    errorListener.assertNoErrors();
-  }
-
-  void test_visitBinaryExpression_questionQuestion_null_null() {
-    Expression left = AstFactory.nullLiteral();
-    Expression right = AstFactory.nullLiteral();
-    Expression expression =
-        AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right);
-
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    DartObjectImpl result = _evaluate(expression, errorReporter);
-    expect(result, isNotNull);
-    expect(result.isNull, isTrue);
-    errorListener.assertNoErrors();
-  }
-
-  void test_visitConditionalExpression_false() {
-    Expression thenExpression = AstFactory.integer(1);
-    Expression elseExpression = AstFactory.integer(0);
-    ConditionalExpression expression = AstFactory.conditionalExpression(
-        AstFactory.booleanLiteral(false), thenExpression, elseExpression);
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    _assertValue(0, _evaluate(expression, errorReporter));
-    errorListener.assertNoErrors();
-  }
-
-  void test_visitConditionalExpression_nonBooleanCondition() {
-    Expression thenExpression = AstFactory.integer(1);
-    Expression elseExpression = AstFactory.integer(0);
-    NullLiteral conditionExpression = AstFactory.nullLiteral();
-    ConditionalExpression expression = AstFactory.conditionalExpression(
-        conditionExpression, thenExpression, elseExpression);
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    DartObjectImpl result = _evaluate(expression, errorReporter);
-    expect(result, isNull);
-    errorListener
-        .assertErrorsWithCodes([CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL]);
-  }
-
-  void test_visitConditionalExpression_nonConstantElse() {
-    Expression thenExpression = AstFactory.integer(1);
-    Expression elseExpression = AstFactory.identifier3("x");
-    ConditionalExpression expression = AstFactory.conditionalExpression(
-        AstFactory.booleanLiteral(true), thenExpression, elseExpression);
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    DartObjectImpl result = _evaluate(expression, errorReporter);
-    expect(result, isNull);
-    errorListener
-        .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]);
-  }
-
-  void test_visitConditionalExpression_nonConstantThen() {
-    Expression thenExpression = AstFactory.identifier3("x");
-    Expression elseExpression = AstFactory.integer(0);
-    ConditionalExpression expression = AstFactory.conditionalExpression(
-        AstFactory.booleanLiteral(true), thenExpression, elseExpression);
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    DartObjectImpl result = _evaluate(expression, errorReporter);
-    expect(result, isNull);
-    errorListener
-        .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]);
-  }
-
-  void test_visitConditionalExpression_true() {
-    Expression thenExpression = AstFactory.integer(1);
-    Expression elseExpression = AstFactory.integer(0);
-    ConditionalExpression expression = AstFactory.conditionalExpression(
-        AstFactory.booleanLiteral(true), thenExpression, elseExpression);
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    _assertValue(1, _evaluate(expression, errorReporter));
-    errorListener.assertNoErrors();
-  }
-
-  void test_visitSimpleIdentifier_className() {
-    CompilationUnit compilationUnit = resolveSource('''
-const a = C;
-class C {}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null);
-    expect(result.type, typeProvider.typeType);
-    expect(result.toTypeValue().name, 'C');
-  }
-
-  void test_visitSimpleIdentifier_dynamic() {
-    CompilationUnit compilationUnit = resolveSource('''
-const a = dynamic;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null);
-    expect(result.type, typeProvider.typeType);
-    expect(result.toTypeValue(), typeProvider.dynamicType);
-  }
-
-  void test_visitSimpleIdentifier_inEnvironment() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const a = b;
-const b = 3;''');
-    Map<String, DartObjectImpl> environment = new Map<String, DartObjectImpl>();
-    DartObjectImpl six =
-        new DartObjectImpl(typeProvider.intType, new IntState(6));
-    environment["b"] = six;
-    _assertValue(6, _evaluateConstant(compilationUnit, "a", environment));
-  }
-
-  void test_visitSimpleIdentifier_notInEnvironment() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const a = b;
-const b = 3;''');
-    Map<String, DartObjectImpl> environment = new Map<String, DartObjectImpl>();
-    DartObjectImpl six =
-        new DartObjectImpl(typeProvider.intType, new IntState(6));
-    environment["c"] = six;
-    _assertValue(3, _evaluateConstant(compilationUnit, "a", environment));
-  }
-
-  void test_visitSimpleIdentifier_withoutEnvironment() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const a = b;
-const b = 3;''');
-    _assertValue(3, _evaluateConstant(compilationUnit, "a", null));
-  }
-
-  void _assertValue(int expectedValue, DartObjectImpl result) {
-    expect(result, isNotNull);
-    expect(result.type.name, "int");
-    expect(result.toIntValue(), expectedValue);
-  }
-
-  NonExistingSource _dummySource() {
-    String path = '/test.dart';
-    return new NonExistingSource(path, toUri(path), UriKind.FILE_URI);
-  }
-
-  DartObjectImpl _evaluate(Expression expression, ErrorReporter errorReporter) {
-    return expression.accept(new ConstantVisitor(
-        new ConstantEvaluationEngine(
-            new TestTypeProvider(), new DeclaredVariables(),
-            typeSystem: new TypeSystemImpl()),
-        errorReporter));
-  }
-
-  DartObjectImpl _evaluateConstant(CompilationUnit compilationUnit, String name,
-      Map<String, DartObjectImpl> lexicalEnvironment) {
-    Source source = compilationUnit.element.source;
-    Expression expression =
-        findTopLevelConstantExpression(compilationUnit, name);
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
-    DartObjectImpl result = expression.accept(new ConstantVisitor(
-        new ConstantEvaluationEngine(typeProvider, new DeclaredVariables(),
-            typeSystem: typeSystem),
-        errorReporter,
-        lexicalEnvironment: lexicalEnvironment));
-    errorListener.assertNoErrors();
-    return result;
-  }
-}
-
-@reflectiveTest
-class DartObjectImplTest extends EngineTestCase {
-  TypeProvider _typeProvider = new TestTypeProvider();
-
-  void test_add_knownDouble_knownDouble() {
-    _assertAdd(_doubleValue(3.0), _doubleValue(1.0), _doubleValue(2.0));
-  }
-
-  void test_add_knownDouble_knownInt() {
-    _assertAdd(_doubleValue(3.0), _doubleValue(1.0), _intValue(2));
-  }
-
-  void test_add_knownDouble_unknownDouble() {
-    _assertAdd(_doubleValue(null), _doubleValue(1.0), _doubleValue(null));
-  }
-
-  void test_add_knownDouble_unknownInt() {
-    _assertAdd(_doubleValue(null), _doubleValue(1.0), _intValue(null));
-  }
-
-  void test_add_knownInt_knownInt() {
-    _assertAdd(_intValue(3), _intValue(1), _intValue(2));
-  }
-
-  void test_add_knownInt_knownString() {
-    _assertAdd(null, _intValue(1), _stringValue("2"));
-  }
-
-  void test_add_knownInt_unknownDouble() {
-    _assertAdd(_doubleValue(null), _intValue(1), _doubleValue(null));
-  }
-
-  void test_add_knownInt_unknownInt() {
-    _assertAdd(_intValue(null), _intValue(1), _intValue(null));
-  }
-
-  void test_add_knownString_knownInt() {
-    _assertAdd(null, _stringValue("1"), _intValue(2));
-  }
-
-  void test_add_knownString_knownString() {
-    _assertAdd(_stringValue("ab"), _stringValue("a"), _stringValue("b"));
-  }
-
-  void test_add_knownString_unknownString() {
-    _assertAdd(_stringValue(null), _stringValue("a"), _stringValue(null));
-  }
-
-  void test_add_unknownDouble_knownDouble() {
-    _assertAdd(_doubleValue(null), _doubleValue(null), _doubleValue(2.0));
-  }
-
-  void test_add_unknownDouble_knownInt() {
-    _assertAdd(_doubleValue(null), _doubleValue(null), _intValue(2));
-  }
-
-  void test_add_unknownInt_knownDouble() {
-    _assertAdd(_doubleValue(null), _intValue(null), _doubleValue(2.0));
-  }
-
-  void test_add_unknownInt_knownInt() {
-    _assertAdd(_intValue(null), _intValue(null), _intValue(2));
-  }
-
-  void test_add_unknownString_knownString() {
-    _assertAdd(_stringValue(null), _stringValue(null), _stringValue("b"));
-  }
-
-  void test_add_unknownString_unknownString() {
-    _assertAdd(_stringValue(null), _stringValue(null), _stringValue(null));
-  }
-
-  void test_bitAnd_knownInt_knownInt() {
-    _assertBitAnd(_intValue(2), _intValue(6), _intValue(3));
-  }
-
-  void test_bitAnd_knownInt_knownString() {
-    _assertBitAnd(null, _intValue(6), _stringValue("3"));
-  }
-
-  void test_bitAnd_knownInt_unknownInt() {
-    _assertBitAnd(_intValue(null), _intValue(6), _intValue(null));
-  }
-
-  void test_bitAnd_knownString_knownInt() {
-    _assertBitAnd(null, _stringValue("6"), _intValue(3));
-  }
-
-  void test_bitAnd_unknownInt_knownInt() {
-    _assertBitAnd(_intValue(null), _intValue(null), _intValue(3));
-  }
-
-  void test_bitAnd_unknownInt_unknownInt() {
-    _assertBitAnd(_intValue(null), _intValue(null), _intValue(null));
-  }
-
-  void test_bitNot_knownInt() {
-    _assertBitNot(_intValue(-4), _intValue(3));
-  }
-
-  void test_bitNot_knownString() {
-    _assertBitNot(null, _stringValue("6"));
-  }
-
-  void test_bitNot_unknownInt() {
-    _assertBitNot(_intValue(null), _intValue(null));
-  }
-
-  void test_bitOr_knownInt_knownInt() {
-    _assertBitOr(_intValue(7), _intValue(6), _intValue(3));
-  }
-
-  void test_bitOr_knownInt_knownString() {
-    _assertBitOr(null, _intValue(6), _stringValue("3"));
-  }
-
-  void test_bitOr_knownInt_unknownInt() {
-    _assertBitOr(_intValue(null), _intValue(6), _intValue(null));
-  }
-
-  void test_bitOr_knownString_knownInt() {
-    _assertBitOr(null, _stringValue("6"), _intValue(3));
-  }
-
-  void test_bitOr_unknownInt_knownInt() {
-    _assertBitOr(_intValue(null), _intValue(null), _intValue(3));
-  }
-
-  void test_bitOr_unknownInt_unknownInt() {
-    _assertBitOr(_intValue(null), _intValue(null), _intValue(null));
-  }
-
-  void test_bitXor_knownInt_knownInt() {
-    _assertBitXor(_intValue(5), _intValue(6), _intValue(3));
-  }
-
-  void test_bitXor_knownInt_knownString() {
-    _assertBitXor(null, _intValue(6), _stringValue("3"));
-  }
-
-  void test_bitXor_knownInt_unknownInt() {
-    _assertBitXor(_intValue(null), _intValue(6), _intValue(null));
-  }
-
-  void test_bitXor_knownString_knownInt() {
-    _assertBitXor(null, _stringValue("6"), _intValue(3));
-  }
-
-  void test_bitXor_unknownInt_knownInt() {
-    _assertBitXor(_intValue(null), _intValue(null), _intValue(3));
-  }
-
-  void test_bitXor_unknownInt_unknownInt() {
-    _assertBitXor(_intValue(null), _intValue(null), _intValue(null));
-  }
-
-  void test_concatenate_knownInt_knownString() {
-    _assertConcatenate(null, _intValue(2), _stringValue("def"));
-  }
-
-  void test_concatenate_knownString_knownInt() {
-    _assertConcatenate(null, _stringValue("abc"), _intValue(3));
-  }
-
-  void test_concatenate_knownString_knownString() {
-    _assertConcatenate(
-        _stringValue("abcdef"), _stringValue("abc"), _stringValue("def"));
-  }
-
-  void test_concatenate_knownString_unknownString() {
-    _assertConcatenate(
-        _stringValue(null), _stringValue("abc"), _stringValue(null));
-  }
-
-  void test_concatenate_unknownString_knownString() {
-    _assertConcatenate(
-        _stringValue(null), _stringValue(null), _stringValue("def"));
-  }
-
-  void test_divide_knownDouble_knownDouble() {
-    _assertDivide(_doubleValue(3.0), _doubleValue(6.0), _doubleValue(2.0));
-  }
-
-  void test_divide_knownDouble_knownInt() {
-    _assertDivide(_doubleValue(3.0), _doubleValue(6.0), _intValue(2));
-  }
-
-  void test_divide_knownDouble_unknownDouble() {
-    _assertDivide(_doubleValue(null), _doubleValue(6.0), _doubleValue(null));
-  }
-
-  void test_divide_knownDouble_unknownInt() {
-    _assertDivide(_doubleValue(null), _doubleValue(6.0), _intValue(null));
-  }
-
-  void test_divide_knownInt_knownInt() {
-    _assertDivide(_doubleValue(3.0), _intValue(6), _intValue(2));
-  }
-
-  void test_divide_knownInt_knownString() {
-    _assertDivide(null, _intValue(6), _stringValue("2"));
-  }
-
-  void test_divide_knownInt_unknownDouble() {
-    _assertDivide(_doubleValue(null), _intValue(6), _doubleValue(null));
-  }
-
-  void test_divide_knownInt_unknownInt() {
-    _assertDivide(_doubleValue(null), _intValue(6), _intValue(null));
-  }
-
-  void test_divide_knownString_knownInt() {
-    _assertDivide(null, _stringValue("6"), _intValue(2));
-  }
-
-  void test_divide_unknownDouble_knownDouble() {
-    _assertDivide(_doubleValue(null), _doubleValue(null), _doubleValue(2.0));
-  }
-
-  void test_divide_unknownDouble_knownInt() {
-    _assertDivide(_doubleValue(null), _doubleValue(null), _intValue(2));
-  }
-
-  void test_divide_unknownInt_knownDouble() {
-    _assertDivide(_doubleValue(null), _intValue(null), _doubleValue(2.0));
-  }
-
-  void test_divide_unknownInt_knownInt() {
-    _assertDivide(_doubleValue(null), _intValue(null), _intValue(2));
-  }
-
-  void test_equalEqual_bool_false() {
-    _assertEqualEqual(_boolValue(false), _boolValue(false), _boolValue(true));
-  }
-
-  void test_equalEqual_bool_true() {
-    _assertEqualEqual(_boolValue(true), _boolValue(true), _boolValue(true));
-  }
-
-  void test_equalEqual_bool_unknown() {
-    _assertEqualEqual(_boolValue(null), _boolValue(null), _boolValue(false));
-  }
-
-  void test_equalEqual_double_false() {
-    _assertEqualEqual(_boolValue(false), _doubleValue(2.0), _doubleValue(4.0));
-  }
-
-  void test_equalEqual_double_true() {
-    _assertEqualEqual(_boolValue(true), _doubleValue(2.0), _doubleValue(2.0));
-  }
-
-  void test_equalEqual_double_unknown() {
-    _assertEqualEqual(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
-  }
-
-  void test_equalEqual_int_false() {
-    _assertEqualEqual(_boolValue(false), _intValue(-5), _intValue(5));
-  }
-
-  void test_equalEqual_int_true() {
-    _assertEqualEqual(_boolValue(true), _intValue(5), _intValue(5));
-  }
-
-  void test_equalEqual_int_unknown() {
-    _assertEqualEqual(_boolValue(null), _intValue(null), _intValue(3));
-  }
-
-  void test_equalEqual_list_empty() {
-    _assertEqualEqual(null, _listValue(), _listValue());
-  }
-
-  void test_equalEqual_list_false() {
-    _assertEqualEqual(null, _listValue(), _listValue());
-  }
-
-  void test_equalEqual_map_empty() {
-    _assertEqualEqual(null, _mapValue(), _mapValue());
-  }
-
-  void test_equalEqual_map_false() {
-    _assertEqualEqual(null, _mapValue(), _mapValue());
-  }
-
-  void test_equalEqual_null() {
-    _assertEqualEqual(_boolValue(true), _nullValue(), _nullValue());
-  }
-
-  void test_equalEqual_string_false() {
-    _assertEqualEqual(
-        _boolValue(false), _stringValue("abc"), _stringValue("def"));
-  }
-
-  void test_equalEqual_string_true() {
-    _assertEqualEqual(
-        _boolValue(true), _stringValue("abc"), _stringValue("abc"));
-  }
-
-  void test_equalEqual_string_unknown() {
-    _assertEqualEqual(
-        _boolValue(null), _stringValue(null), _stringValue("def"));
-  }
-
-  void test_equals_list_false_differentSizes() {
-    expect(
-        _listValue([_boolValue(true)]) ==
-            _listValue([_boolValue(true), _boolValue(false)]),
-        isFalse);
-  }
-
-  void test_equals_list_false_sameSize() {
-    expect(_listValue([_boolValue(true)]) == _listValue([_boolValue(false)]),
-        isFalse);
-  }
-
-  void test_equals_list_true_empty() {
-    expect(_listValue(), _listValue());
-  }
-
-  void test_equals_list_true_nonEmpty() {
-    expect(_listValue([_boolValue(true)]), _listValue([_boolValue(true)]));
-  }
-
-  void test_equals_map_true_empty() {
-    expect(_mapValue(), _mapValue());
-  }
-
-  void test_equals_symbol_false() {
-    expect(_symbolValue("a") == _symbolValue("b"), isFalse);
-  }
-
-  void test_equals_symbol_true() {
-    expect(_symbolValue("a"), _symbolValue("a"));
-  }
-
-  void test_getValue_bool_false() {
-    expect(_boolValue(false).toBoolValue(), false);
-  }
-
-  void test_getValue_bool_true() {
-    expect(_boolValue(true).toBoolValue(), true);
-  }
-
-  void test_getValue_bool_unknown() {
-    expect(_boolValue(null).toBoolValue(), isNull);
-  }
-
-  void test_getValue_double_known() {
-    double value = 2.3;
-    expect(_doubleValue(value).toDoubleValue(), value);
-  }
-
-  void test_getValue_double_unknown() {
-    expect(_doubleValue(null).toDoubleValue(), isNull);
-  }
-
-  void test_getValue_int_known() {
-    int value = 23;
-    expect(_intValue(value).toIntValue(), value);
-  }
-
-  void test_getValue_int_unknown() {
-    expect(_intValue(null).toIntValue(), isNull);
-  }
-
-  void test_getValue_list_empty() {
-    Object result = _listValue().toListValue();
-    _assertInstanceOfObjectArray(result);
-    List<Object> array = result as List<Object>;
-    expect(array, hasLength(0));
-  }
-
-  void test_getValue_list_valid() {
-    Object result = _listValue([_intValue(23)]).toListValue();
-    _assertInstanceOfObjectArray(result);
-    List<Object> array = result as List<Object>;
-    expect(array, hasLength(1));
-  }
-
-  void test_getValue_map_empty() {
-    Object result = _mapValue().toMapValue();
-    EngineTestCase.assertInstanceOf((obj) => obj is Map, Map, result);
-    Map map = result as Map;
-    expect(map, hasLength(0));
-  }
-
-  void test_getValue_map_valid() {
-    Object result =
-        _mapValue([_stringValue("key"), _stringValue("value")]).toMapValue();
-    EngineTestCase.assertInstanceOf((obj) => obj is Map, Map, result);
-    Map map = result as Map;
-    expect(map, hasLength(1));
-  }
-
-  void test_getValue_null() {
-    expect(_nullValue().isNull, isTrue);
-  }
-
-  void test_getValue_string_known() {
-    String value = "twenty-three";
-    expect(_stringValue(value).toStringValue(), value);
-  }
-
-  void test_getValue_string_unknown() {
-    expect(_stringValue(null).toStringValue(), isNull);
-  }
-
-  void test_greaterThan_knownDouble_knownDouble_false() {
-    _assertGreaterThan(_boolValue(false), _doubleValue(1.0), _doubleValue(2.0));
-  }
-
-  void test_greaterThan_knownDouble_knownDouble_true() {
-    _assertGreaterThan(_boolValue(true), _doubleValue(2.0), _doubleValue(1.0));
-  }
-
-  void test_greaterThan_knownDouble_knownInt_false() {
-    _assertGreaterThan(_boolValue(false), _doubleValue(1.0), _intValue(2));
-  }
-
-  void test_greaterThan_knownDouble_knownInt_true() {
-    _assertGreaterThan(_boolValue(true), _doubleValue(2.0), _intValue(1));
-  }
-
-  void test_greaterThan_knownDouble_unknownDouble() {
-    _assertGreaterThan(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
-  }
-
-  void test_greaterThan_knownDouble_unknownInt() {
-    _assertGreaterThan(_boolValue(null), _doubleValue(1.0), _intValue(null));
-  }
-
-  void test_greaterThan_knownInt_knownInt_false() {
-    _assertGreaterThan(_boolValue(false), _intValue(1), _intValue(2));
-  }
-
-  void test_greaterThan_knownInt_knownInt_true() {
-    _assertGreaterThan(_boolValue(true), _intValue(2), _intValue(1));
-  }
-
-  void test_greaterThan_knownInt_knownString() {
-    _assertGreaterThan(null, _intValue(1), _stringValue("2"));
-  }
-
-  void test_greaterThan_knownInt_unknownDouble() {
-    _assertGreaterThan(_boolValue(null), _intValue(1), _doubleValue(null));
-  }
-
-  void test_greaterThan_knownInt_unknownInt() {
-    _assertGreaterThan(_boolValue(null), _intValue(1), _intValue(null));
-  }
-
-  void test_greaterThan_knownString_knownInt() {
-    _assertGreaterThan(null, _stringValue("1"), _intValue(2));
-  }
-
-  void test_greaterThan_unknownDouble_knownDouble() {
-    _assertGreaterThan(_boolValue(null), _doubleValue(null), _doubleValue(2.0));
-  }
-
-  void test_greaterThan_unknownDouble_knownInt() {
-    _assertGreaterThan(_boolValue(null), _doubleValue(null), _intValue(2));
-  }
-
-  void test_greaterThan_unknownInt_knownDouble() {
-    _assertGreaterThan(_boolValue(null), _intValue(null), _doubleValue(2.0));
-  }
-
-  void test_greaterThan_unknownInt_knownInt() {
-    _assertGreaterThan(_boolValue(null), _intValue(null), _intValue(2));
-  }
-
-  void test_greaterThanOrEqual_knownDouble_knownDouble_false() {
-    _assertGreaterThanOrEqual(
-        _boolValue(false), _doubleValue(1.0), _doubleValue(2.0));
-  }
-
-  void test_greaterThanOrEqual_knownDouble_knownDouble_true() {
-    _assertGreaterThanOrEqual(
-        _boolValue(true), _doubleValue(2.0), _doubleValue(1.0));
-  }
-
-  void test_greaterThanOrEqual_knownDouble_knownInt_false() {
-    _assertGreaterThanOrEqual(
-        _boolValue(false), _doubleValue(1.0), _intValue(2));
-  }
-
-  void test_greaterThanOrEqual_knownDouble_knownInt_true() {
-    _assertGreaterThanOrEqual(
-        _boolValue(true), _doubleValue(2.0), _intValue(1));
-  }
-
-  void test_greaterThanOrEqual_knownDouble_unknownDouble() {
-    _assertGreaterThanOrEqual(
-        _boolValue(null), _doubleValue(1.0), _doubleValue(null));
-  }
-
-  void test_greaterThanOrEqual_knownDouble_unknownInt() {
-    _assertGreaterThanOrEqual(
-        _boolValue(null), _doubleValue(1.0), _intValue(null));
-  }
-
-  void test_greaterThanOrEqual_knownInt_knownInt_false() {
-    _assertGreaterThanOrEqual(_boolValue(false), _intValue(1), _intValue(2));
-  }
-
-  void test_greaterThanOrEqual_knownInt_knownInt_true() {
-    _assertGreaterThanOrEqual(_boolValue(true), _intValue(2), _intValue(2));
-  }
-
-  void test_greaterThanOrEqual_knownInt_knownString() {
-    _assertGreaterThanOrEqual(null, _intValue(1), _stringValue("2"));
-  }
-
-  void test_greaterThanOrEqual_knownInt_unknownDouble() {
-    _assertGreaterThanOrEqual(
-        _boolValue(null), _intValue(1), _doubleValue(null));
-  }
-
-  void test_greaterThanOrEqual_knownInt_unknownInt() {
-    _assertGreaterThanOrEqual(_boolValue(null), _intValue(1), _intValue(null));
-  }
-
-  void test_greaterThanOrEqual_knownString_knownInt() {
-    _assertGreaterThanOrEqual(null, _stringValue("1"), _intValue(2));
-  }
-
-  void test_greaterThanOrEqual_unknownDouble_knownDouble() {
-    _assertGreaterThanOrEqual(
-        _boolValue(null), _doubleValue(null), _doubleValue(2.0));
-  }
-
-  void test_greaterThanOrEqual_unknownDouble_knownInt() {
-    _assertGreaterThanOrEqual(
-        _boolValue(null), _doubleValue(null), _intValue(2));
-  }
-
-  void test_greaterThanOrEqual_unknownInt_knownDouble() {
-    _assertGreaterThanOrEqual(
-        _boolValue(null), _intValue(null), _doubleValue(2.0));
-  }
-
-  void test_greaterThanOrEqual_unknownInt_knownInt() {
-    _assertGreaterThanOrEqual(_boolValue(null), _intValue(null), _intValue(2));
-  }
-
-  void test_hasKnownValue_bool_false() {
-    expect(_boolValue(false).hasKnownValue, isTrue);
-  }
-
-  void test_hasKnownValue_bool_true() {
-    expect(_boolValue(true).hasKnownValue, isTrue);
-  }
-
-  void test_hasKnownValue_bool_unknown() {
-    expect(_boolValue(null).hasKnownValue, isFalse);
-  }
-
-  void test_hasKnownValue_double_known() {
-    expect(_doubleValue(2.3).hasKnownValue, isTrue);
-  }
-
-  void test_hasKnownValue_double_unknown() {
-    expect(_doubleValue(null).hasKnownValue, isFalse);
-  }
-
-  void test_hasKnownValue_dynamic() {
-    expect(_dynamicValue().hasKnownValue, isTrue);
-  }
-
-  void test_hasKnownValue_int_known() {
-    expect(_intValue(23).hasKnownValue, isTrue);
-  }
-
-  void test_hasKnownValue_int_unknown() {
-    expect(_intValue(null).hasKnownValue, isFalse);
-  }
-
-  void test_hasKnownValue_list_empty() {
-    expect(_listValue().hasKnownValue, isTrue);
-  }
-
-  void test_hasKnownValue_list_invalidElement() {
-    expect(_listValue([_dynamicValue]).hasKnownValue, isTrue);
-  }
-
-  void test_hasKnownValue_list_valid() {
-    expect(_listValue([_intValue(23)]).hasKnownValue, isTrue);
-  }
-
-  void test_hasKnownValue_map_empty() {
-    expect(_mapValue().hasKnownValue, isTrue);
-  }
-
-  void test_hasKnownValue_map_invalidKey() {
-    expect(_mapValue([_dynamicValue(), _stringValue("value")]).hasKnownValue,
-        isTrue);
-  }
-
-  void test_hasKnownValue_map_invalidValue() {
-    expect(_mapValue([_stringValue("key"), _dynamicValue()]).hasKnownValue,
-        isTrue);
-  }
-
-  void test_hasKnownValue_map_valid() {
-    expect(
-        _mapValue([_stringValue("key"), _stringValue("value")]).hasKnownValue,
-        isTrue);
-  }
-
-  void test_hasKnownValue_null() {
-    expect(_nullValue().hasKnownValue, isTrue);
-  }
-
-  void test_hasKnownValue_num() {
-    expect(_numValue().hasKnownValue, isFalse);
-  }
-
-  void test_hasKnownValue_string_known() {
-    expect(_stringValue("twenty-three").hasKnownValue, isTrue);
-  }
-
-  void test_hasKnownValue_string_unknown() {
-    expect(_stringValue(null).hasKnownValue, isFalse);
-  }
-
-  void test_identical_bool_false() {
-    _assertIdentical(_boolValue(false), _boolValue(false), _boolValue(true));
-  }
-
-  void test_identical_bool_true() {
-    _assertIdentical(_boolValue(true), _boolValue(true), _boolValue(true));
-  }
-
-  void test_identical_bool_unknown() {
-    _assertIdentical(_boolValue(null), _boolValue(null), _boolValue(false));
-  }
-
-  void test_identical_double_false() {
-    _assertIdentical(_boolValue(false), _doubleValue(2.0), _doubleValue(4.0));
-  }
-
-  void test_identical_double_true() {
-    _assertIdentical(_boolValue(true), _doubleValue(2.0), _doubleValue(2.0));
-  }
-
-  void test_identical_double_unknown() {
-    _assertIdentical(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
-  }
-
-  void test_identical_int_false() {
-    _assertIdentical(_boolValue(false), _intValue(-5), _intValue(5));
-  }
-
-  void test_identical_int_true() {
-    _assertIdentical(_boolValue(true), _intValue(5), _intValue(5));
-  }
-
-  void test_identical_int_unknown() {
-    _assertIdentical(_boolValue(null), _intValue(null), _intValue(3));
-  }
-
-  void test_identical_list_empty() {
-    _assertIdentical(_boolValue(true), _listValue(), _listValue());
-  }
-
-  void test_identical_list_false() {
-    _assertIdentical(
-        _boolValue(false), _listValue(), _listValue([_intValue(3)]));
-  }
-
-  void test_identical_map_empty() {
-    _assertIdentical(_boolValue(true), _mapValue(), _mapValue());
-  }
-
-  void test_identical_map_false() {
-    _assertIdentical(_boolValue(false), _mapValue(),
-        _mapValue([_intValue(1), _intValue(2)]));
-  }
-
-  void test_identical_null() {
-    _assertIdentical(_boolValue(true), _nullValue(), _nullValue());
-  }
-
-  void test_identical_string_false() {
-    _assertIdentical(
-        _boolValue(false), _stringValue("abc"), _stringValue("def"));
-  }
-
-  void test_identical_string_true() {
-    _assertIdentical(
-        _boolValue(true), _stringValue("abc"), _stringValue("abc"));
-  }
-
-  void test_identical_string_unknown() {
-    _assertIdentical(_boolValue(null), _stringValue(null), _stringValue("def"));
-  }
-
-  void test_integerDivide_knownDouble_knownDouble() {
-    _assertIntegerDivide(_intValue(3), _doubleValue(6.0), _doubleValue(2.0));
-  }
-
-  void test_integerDivide_knownDouble_knownInt() {
-    _assertIntegerDivide(_intValue(3), _doubleValue(6.0), _intValue(2));
-  }
-
-  void test_integerDivide_knownDouble_unknownDouble() {
-    _assertIntegerDivide(
-        _intValue(null), _doubleValue(6.0), _doubleValue(null));
-  }
-
-  void test_integerDivide_knownDouble_unknownInt() {
-    _assertIntegerDivide(_intValue(null), _doubleValue(6.0), _intValue(null));
-  }
-
-  void test_integerDivide_knownInt_knownInt() {
-    _assertIntegerDivide(_intValue(3), _intValue(6), _intValue(2));
-  }
-
-  void test_integerDivide_knownInt_knownString() {
-    _assertIntegerDivide(null, _intValue(6), _stringValue("2"));
-  }
-
-  void test_integerDivide_knownInt_unknownDouble() {
-    _assertIntegerDivide(_intValue(null), _intValue(6), _doubleValue(null));
-  }
-
-  void test_integerDivide_knownInt_unknownInt() {
-    _assertIntegerDivide(_intValue(null), _intValue(6), _intValue(null));
-  }
-
-  void test_integerDivide_knownString_knownInt() {
-    _assertIntegerDivide(null, _stringValue("6"), _intValue(2));
-  }
-
-  void test_integerDivide_unknownDouble_knownDouble() {
-    _assertIntegerDivide(
-        _intValue(null), _doubleValue(null), _doubleValue(2.0));
-  }
-
-  void test_integerDivide_unknownDouble_knownInt() {
-    _assertIntegerDivide(_intValue(null), _doubleValue(null), _intValue(2));
-  }
-
-  void test_integerDivide_unknownInt_knownDouble() {
-    _assertIntegerDivide(_intValue(null), _intValue(null), _doubleValue(2.0));
-  }
-
-  void test_integerDivide_unknownInt_knownInt() {
-    _assertIntegerDivide(_intValue(null), _intValue(null), _intValue(2));
-  }
-
-  void test_isBoolNumStringOrNull_bool_false() {
-    expect(_boolValue(false).isBoolNumStringOrNull, isTrue);
-  }
-
-  void test_isBoolNumStringOrNull_bool_true() {
-    expect(_boolValue(true).isBoolNumStringOrNull, isTrue);
-  }
-
-  void test_isBoolNumStringOrNull_bool_unknown() {
-    expect(_boolValue(null).isBoolNumStringOrNull, isTrue);
-  }
-
-  void test_isBoolNumStringOrNull_double_known() {
-    expect(_doubleValue(2.3).isBoolNumStringOrNull, isTrue);
-  }
-
-  void test_isBoolNumStringOrNull_double_unknown() {
-    expect(_doubleValue(null).isBoolNumStringOrNull, isTrue);
-  }
-
-  void test_isBoolNumStringOrNull_dynamic() {
-    expect(_dynamicValue().isBoolNumStringOrNull, isTrue);
-  }
-
-  void test_isBoolNumStringOrNull_int_known() {
-    expect(_intValue(23).isBoolNumStringOrNull, isTrue);
-  }
-
-  void test_isBoolNumStringOrNull_int_unknown() {
-    expect(_intValue(null).isBoolNumStringOrNull, isTrue);
-  }
-
-  void test_isBoolNumStringOrNull_list() {
-    expect(_listValue().isBoolNumStringOrNull, isFalse);
-  }
-
-  void test_isBoolNumStringOrNull_null() {
-    expect(_nullValue().isBoolNumStringOrNull, isTrue);
-  }
-
-  void test_isBoolNumStringOrNull_num() {
-    expect(_numValue().isBoolNumStringOrNull, isTrue);
-  }
-
-  void test_isBoolNumStringOrNull_string_known() {
-    expect(_stringValue("twenty-three").isBoolNumStringOrNull, isTrue);
-  }
-
-  void test_isBoolNumStringOrNull_string_unknown() {
-    expect(_stringValue(null).isBoolNumStringOrNull, isTrue);
-  }
-
-  void test_lessThan_knownDouble_knownDouble_false() {
-    _assertLessThan(_boolValue(false), _doubleValue(2.0), _doubleValue(1.0));
-  }
-
-  void test_lessThan_knownDouble_knownDouble_true() {
-    _assertLessThan(_boolValue(true), _doubleValue(1.0), _doubleValue(2.0));
-  }
-
-  void test_lessThan_knownDouble_knownInt_false() {
-    _assertLessThan(_boolValue(false), _doubleValue(2.0), _intValue(1));
-  }
-
-  void test_lessThan_knownDouble_knownInt_true() {
-    _assertLessThan(_boolValue(true), _doubleValue(1.0), _intValue(2));
-  }
-
-  void test_lessThan_knownDouble_unknownDouble() {
-    _assertLessThan(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
-  }
-
-  void test_lessThan_knownDouble_unknownInt() {
-    _assertLessThan(_boolValue(null), _doubleValue(1.0), _intValue(null));
-  }
-
-  void test_lessThan_knownInt_knownInt_false() {
-    _assertLessThan(_boolValue(false), _intValue(2), _intValue(1));
-  }
-
-  void test_lessThan_knownInt_knownInt_true() {
-    _assertLessThan(_boolValue(true), _intValue(1), _intValue(2));
-  }
-
-  void test_lessThan_knownInt_knownString() {
-    _assertLessThan(null, _intValue(1), _stringValue("2"));
-  }
-
-  void test_lessThan_knownInt_unknownDouble() {
-    _assertLessThan(_boolValue(null), _intValue(1), _doubleValue(null));
-  }
-
-  void test_lessThan_knownInt_unknownInt() {
-    _assertLessThan(_boolValue(null), _intValue(1), _intValue(null));
-  }
-
-  void test_lessThan_knownString_knownInt() {
-    _assertLessThan(null, _stringValue("1"), _intValue(2));
-  }
-
-  void test_lessThan_unknownDouble_knownDouble() {
-    _assertLessThan(_boolValue(null), _doubleValue(null), _doubleValue(2.0));
-  }
-
-  void test_lessThan_unknownDouble_knownInt() {
-    _assertLessThan(_boolValue(null), _doubleValue(null), _intValue(2));
-  }
-
-  void test_lessThan_unknownInt_knownDouble() {
-    _assertLessThan(_boolValue(null), _intValue(null), _doubleValue(2.0));
-  }
-
-  void test_lessThan_unknownInt_knownInt() {
-    _assertLessThan(_boolValue(null), _intValue(null), _intValue(2));
-  }
-
-  void test_lessThanOrEqual_knownDouble_knownDouble_false() {
-    _assertLessThanOrEqual(
-        _boolValue(false), _doubleValue(2.0), _doubleValue(1.0));
-  }
-
-  void test_lessThanOrEqual_knownDouble_knownDouble_true() {
-    _assertLessThanOrEqual(
-        _boolValue(true), _doubleValue(1.0), _doubleValue(2.0));
-  }
-
-  void test_lessThanOrEqual_knownDouble_knownInt_false() {
-    _assertLessThanOrEqual(_boolValue(false), _doubleValue(2.0), _intValue(1));
-  }
-
-  void test_lessThanOrEqual_knownDouble_knownInt_true() {
-    _assertLessThanOrEqual(_boolValue(true), _doubleValue(1.0), _intValue(2));
-  }
-
-  void test_lessThanOrEqual_knownDouble_unknownDouble() {
-    _assertLessThanOrEqual(
-        _boolValue(null), _doubleValue(1.0), _doubleValue(null));
-  }
-
-  void test_lessThanOrEqual_knownDouble_unknownInt() {
-    _assertLessThanOrEqual(
-        _boolValue(null), _doubleValue(1.0), _intValue(null));
-  }
-
-  void test_lessThanOrEqual_knownInt_knownInt_false() {
-    _assertLessThanOrEqual(_boolValue(false), _intValue(2), _intValue(1));
-  }
-
-  void test_lessThanOrEqual_knownInt_knownInt_true() {
-    _assertLessThanOrEqual(_boolValue(true), _intValue(1), _intValue(2));
-  }
-
-  void test_lessThanOrEqual_knownInt_knownString() {
-    _assertLessThanOrEqual(null, _intValue(1), _stringValue("2"));
-  }
-
-  void test_lessThanOrEqual_knownInt_unknownDouble() {
-    _assertLessThanOrEqual(_boolValue(null), _intValue(1), _doubleValue(null));
-  }
-
-  void test_lessThanOrEqual_knownInt_unknownInt() {
-    _assertLessThanOrEqual(_boolValue(null), _intValue(1), _intValue(null));
-  }
-
-  void test_lessThanOrEqual_knownString_knownInt() {
-    _assertLessThanOrEqual(null, _stringValue("1"), _intValue(2));
-  }
-
-  void test_lessThanOrEqual_unknownDouble_knownDouble() {
-    _assertLessThanOrEqual(
-        _boolValue(null), _doubleValue(null), _doubleValue(2.0));
-  }
-
-  void test_lessThanOrEqual_unknownDouble_knownInt() {
-    _assertLessThanOrEqual(_boolValue(null), _doubleValue(null), _intValue(2));
-  }
-
-  void test_lessThanOrEqual_unknownInt_knownDouble() {
-    _assertLessThanOrEqual(
-        _boolValue(null), _intValue(null), _doubleValue(2.0));
-  }
-
-  void test_lessThanOrEqual_unknownInt_knownInt() {
-    _assertLessThanOrEqual(_boolValue(null), _intValue(null), _intValue(2));
-  }
-
-  void test_logicalAnd_false_false() {
-    _assertLogicalAnd(_boolValue(false), _boolValue(false), _boolValue(false));
-  }
-
-  void test_logicalAnd_false_null() {
-    try {
-      _assertLogicalAnd(_boolValue(false), _boolValue(false), _nullValue());
-      fail("Expected EvaluationException");
-    } on EvaluationException {}
-  }
-
-  void test_logicalAnd_false_string() {
-    try {
-      _assertLogicalAnd(
-          _boolValue(false), _boolValue(false), _stringValue("false"));
-      fail("Expected EvaluationException");
-    } on EvaluationException {}
-  }
-
-  void test_logicalAnd_false_true() {
-    _assertLogicalAnd(_boolValue(false), _boolValue(false), _boolValue(true));
-  }
-
-  void test_logicalAnd_null_false() {
-    try {
-      _assertLogicalAnd(_boolValue(false), _nullValue(), _boolValue(false));
-      fail("Expected EvaluationException");
-    } on EvaluationException {}
-  }
-
-  void test_logicalAnd_null_true() {
-    try {
-      _assertLogicalAnd(_boolValue(false), _nullValue(), _boolValue(true));
-      fail("Expected EvaluationException");
-    } on EvaluationException {}
-  }
-
-  void test_logicalAnd_string_false() {
-    try {
-      _assertLogicalAnd(
-          _boolValue(false), _stringValue("true"), _boolValue(false));
-      fail("Expected EvaluationException");
-    } on EvaluationException {}
-  }
-
-  void test_logicalAnd_string_true() {
-    try {
-      _assertLogicalAnd(
-          _boolValue(false), _stringValue("false"), _boolValue(true));
-      fail("Expected EvaluationException");
-    } on EvaluationException {}
-  }
-
-  void test_logicalAnd_true_false() {
-    _assertLogicalAnd(_boolValue(false), _boolValue(true), _boolValue(false));
-  }
-
-  void test_logicalAnd_true_null() {
-    _assertLogicalAnd(null, _boolValue(true), _nullValue());
-  }
-
-  void test_logicalAnd_true_string() {
-    try {
-      _assertLogicalAnd(
-          _boolValue(false), _boolValue(true), _stringValue("true"));
-      fail("Expected EvaluationException");
-    } on EvaluationException {}
-  }
-
-  void test_logicalAnd_true_true() {
-    _assertLogicalAnd(_boolValue(true), _boolValue(true), _boolValue(true));
-  }
-
-  void test_logicalNot_false() {
-    _assertLogicalNot(_boolValue(true), _boolValue(false));
-  }
-
-  void test_logicalNot_null() {
-    _assertLogicalNot(null, _nullValue());
-  }
-
-  void test_logicalNot_string() {
-    try {
-      _assertLogicalNot(_boolValue(true), _stringValue(null));
-      fail("Expected EvaluationException");
-    } on EvaluationException {}
-  }
-
-  void test_logicalNot_true() {
-    _assertLogicalNot(_boolValue(false), _boolValue(true));
-  }
-
-  void test_logicalNot_unknown() {
-    _assertLogicalNot(_boolValue(null), _boolValue(null));
-  }
-
-  void test_logicalOr_false_false() {
-    _assertLogicalOr(_boolValue(false), _boolValue(false), _boolValue(false));
-  }
-
-  void test_logicalOr_false_null() {
-    _assertLogicalOr(null, _boolValue(false), _nullValue());
-  }
-
-  void test_logicalOr_false_string() {
-    try {
-      _assertLogicalOr(
-          _boolValue(false), _boolValue(false), _stringValue("false"));
-      fail("Expected EvaluationException");
-    } on EvaluationException {}
-  }
-
-  void test_logicalOr_false_true() {
-    _assertLogicalOr(_boolValue(true), _boolValue(false), _boolValue(true));
-  }
-
-  void test_logicalOr_null_false() {
-    try {
-      _assertLogicalOr(_boolValue(false), _nullValue(), _boolValue(false));
-      fail("Expected EvaluationException");
-    } on EvaluationException {}
-  }
-
-  void test_logicalOr_null_true() {
-    try {
-      _assertLogicalOr(_boolValue(true), _nullValue(), _boolValue(true));
-      fail("Expected EvaluationException");
-    } on EvaluationException {}
-  }
-
-  void test_logicalOr_string_false() {
-    try {
-      _assertLogicalOr(
-          _boolValue(false), _stringValue("true"), _boolValue(false));
-      fail("Expected EvaluationException");
-    } on EvaluationException {}
-  }
-
-  void test_logicalOr_string_true() {
-    try {
-      _assertLogicalOr(
-          _boolValue(true), _stringValue("false"), _boolValue(true));
-      fail("Expected EvaluationException");
-    } on EvaluationException {}
-  }
-
-  void test_logicalOr_true_false() {
-    _assertLogicalOr(_boolValue(true), _boolValue(true), _boolValue(false));
-  }
-
-  void test_logicalOr_true_null() {
-    try {
-      _assertLogicalOr(_boolValue(true), _boolValue(true), _nullValue());
-      fail("Expected EvaluationException");
-    } on EvaluationException {}
-  }
-
-  void test_logicalOr_true_string() {
-    try {
-      _assertLogicalOr(
-          _boolValue(true), _boolValue(true), _stringValue("true"));
-      fail("Expected EvaluationException");
-    } on EvaluationException {}
-  }
-
-  void test_logicalOr_true_true() {
-    _assertLogicalOr(_boolValue(true), _boolValue(true), _boolValue(true));
-  }
-
-  void test_minus_knownDouble_knownDouble() {
-    _assertMinus(_doubleValue(1.0), _doubleValue(4.0), _doubleValue(3.0));
-  }
-
-  void test_minus_knownDouble_knownInt() {
-    _assertMinus(_doubleValue(1.0), _doubleValue(4.0), _intValue(3));
-  }
-
-  void test_minus_knownDouble_unknownDouble() {
-    _assertMinus(_doubleValue(null), _doubleValue(4.0), _doubleValue(null));
-  }
-
-  void test_minus_knownDouble_unknownInt() {
-    _assertMinus(_doubleValue(null), _doubleValue(4.0), _intValue(null));
-  }
-
-  void test_minus_knownInt_knownInt() {
-    _assertMinus(_intValue(1), _intValue(4), _intValue(3));
-  }
-
-  void test_minus_knownInt_knownString() {
-    _assertMinus(null, _intValue(4), _stringValue("3"));
-  }
-
-  void test_minus_knownInt_unknownDouble() {
-    _assertMinus(_doubleValue(null), _intValue(4), _doubleValue(null));
-  }
-
-  void test_minus_knownInt_unknownInt() {
-    _assertMinus(_intValue(null), _intValue(4), _intValue(null));
-  }
-
-  void test_minus_knownString_knownInt() {
-    _assertMinus(null, _stringValue("4"), _intValue(3));
-  }
-
-  void test_minus_unknownDouble_knownDouble() {
-    _assertMinus(_doubleValue(null), _doubleValue(null), _doubleValue(3.0));
-  }
-
-  void test_minus_unknownDouble_knownInt() {
-    _assertMinus(_doubleValue(null), _doubleValue(null), _intValue(3));
-  }
-
-  void test_minus_unknownInt_knownDouble() {
-    _assertMinus(_doubleValue(null), _intValue(null), _doubleValue(3.0));
-  }
-
-  void test_minus_unknownInt_knownInt() {
-    _assertMinus(_intValue(null), _intValue(null), _intValue(3));
-  }
-
-  void test_negated_double_known() {
-    _assertNegated(_doubleValue(2.0), _doubleValue(-2.0));
-  }
-
-  void test_negated_double_unknown() {
-    _assertNegated(_doubleValue(null), _doubleValue(null));
-  }
-
-  void test_negated_int_known() {
-    _assertNegated(_intValue(-3), _intValue(3));
-  }
-
-  void test_negated_int_unknown() {
-    _assertNegated(_intValue(null), _intValue(null));
-  }
-
-  void test_negated_string() {
-    _assertNegated(null, _stringValue(null));
-  }
-
-  void test_notEqual_bool_false() {
-    _assertNotEqual(_boolValue(false), _boolValue(true), _boolValue(true));
-  }
-
-  void test_notEqual_bool_true() {
-    _assertNotEqual(_boolValue(true), _boolValue(false), _boolValue(true));
-  }
-
-  void test_notEqual_bool_unknown() {
-    _assertNotEqual(_boolValue(null), _boolValue(null), _boolValue(false));
-  }
-
-  void test_notEqual_double_false() {
-    _assertNotEqual(_boolValue(false), _doubleValue(2.0), _doubleValue(2.0));
-  }
-
-  void test_notEqual_double_true() {
-    _assertNotEqual(_boolValue(true), _doubleValue(2.0), _doubleValue(4.0));
-  }
-
-  void test_notEqual_double_unknown() {
-    _assertNotEqual(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
-  }
-
-  void test_notEqual_int_false() {
-    _assertNotEqual(_boolValue(false), _intValue(5), _intValue(5));
-  }
-
-  void test_notEqual_int_true() {
-    _assertNotEqual(_boolValue(true), _intValue(-5), _intValue(5));
-  }
-
-  void test_notEqual_int_unknown() {
-    _assertNotEqual(_boolValue(null), _intValue(null), _intValue(3));
-  }
-
-  void test_notEqual_null() {
-    _assertNotEqual(_boolValue(false), _nullValue(), _nullValue());
-  }
-
-  void test_notEqual_string_false() {
-    _assertNotEqual(
-        _boolValue(false), _stringValue("abc"), _stringValue("abc"));
-  }
-
-  void test_notEqual_string_true() {
-    _assertNotEqual(_boolValue(true), _stringValue("abc"), _stringValue("def"));
-  }
-
-  void test_notEqual_string_unknown() {
-    _assertNotEqual(_boolValue(null), _stringValue(null), _stringValue("def"));
-  }
-
-  void test_performToString_bool_false() {
-    _assertPerformToString(_stringValue("false"), _boolValue(false));
-  }
-
-  void test_performToString_bool_true() {
-    _assertPerformToString(_stringValue("true"), _boolValue(true));
-  }
-
-  void test_performToString_bool_unknown() {
-    _assertPerformToString(_stringValue(null), _boolValue(null));
-  }
-
-  void test_performToString_double_known() {
-    _assertPerformToString(_stringValue("2.0"), _doubleValue(2.0));
-  }
-
-  void test_performToString_double_unknown() {
-    _assertPerformToString(_stringValue(null), _doubleValue(null));
-  }
-
-  void test_performToString_int_known() {
-    _assertPerformToString(_stringValue("5"), _intValue(5));
-  }
-
-  void test_performToString_int_unknown() {
-    _assertPerformToString(_stringValue(null), _intValue(null));
-  }
-
-  void test_performToString_null() {
-    _assertPerformToString(_stringValue("null"), _nullValue());
-  }
-
-  void test_performToString_string_known() {
-    _assertPerformToString(_stringValue("abc"), _stringValue("abc"));
-  }
-
-  void test_performToString_string_unknown() {
-    _assertPerformToString(_stringValue(null), _stringValue(null));
-  }
-
-  void test_remainder_knownDouble_knownDouble() {
-    _assertRemainder(_doubleValue(1.0), _doubleValue(7.0), _doubleValue(2.0));
-  }
-
-  void test_remainder_knownDouble_knownInt() {
-    _assertRemainder(_doubleValue(1.0), _doubleValue(7.0), _intValue(2));
-  }
-
-  void test_remainder_knownDouble_unknownDouble() {
-    _assertRemainder(_doubleValue(null), _doubleValue(7.0), _doubleValue(null));
-  }
-
-  void test_remainder_knownDouble_unknownInt() {
-    _assertRemainder(_doubleValue(null), _doubleValue(6.0), _intValue(null));
-  }
-
-  void test_remainder_knownInt_knownInt() {
-    _assertRemainder(_intValue(1), _intValue(7), _intValue(2));
-  }
-
-  void test_remainder_knownInt_knownString() {
-    _assertRemainder(null, _intValue(7), _stringValue("2"));
-  }
-
-  void test_remainder_knownInt_unknownDouble() {
-    _assertRemainder(_doubleValue(null), _intValue(7), _doubleValue(null));
-  }
-
-  void test_remainder_knownInt_unknownInt() {
-    _assertRemainder(_intValue(null), _intValue(7), _intValue(null));
-  }
-
-  void test_remainder_knownString_knownInt() {
-    _assertRemainder(null, _stringValue("7"), _intValue(2));
-  }
-
-  void test_remainder_unknownDouble_knownDouble() {
-    _assertRemainder(_doubleValue(null), _doubleValue(null), _doubleValue(2.0));
-  }
-
-  void test_remainder_unknownDouble_knownInt() {
-    _assertRemainder(_doubleValue(null), _doubleValue(null), _intValue(2));
-  }
-
-  void test_remainder_unknownInt_knownDouble() {
-    _assertRemainder(_doubleValue(null), _intValue(null), _doubleValue(2.0));
-  }
-
-  void test_remainder_unknownInt_knownInt() {
-    _assertRemainder(_intValue(null), _intValue(null), _intValue(2));
-  }
-
-  void test_shiftLeft_knownInt_knownInt() {
-    _assertShiftLeft(_intValue(48), _intValue(6), _intValue(3));
-  }
-
-  void test_shiftLeft_knownInt_knownString() {
-    _assertShiftLeft(null, _intValue(6), _stringValue(null));
-  }
-
-  void test_shiftLeft_knownInt_tooLarge() {
-    _assertShiftLeft(
-        _intValue(null),
-        _intValue(6),
-        new DartObjectImpl(
-            _typeProvider.intType, new IntState(LONG_MAX_VALUE)));
-  }
-
-  void test_shiftLeft_knownInt_unknownInt() {
-    _assertShiftLeft(_intValue(null), _intValue(6), _intValue(null));
-  }
-
-  void test_shiftLeft_knownString_knownInt() {
-    _assertShiftLeft(null, _stringValue(null), _intValue(3));
-  }
-
-  void test_shiftLeft_unknownInt_knownInt() {
-    _assertShiftLeft(_intValue(null), _intValue(null), _intValue(3));
-  }
-
-  void test_shiftLeft_unknownInt_unknownInt() {
-    _assertShiftLeft(_intValue(null), _intValue(null), _intValue(null));
-  }
-
-  void test_shiftRight_knownInt_knownInt() {
-    _assertShiftRight(_intValue(6), _intValue(48), _intValue(3));
-  }
-
-  void test_shiftRight_knownInt_knownString() {
-    _assertShiftRight(null, _intValue(48), _stringValue(null));
-  }
-
-  void test_shiftRight_knownInt_tooLarge() {
-    _assertShiftRight(
-        _intValue(null),
-        _intValue(48),
-        new DartObjectImpl(
-            _typeProvider.intType, new IntState(LONG_MAX_VALUE)));
-  }
-
-  void test_shiftRight_knownInt_unknownInt() {
-    _assertShiftRight(_intValue(null), _intValue(48), _intValue(null));
-  }
-
-  void test_shiftRight_knownString_knownInt() {
-    _assertShiftRight(null, _stringValue(null), _intValue(3));
-  }
-
-  void test_shiftRight_unknownInt_knownInt() {
-    _assertShiftRight(_intValue(null), _intValue(null), _intValue(3));
-  }
-
-  void test_shiftRight_unknownInt_unknownInt() {
-    _assertShiftRight(_intValue(null), _intValue(null), _intValue(null));
-  }
-
-  void test_stringLength_int() {
-    try {
-      _assertStringLength(_intValue(null), _intValue(0));
-      fail("Expected EvaluationException");
-    } on EvaluationException {}
-  }
-
-  void test_stringLength_knownString() {
-    _assertStringLength(_intValue(3), _stringValue("abc"));
-  }
-
-  void test_stringLength_unknownString() {
-    _assertStringLength(_intValue(null), _stringValue(null));
-  }
-
-  void test_times_knownDouble_knownDouble() {
-    _assertTimes(_doubleValue(6.0), _doubleValue(2.0), _doubleValue(3.0));
-  }
-
-  void test_times_knownDouble_knownInt() {
-    _assertTimes(_doubleValue(6.0), _doubleValue(2.0), _intValue(3));
-  }
-
-  void test_times_knownDouble_unknownDouble() {
-    _assertTimes(_doubleValue(null), _doubleValue(2.0), _doubleValue(null));
-  }
-
-  void test_times_knownDouble_unknownInt() {
-    _assertTimes(_doubleValue(null), _doubleValue(2.0), _intValue(null));
-  }
-
-  void test_times_knownInt_knownInt() {
-    _assertTimes(_intValue(6), _intValue(2), _intValue(3));
-  }
-
-  void test_times_knownInt_knownString() {
-    _assertTimes(null, _intValue(2), _stringValue("3"));
-  }
-
-  void test_times_knownInt_unknownDouble() {
-    _assertTimes(_doubleValue(null), _intValue(2), _doubleValue(null));
-  }
-
-  void test_times_knownInt_unknownInt() {
-    _assertTimes(_intValue(null), _intValue(2), _intValue(null));
-  }
-
-  void test_times_knownString_knownInt() {
-    _assertTimes(null, _stringValue("2"), _intValue(3));
-  }
-
-  void test_times_unknownDouble_knownDouble() {
-    _assertTimes(_doubleValue(null), _doubleValue(null), _doubleValue(3.0));
-  }
-
-  void test_times_unknownDouble_knownInt() {
-    _assertTimes(_doubleValue(null), _doubleValue(null), _intValue(3));
-  }
-
-  void test_times_unknownInt_knownDouble() {
-    _assertTimes(_doubleValue(null), _intValue(null), _doubleValue(3.0));
-  }
-
-  void test_times_unknownInt_knownInt() {
-    _assertTimes(_intValue(null), _intValue(null), _intValue(3));
-  }
-
-  /**
-   * Assert that the result of adding the left and right operands is the expected value, or that the
-   * operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertAdd(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.add(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result = leftOperand.add(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of bit-anding the left and right operands is the expected value, or that
-   * the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertBitAnd(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.bitAnd(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result = leftOperand.bitAnd(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the bit-not of the operand is the expected value, or that the operation throws an
-   * exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param operand the operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertBitNot(DartObjectImpl expected, DartObjectImpl operand) {
-    if (expected == null) {
-      try {
-        operand.bitNot(_typeProvider);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result = operand.bitNot(_typeProvider);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of bit-oring the left and right operands is the expected value, or that
-   * the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertBitOr(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.bitOr(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result = leftOperand.bitOr(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of bit-xoring the left and right operands is the expected value, or that
-   * the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertBitXor(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.bitXor(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result = leftOperand.bitXor(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of concatenating the left and right operands is the expected value, or
-   * that the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertConcatenate(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.concatenate(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result =
-          leftOperand.concatenate(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of dividing the left and right operands is the expected value, or that
-   * the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertDivide(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.divide(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result = leftOperand.divide(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of comparing the left and right operands for equality is the expected
-   * value, or that the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertEqualEqual(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.equalEqual(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result =
-          leftOperand.equalEqual(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of comparing the left and right operands is the expected value, or that
-   * the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertGreaterThan(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.greaterThan(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result =
-          leftOperand.greaterThan(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of comparing the left and right operands is the expected value, or that
-   * the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertGreaterThanOrEqual(DartObjectImpl expected,
-      DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.greaterThanOrEqual(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result =
-          leftOperand.greaterThanOrEqual(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of comparing the left and right operands using
-   * identical() is the expected value.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   */
-  void _assertIdentical(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    DartObjectImpl result =
-        leftOperand.isIdentical(_typeProvider, rightOperand);
-    expect(result, isNotNull);
-    expect(result, expected);
-  }
-
-  void _assertInstanceOfObjectArray(Object result) {
-    // TODO(scheglov) implement
-  }
-
-  /**
-   * Assert that the result of dividing the left and right operands as integers is the expected
-   * value, or that the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertIntegerDivide(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.integerDivide(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result =
-          leftOperand.integerDivide(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of comparing the left and right operands is the expected value, or that
-   * the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertLessThan(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.lessThan(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result = leftOperand.lessThan(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of comparing the left and right operands is the expected value, or that
-   * the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertLessThanOrEqual(DartObjectImpl expected,
-      DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.lessThanOrEqual(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result =
-          leftOperand.lessThanOrEqual(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of logical-anding the left and right operands is the expected value, or
-   * that the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertLogicalAnd(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.logicalAnd(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result =
-          leftOperand.logicalAnd(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the logical-not of the operand is the expected value, or that the operation throws
-   * an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param operand the operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertLogicalNot(DartObjectImpl expected, DartObjectImpl operand) {
-    if (expected == null) {
-      try {
-        operand.logicalNot(_typeProvider);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result = operand.logicalNot(_typeProvider);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of logical-oring the left and right operands is the expected value, or
-   * that the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertLogicalOr(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.logicalOr(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result =
-          leftOperand.logicalOr(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of subtracting the left and right operands is the expected value, or
-   * that the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertMinus(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.minus(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result = leftOperand.minus(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the negation of the operand is the expected value, or that the operation throws an
-   * exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param operand the operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertNegated(DartObjectImpl expected, DartObjectImpl operand) {
-    if (expected == null) {
-      try {
-        operand.negated(_typeProvider);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result = operand.negated(_typeProvider);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of comparing the left and right operands for inequality is the expected
-   * value, or that the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertNotEqual(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.notEqual(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result = leftOperand.notEqual(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that converting the operand to a string is the expected value, or that the operation
-   * throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param operand the operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertPerformToString(DartObjectImpl expected, DartObjectImpl operand) {
-    if (expected == null) {
-      try {
-        operand.performToString(_typeProvider);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result = operand.performToString(_typeProvider);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of taking the remainder of the left and right operands is the expected
-   * value, or that the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertRemainder(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.remainder(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result =
-          leftOperand.remainder(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of multiplying the left and right operands is the expected value, or
-   * that the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertShiftLeft(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.shiftLeft(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result =
-          leftOperand.shiftLeft(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of multiplying the left and right operands is the expected value, or
-   * that the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the right operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertShiftRight(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.shiftRight(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result =
-          leftOperand.shiftRight(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the length of the operand is the expected value, or that the operation throws an
-   * exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param operand the operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertStringLength(DartObjectImpl expected, DartObjectImpl operand) {
-    if (expected == null) {
-      try {
-        operand.stringLength(_typeProvider);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result = operand.stringLength(_typeProvider);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  /**
-   * Assert that the result of multiplying the left and right operands is the expected value, or
-   * that the operation throws an exception if the expected value is `null`.
-   *
-   * @param expected the expected result of the operation
-   * @param leftOperand the left operand to the operation
-   * @param rightOperand the left operand to the operation
-   * @throws EvaluationException if the result is an exception when it should not be
-   */
-  void _assertTimes(DartObjectImpl expected, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand) {
-    if (expected == null) {
-      try {
-        leftOperand.times(_typeProvider, rightOperand);
-        fail("Expected an EvaluationException");
-      } on EvaluationException {}
-    } else {
-      DartObjectImpl result = leftOperand.times(_typeProvider, rightOperand);
-      expect(result, isNotNull);
-      expect(result, expected);
-    }
-  }
-
-  DartObjectImpl _boolValue(bool value) {
-    if (value == null) {
-      return new DartObjectImpl(
-          _typeProvider.boolType, BoolState.UNKNOWN_VALUE);
-    } else if (identical(value, false)) {
-      return new DartObjectImpl(_typeProvider.boolType, BoolState.FALSE_STATE);
-    } else if (identical(value, true)) {
-      return new DartObjectImpl(_typeProvider.boolType, BoolState.TRUE_STATE);
-    }
-    fail("Invalid boolean value used in test");
-    return null;
-  }
-
-  DartObjectImpl _doubleValue(double value) {
-    if (value == null) {
-      return new DartObjectImpl(
-          _typeProvider.doubleType, DoubleState.UNKNOWN_VALUE);
-    } else {
-      return new DartObjectImpl(
-          _typeProvider.doubleType, new DoubleState(value));
-    }
-  }
-
-  DartObjectImpl _dynamicValue() {
-    return new DartObjectImpl(
-        _typeProvider.nullType, DynamicState.DYNAMIC_STATE);
-  }
-
-  DartObjectImpl _intValue(int value) {
-    if (value == null) {
-      return new DartObjectImpl(_typeProvider.intType, IntState.UNKNOWN_VALUE);
-    } else {
-      return new DartObjectImpl(_typeProvider.intType, new IntState(value));
-    }
-  }
-
-  DartObjectImpl _listValue(
-      [List<DartObjectImpl> elements = DartObjectImpl.EMPTY_LIST]) {
-    return new DartObjectImpl(_typeProvider.listType, new ListState(elements));
-  }
-
-  DartObjectImpl _mapValue(
-      [List<DartObjectImpl> keyElementPairs = DartObjectImpl.EMPTY_LIST]) {
-    Map<DartObjectImpl, DartObjectImpl> map =
-        new Map<DartObjectImpl, DartObjectImpl>();
-    int count = keyElementPairs.length;
-    for (int i = 0; i < count;) {
-      map[keyElementPairs[i++]] = keyElementPairs[i++];
-    }
-    return new DartObjectImpl(_typeProvider.mapType, new MapState(map));
-  }
-
-  DartObjectImpl _nullValue() {
-    return new DartObjectImpl(_typeProvider.nullType, NullState.NULL_STATE);
-  }
-
-  DartObjectImpl _numValue() {
-    return new DartObjectImpl(_typeProvider.nullType, NumState.UNKNOWN_VALUE);
-  }
-
-  DartObjectImpl _stringValue(String value) {
-    if (value == null) {
-      return new DartObjectImpl(
-          _typeProvider.stringType, StringState.UNKNOWN_VALUE);
-    } else {
-      return new DartObjectImpl(
-          _typeProvider.stringType, new StringState(value));
-    }
-  }
-
-  DartObjectImpl _symbolValue(String value) {
-    return new DartObjectImpl(_typeProvider.symbolType, new SymbolState(value));
-  }
-}
-
-@reflectiveTest
-class DeclaredVariablesTest extends EngineTestCase {
-  void test_getBool_false() {
-    TestTypeProvider typeProvider = new TestTypeProvider();
-    String variableName = "var";
-    DeclaredVariables variables = new DeclaredVariables();
-    variables.define(variableName, "false");
-    DartObject object = variables.getBool(typeProvider, variableName);
-    expect(object, isNotNull);
-    expect(object.toBoolValue(), false);
-  }
-
-  void test_getBool_invalid() {
-    TestTypeProvider typeProvider = new TestTypeProvider();
-    String variableName = "var";
-    DeclaredVariables variables = new DeclaredVariables();
-    variables.define(variableName, "not true");
-    _assertNullDartObject(
-        typeProvider, variables.getBool(typeProvider, variableName));
-  }
-
-  void test_getBool_true() {
-    TestTypeProvider typeProvider = new TestTypeProvider();
-    String variableName = "var";
-    DeclaredVariables variables = new DeclaredVariables();
-    variables.define(variableName, "true");
-    DartObject object = variables.getBool(typeProvider, variableName);
-    expect(object, isNotNull);
-    expect(object.toBoolValue(), true);
-  }
-
-  void test_getBool_undefined() {
-    TestTypeProvider typeProvider = new TestTypeProvider();
-    String variableName = "var";
-    DeclaredVariables variables = new DeclaredVariables();
-    _assertUnknownDartObject(
-        typeProvider.boolType, variables.getBool(typeProvider, variableName));
-  }
-
-  void test_getInt_invalid() {
-    TestTypeProvider typeProvider = new TestTypeProvider();
-    String variableName = "var";
-    DeclaredVariables variables = new DeclaredVariables();
-    variables.define(variableName, "four score and seven years");
-    _assertNullDartObject(
-        typeProvider, variables.getInt(typeProvider, variableName));
-  }
-
-  void test_getInt_undefined() {
-    TestTypeProvider typeProvider = new TestTypeProvider();
-    String variableName = "var";
-    DeclaredVariables variables = new DeclaredVariables();
-    _assertUnknownDartObject(
-        typeProvider.intType, variables.getInt(typeProvider, variableName));
-  }
-
-  void test_getInt_valid() {
-    TestTypeProvider typeProvider = new TestTypeProvider();
-    String variableName = "var";
-    DeclaredVariables variables = new DeclaredVariables();
-    variables.define(variableName, "23");
-    DartObject object = variables.getInt(typeProvider, variableName);
-    expect(object, isNotNull);
-    expect(object.toIntValue(), 23);
-  }
-
-  void test_getString_defined() {
-    TestTypeProvider typeProvider = new TestTypeProvider();
-    String variableName = "var";
-    String value = "value";
-    DeclaredVariables variables = new DeclaredVariables();
-    variables.define(variableName, value);
-    DartObject object = variables.getString(typeProvider, variableName);
-    expect(object, isNotNull);
-    expect(object.toStringValue(), value);
-  }
-
-  void test_getString_undefined() {
-    TestTypeProvider typeProvider = new TestTypeProvider();
-    String variableName = "var";
-    DeclaredVariables variables = new DeclaredVariables();
-    _assertUnknownDartObject(typeProvider.stringType,
-        variables.getString(typeProvider, variableName));
-  }
-
-  void _assertNullDartObject(TestTypeProvider typeProvider, DartObject result) {
-    expect(result.type, typeProvider.nullType);
-  }
-
-  void _assertUnknownDartObject(
-      ParameterizedType expectedType, DartObject result) {
-    expect((result as DartObjectImpl).isUnknown, isTrue);
-    expect(result.type, expectedType);
-  }
-}
-
-@reflectiveTest
-class ReferenceFinderTest {
-  DirectedGraph<ConstantEvaluationTarget> _referenceGraph;
-  VariableElement _head;
-  Element _tail;
-
-  void setUp() {
-    _referenceGraph = new DirectedGraph<ConstantEvaluationTarget>();
-    _head = ElementFactory.topLevelVariableElement2("v1");
-  }
-
-  void test_visitSimpleIdentifier_const() {
-    _visitNode(_makeTailVariable("v2", true));
-    _assertOneArc(_tail);
-  }
-
-  void test_visitSuperConstructorInvocation_const() {
-    _visitNode(_makeTailSuperConstructorInvocation("A", true));
-    _assertOneArc(_tail);
-  }
-
-  void test_visitSuperConstructorInvocation_nonConst() {
-    _visitNode(_makeTailSuperConstructorInvocation("A", false));
-    _assertOneArc(_tail);
-  }
-
-  void test_visitSuperConstructorInvocation_unresolved() {
-    SuperConstructorInvocation superConstructorInvocation =
-        AstFactory.superConstructorInvocation();
-    _visitNode(superConstructorInvocation);
-    _assertNoArcs();
-  }
-
-  void _assertNoArcs() {
-    Set<ConstantEvaluationTarget> tails = _referenceGraph.getTails(_head);
-    expect(tails, hasLength(0));
-  }
-
-  void _assertOneArc(Element tail) {
-    Set<ConstantEvaluationTarget> tails = _referenceGraph.getTails(_head);
-    expect(tails, hasLength(1));
-    expect(tails.first, same(tail));
-  }
-
-  ReferenceFinder _createReferenceFinder(ConstantEvaluationTarget source) =>
-      new ReferenceFinder((ConstantEvaluationTarget dependency) {
-        _referenceGraph.addEdge(source, dependency);
-      });
-  SuperConstructorInvocation _makeTailSuperConstructorInvocation(
-      String name, bool isConst) {
-    List<ConstructorInitializer> initializers =
-        new List<ConstructorInitializer>();
-    ConstructorDeclaration constructorDeclaration =
-        AstFactory.constructorDeclaration(AstFactory.identifier3(name), null,
-            AstFactory.formalParameterList(), initializers);
-    if (isConst) {
-      constructorDeclaration.constKeyword = new KeywordToken(Keyword.CONST, 0);
-    }
-    ClassElementImpl classElement = ElementFactory.classElement2(name);
-    SuperConstructorInvocation superConstructorInvocation =
-        AstFactory.superConstructorInvocation();
-    ConstructorElementImpl constructorElement =
-        ElementFactory.constructorElement(classElement, name, isConst);
-    _tail = constructorElement;
-    superConstructorInvocation.staticElement = constructorElement;
-    return superConstructorInvocation;
-  }
-
-  SimpleIdentifier _makeTailVariable(String name, bool isConst) {
-    VariableDeclaration variableDeclaration =
-        AstFactory.variableDeclaration(name);
-    ConstLocalVariableElementImpl variableElement =
-        ElementFactory.constLocalVariableElement(name);
-    _tail = variableElement;
-    variableElement.const3 = isConst;
-    AstFactory.variableDeclarationList2(
-        isConst ? Keyword.CONST : Keyword.VAR, [variableDeclaration]);
-    SimpleIdentifier identifier = AstFactory.identifier3(name);
-    identifier.staticElement = variableElement;
-    return identifier;
-  }
-
-  void _visitNode(AstNode node) {
-    node.accept(_createReferenceFinder(_head));
-  }
-}
-
-class _TestAnalysisContext extends TestAnalysisContext {
-  @override
-  InternalAnalysisContext getContextFor(Source source) => this;
-}
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 ac762c4b..02993c5 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -1917,6 +1917,26 @@
         [StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE]);
   }
 
+  void test_forIn_object() {
+    assertNoErrorsInCode(
+        '''
+f() {
+  Object o; // Could be [].
+  for (var i in o) {}
+}
+''');
+  }
+
+  void test_forIn_dynamic() {
+    assertNoErrorsInCode(
+        '''
+f() {
+  dynamic d; // Could be [].
+  for (var i in d) {}
+}
+''');
+  }
+
   void test_forIn_declaredVariableWrongType() {
     assertErrorsInCode(
         '''
diff --git a/pkg/analyzer/test/source/error_processor_test.dart b/pkg/analyzer/test/source/error_processor_test.dart
index 864bbf8..d7aaeee 100644
--- a/pkg/analyzer/test/source/error_processor_test.dart
+++ b/pkg/analyzer/test/source/error_processor_test.dart
@@ -39,6 +39,11 @@
     ['x']
   ]);
 
+  AnalysisError non_bool_operand = new AnalysisError(
+      new TestSource(), 0, 1, StaticTypeWarningCode.NON_BOOL_OPERAND, [
+    ['x']
+  ]);
+
   oneTimeSetup();
 
   setUp(() {
@@ -66,7 +71,15 @@
 analyzer:
   strong-mode: true
 ''');
-      expect(getProcessor(invalid_assignment).severity, ErrorSeverity.ERROR);
+      expect(getProcessor(non_bool_operand).severity, ErrorSeverity.ERROR);
+    });
+
+    test('does not upgrade other warnings to errors in strong mode', () {
+      configureOptions('''
+analyzer:
+  strong-mode: true
+''');
+      expect(getProcessor(unused_local_variable), isNull);
     });
   });
 
diff --git a/pkg/analyzer/test/src/context/cache_test.dart b/pkg/analyzer/test/src/context/cache_test.dart
index 37bd49c..3c44f09 100644
--- a/pkg/analyzer/test/src/context/cache_test.dart
+++ b/pkg/analyzer/test/src/context/cache_test.dart
@@ -1127,7 +1127,7 @@
 
   @override
   DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
-      ResultDescriptor descriptor) {
+      ResultDescriptor descriptor, Object value) {
     if (descriptor == keepDescriptor) {
       return DeltaResult.KEEP_CONTINUE;
     }
diff --git a/pkg/analyzer/test/src/context/mock_sdk.dart b/pkg/analyzer/test/src/context/mock_sdk.dart
index 715ad1c..8103e12 100644
--- a/pkg/analyzer/test/src/context/mock_sdk.dart
+++ b/pkg/analyzer/test/src/context/mock_sdk.dart
@@ -158,6 +158,15 @@
   void operator []=(int index, E value) {}
   Iterator<E> get iterator => null;
   void clear() {}
+
+  bool get isEmpty => false;
+  E get first => null;
+
+  Iterable/*<R>*/ map/*<R>*/(/*=R*/ f(E e)) => null;
+
+  /*=R*/ fold/*<R>*/(/*=R*/ initialValue,
+      /*=R*/ combine(/*=R*/ previousValue, E element)) => null;
+
 }
 
 class Map<K, V> extends Object {
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
new file mode 100644
index 0000000..960726e
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -0,0 +1,1603 @@
+// 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 analyzer.test.constant_test;
+
+import 'package:analyzer/context/declared_variables.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/generated/constant.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/generated/testing/ast_factory.dart';
+import 'package:analyzer/src/generated/testing/test_type_provider.dart';
+import 'package:analyzer/src/task/dart.dart';
+import 'package:path/path.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../../generated/resolver_test_case.dart';
+import '../../../generated/test_support.dart';
+import '../../../reflective_tests.dart';
+import '../../../utils.dart';
+
+main() {
+  initializeTestEnvironment();
+  runReflectiveTests(ConstantValueComputerTest);
+  runReflectiveTests(ConstantVisitorTest);
+}
+
+/**
+ * Implementation of [ConstantEvaluationValidator] used during unit tests;
+ * verifies that any nodes referenced during constant evaluation are present in
+ * the dependency graph.
+ */
+class ConstantEvaluationValidator_ForTest
+    implements ConstantEvaluationValidator {
+  final InternalAnalysisContext context;
+  ConstantValueComputer computer;
+  ConstantEvaluationTarget _nodeBeingEvaluated;
+
+  ConstantEvaluationValidator_ForTest(this.context);
+
+  @override
+  void beforeComputeValue(ConstantEvaluationTarget constant) {
+    _nodeBeingEvaluated = constant;
+  }
+
+  @override
+  void beforeGetConstantInitializers(ConstructorElement constructor) =>
+      _checkPathTo(constructor);
+
+  @override
+  void beforeGetEvaluationResult(ConstantEvaluationTarget constant) =>
+      _checkPathTo(constant);
+
+  @override
+  void beforeGetFieldEvaluationResult(FieldElementImpl field) =>
+      _checkPathTo(field);
+
+  @override
+  void beforeGetParameterDefault(ParameterElement parameter) =>
+      _checkPathTo(parameter);
+
+  void _checkPathTo(ConstantEvaluationTarget target) {
+    if (computer.referenceGraph.containsPath(_nodeBeingEvaluated, target)) {
+      return; // pass
+    }
+    // print a nice error message on failure
+    StringBuffer out = new StringBuffer();
+    out.writeln("missing path in constant dependency graph");
+    out.writeln("from $_nodeBeingEvaluated to $target");
+    for (var s in context.analysisCache.sources) {
+      String text = context.getContents(s).data;
+      if (text != "") {
+        out.writeln('''
+=== ${s.shortName}
+$text''');
+      }
+    }
+    fail(out.toString());
+  }
+}
+
+@reflectiveTest
+class ConstantValueComputerTest extends ResolverTestCase {
+  void test_annotation_constConstructor() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+  final int i;
+  const A(this.i);
+}
+
+class C {
+  @A(5)
+  f() {}
+}
+''');
+    EvaluationResultImpl result =
+        _evaluateAnnotation(compilationUnit, "C", "f");
+    Map<String, DartObjectImpl> annotationFields = _assertType(result, 'A');
+    _assertIntField(annotationFields, 'i', 5);
+  }
+
+  void test_annotation_constConstructor_named() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+  final int i;
+  const A.named(this.i);
+}
+
+class C {
+  @A.named(5)
+  f() {}
+}
+''');
+    EvaluationResultImpl result =
+        _evaluateAnnotation(compilationUnit, "C", "f");
+    Map<String, DartObjectImpl> annotationFields = _assertType(result, 'A');
+    _assertIntField(annotationFields, 'i', 5);
+  }
+
+  void test_annotation_constConstructor_noArgs() {
+    // Failing to pass arguments to an annotation which is a constant
+    // constructor is illegal, but shouldn't crash analysis.
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+  final int i;
+  const A(this.i);
+}
+
+class C {
+  @A
+  f() {}
+}
+''');
+    _evaluateAnnotation(compilationUnit, "C", "f");
+  }
+
+  void test_annotation_constConstructor_noArgs_named() {
+    // Failing to pass arguments to an annotation which is a constant
+    // constructor is illegal, but shouldn't crash analysis.
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+  final int i;
+  const A.named(this.i);
+}
+
+class C {
+  @A.named
+  f() {}
+}
+''');
+    _evaluateAnnotation(compilationUnit, "C", "f");
+  }
+
+  void test_annotation_nonConstConstructor() {
+    // Calling a non-const constructor from an annotation that is illegal, but
+    // shouldn't crash analysis.
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+  final int i;
+  A(this.i);
+}
+
+class C {
+  @A(5)
+  f() {}
+}
+''');
+    _evaluateAnnotation(compilationUnit, "C", "f");
+  }
+
+  void test_annotation_staticConst() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+class C {
+  static const int i = 5;
+
+  @i
+  f() {}
+}
+''');
+    EvaluationResultImpl result =
+        _evaluateAnnotation(compilationUnit, "C", "f");
+    expect(_assertValidInt(result), 5);
+  }
+
+  void test_annotation_staticConst_args() {
+    // Applying arguments to an annotation that is a static const is
+    // illegal, but shouldn't crash analysis.
+    CompilationUnit compilationUnit = resolveSource(r'''
+class C {
+  static const int i = 5;
+
+  @i(1)
+  f() {}
+}
+''');
+    _evaluateAnnotation(compilationUnit, "C", "f");
+  }
+
+  void test_annotation_staticConst_otherClass() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+  static const int i = 5;
+}
+
+class C {
+  @A.i
+  f() {}
+}
+''');
+    EvaluationResultImpl result =
+        _evaluateAnnotation(compilationUnit, "C", "f");
+    expect(_assertValidInt(result), 5);
+  }
+
+  void test_annotation_staticConst_otherClass_args() {
+    // Applying arguments to an annotation that is a static const is
+    // illegal, but shouldn't crash analysis.
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+  static const int i = 5;
+}
+
+class C {
+  @A.i(1)
+  f() {}
+}
+''');
+    _evaluateAnnotation(compilationUnit, "C", "f");
+  }
+
+  void test_annotation_topLevelVariable() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const int i = 5;
+class C {
+  @i
+  f() {}
+}
+''');
+    EvaluationResultImpl result =
+        _evaluateAnnotation(compilationUnit, "C", "f");
+    expect(_assertValidInt(result), 5);
+  }
+
+  void test_annotation_topLevelVariable_args() {
+    // Applying arguments to an annotation that is a top-level variable is
+    // illegal, but shouldn't crash analysis.
+    CompilationUnit compilationUnit = resolveSource(r'''
+const int i = 5;
+class C {
+  @i(1)
+  f() {}
+}
+''');
+    _evaluateAnnotation(compilationUnit, "C", "f");
+  }
+
+  void test_computeValues_cycle() {
+    TestLogger logger = new TestLogger();
+    AnalysisEngine.instance.logger = logger;
+    try {
+      Source source = addSource(r'''
+  const int a = c;
+  const int b = a;
+  const int c = b;''');
+      LibraryElement libraryElement = resolve2(source);
+      CompilationUnit unit =
+          analysisContext.resolveCompilationUnit(source, libraryElement);
+      analysisContext.computeErrors(source);
+      expect(unit, isNotNull);
+      ConstantValueComputer computer = _makeConstantValueComputer();
+      computer.add(unit, source, source);
+      computer.computeValues();
+      NodeList<CompilationUnitMember> members = unit.declarations;
+      expect(members, hasLength(3));
+      _validate(false, (members[0] as TopLevelVariableDeclaration).variables);
+      _validate(false, (members[1] as TopLevelVariableDeclaration).variables);
+      _validate(false, (members[2] as TopLevelVariableDeclaration).variables);
+    } finally {
+      AnalysisEngine.instance.logger = Logger.NULL;
+    }
+  }
+
+  void test_computeValues_dependentVariables() {
+    Source source = addSource(r'''
+const int b = a;
+const int a = 0;''');
+    LibraryElement libraryElement = resolve2(source);
+    CompilationUnit unit =
+        analysisContext.resolveCompilationUnit(source, libraryElement);
+    expect(unit, isNotNull);
+    ConstantValueComputer computer = _makeConstantValueComputer();
+    computer.add(unit, source, source);
+    computer.computeValues();
+    NodeList<CompilationUnitMember> members = unit.declarations;
+    expect(members, hasLength(2));
+    _validate(true, (members[0] as TopLevelVariableDeclaration).variables);
+    _validate(true, (members[1] as TopLevelVariableDeclaration).variables);
+  }
+
+  void test_computeValues_empty() {
+    ConstantValueComputer computer = _makeConstantValueComputer();
+    computer.computeValues();
+  }
+
+  void test_computeValues_multipleSources() {
+    Source librarySource = addNamedSource(
+        "/lib.dart",
+        r'''
+library lib;
+part 'part.dart';
+const int c = b;
+const int a = 0;''');
+    Source partSource = addNamedSource(
+        "/part.dart",
+        r'''
+part of lib;
+const int b = a;
+const int d = c;''');
+    LibraryElement libraryElement = resolve2(librarySource);
+    CompilationUnit libraryUnit =
+        analysisContext.resolveCompilationUnit(librarySource, libraryElement);
+    expect(libraryUnit, isNotNull);
+    CompilationUnit partUnit =
+        analysisContext.resolveCompilationUnit(partSource, libraryElement);
+    expect(partUnit, isNotNull);
+    ConstantValueComputer computer = _makeConstantValueComputer();
+    computer.add(libraryUnit, librarySource, librarySource);
+    computer.add(partUnit, partSource, librarySource);
+    computer.computeValues();
+    NodeList<CompilationUnitMember> libraryMembers = libraryUnit.declarations;
+    expect(libraryMembers, hasLength(2));
+    _validate(
+        true, (libraryMembers[0] as TopLevelVariableDeclaration).variables);
+    _validate(
+        true, (libraryMembers[1] as TopLevelVariableDeclaration).variables);
+    NodeList<CompilationUnitMember> partMembers = libraryUnit.declarations;
+    expect(partMembers, hasLength(2));
+    _validate(true, (partMembers[0] as TopLevelVariableDeclaration).variables);
+    _validate(true, (partMembers[1] as TopLevelVariableDeclaration).variables);
+  }
+
+  void test_computeValues_singleVariable() {
+    Source source = addSource("const int a = 0;");
+    LibraryElement libraryElement = resolve2(source);
+    CompilationUnit unit =
+        analysisContext.resolveCompilationUnit(source, libraryElement);
+    expect(unit, isNotNull);
+    ConstantValueComputer computer = _makeConstantValueComputer();
+    computer.add(unit, source, source);
+    computer.computeValues();
+    NodeList<CompilationUnitMember> members = unit.declarations;
+    expect(members, hasLength(1));
+    _validate(true, (members[0] as TopLevelVariableDeclaration).variables);
+  }
+
+  void test_computeValues_value_depends_on_enum() {
+    Source source = addSource('''
+enum E { id0, id1 }
+const E e = E.id0;
+''');
+    LibraryElement libraryElement = resolve2(source);
+    CompilationUnit unit =
+        analysisContext.resolveCompilationUnit(source, libraryElement);
+    expect(unit, isNotNull);
+    ConstantValueComputer computer = _makeConstantValueComputer();
+    computer.add(unit, source, source);
+    computer.computeValues();
+    TopLevelVariableDeclaration declaration = unit.declarations
+        .firstWhere((member) => member is TopLevelVariableDeclaration);
+    _validate(true, declaration.variables);
+  }
+
+  void test_dependencyOnConstructor() {
+    // x depends on "const A()"
+    _assertProperDependencies(r'''
+class A {
+  const A();
+}
+const x = const A();''');
+  }
+
+  void test_dependencyOnConstructorArgument() {
+    // "const A(x)" depends on x
+    _assertProperDependencies(r'''
+class A {
+  const A(this.next);
+  final A next;
+}
+const A x = const A(null);
+const A y = const A(x);''');
+  }
+
+  void test_dependencyOnConstructorArgument_unresolvedConstructor() {
+    // "const A.a(x)" depends on x even if the constructor A.a can't be found.
+    _assertProperDependencies(
+        r'''
+class A {
+}
+const int x = 1;
+const A y = const A.a(x);''',
+        [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR]);
+  }
+
+  void test_dependencyOnConstructorInitializer() {
+    // "const A()" depends on x
+    _assertProperDependencies(r'''
+const int x = 1;
+class A {
+  const A() : v = x;
+  final int v;
+}''');
+  }
+
+  void test_dependencyOnExplicitSuperConstructor() {
+    // b depends on B() depends on A()
+    _assertProperDependencies(r'''
+class A {
+  const A(this.x);
+  final int x;
+}
+class B extends A {
+  const B() : super(5);
+}
+const B b = const B();''');
+  }
+
+  void test_dependencyOnExplicitSuperConstructorParameters() {
+    // b depends on B() depends on i
+    _assertProperDependencies(r'''
+class A {
+  const A(this.x);
+  final int x;
+}
+class B extends A {
+  const B() : super(i);
+}
+const B b = const B();
+const int i = 5;''');
+  }
+
+  void test_dependencyOnFactoryRedirect() {
+    // a depends on A.foo() depends on A.bar()
+    _assertProperDependencies(r'''
+const A a = const A.foo();
+class A {
+  factory const A.foo() = A.bar;
+  const A.bar();
+}''');
+  }
+
+  void test_dependencyOnFactoryRedirectWithTypeParams() {
+    _assertProperDependencies(r'''
+class A {
+  const factory A(var a) = B<int>;
+}
+
+class B<T> implements A {
+  final T x;
+  const B(this.x);
+}
+
+const A a = const A(10);''');
+  }
+
+  void test_dependencyOnImplicitSuperConstructor() {
+    // b depends on B() depends on A()
+    _assertProperDependencies(r'''
+class A {
+  const A() : x = 5;
+  final int x;
+}
+class B extends A {
+  const B();
+}
+const B b = const B();''');
+  }
+
+  void test_dependencyOnInitializedFinal() {
+    // a depends on A() depends on A.x
+    _assertProperDependencies('''
+class A {
+  const A();
+  final int x = 1;
+}
+const A a = const A();
+''');
+  }
+
+  void test_dependencyOnInitializedNonStaticConst() {
+    // Even though non-static consts are not allowed by the language, we need
+    // to handle them for error recovery purposes.
+    // a depends on A() depends on A.x
+    _assertProperDependencies(
+        '''
+class A {
+  const A();
+  const int x = 1;
+}
+const A a = const A();
+''',
+        [CompileTimeErrorCode.CONST_INSTANCE_FIELD]);
+  }
+
+  void test_dependencyOnNonFactoryRedirect() {
+    // a depends on A.foo() depends on A.bar()
+    _assertProperDependencies(r'''
+const A a = const A.foo();
+class A {
+  const A.foo() : this.bar();
+  const A.bar();
+}''');
+  }
+
+  void test_dependencyOnNonFactoryRedirect_arg() {
+    // a depends on A.foo() depends on b
+    _assertProperDependencies(r'''
+const A a = const A.foo();
+const int b = 1;
+class A {
+  const A.foo() : this.bar(b);
+  const A.bar(x) : y = x;
+  final int y;
+}''');
+  }
+
+  void test_dependencyOnNonFactoryRedirect_defaultValue() {
+    // a depends on A.foo() depends on A.bar() depends on b
+    _assertProperDependencies(r'''
+const A a = const A.foo();
+const int b = 1;
+class A {
+  const A.foo() : this.bar();
+  const A.bar([x = b]) : y = x;
+  final int y;
+}''');
+  }
+
+  void test_dependencyOnNonFactoryRedirect_toMissing() {
+    // a depends on A.foo() which depends on nothing, since A.bar() is
+    // missing.
+    _assertProperDependencies(
+        r'''
+const A a = const A.foo();
+class A {
+  const A.foo() : this.bar();
+}''',
+        [CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR]);
+  }
+
+  void test_dependencyOnNonFactoryRedirect_toNonConst() {
+    // a depends on A.foo() which depends on nothing, since A.bar() is
+    // non-const.
+    _assertProperDependencies(r'''
+const A a = const A.foo();
+class A {
+  const A.foo() : this.bar();
+  A.bar();
+}''');
+  }
+
+  void test_dependencyOnNonFactoryRedirect_unnamed() {
+    // a depends on A.foo() depends on A()
+    _assertProperDependencies(r'''
+const A a = const A.foo();
+class A {
+  const A.foo() : this();
+  const A();
+}''');
+  }
+
+  void test_dependencyOnOptionalParameterDefault() {
+    // a depends on A() depends on B()
+    _assertProperDependencies(r'''
+class A {
+  const A([x = const B()]) : b = x;
+  final B b;
+}
+class B {
+  const B();
+}
+const A a = const A();''');
+  }
+
+  void test_dependencyOnVariable() {
+    // x depends on y
+    _assertProperDependencies(r'''
+const x = y + 1;
+const y = 2;''');
+  }
+
+  void test_final_initialized_at_declaration() {
+    CompilationUnit compilationUnit = resolveSource('''
+class A {
+  final int i = 123;
+  const A();
+}
+
+const A a = const A();
+''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, 'a');
+    Map<String, DartObjectImpl> fields = _assertType(result, "A");
+    expect(fields, hasLength(1));
+    _assertIntField(fields, "i", 123);
+  }
+
+  void test_fromEnvironment_bool_default_false() {
+    expect(_assertValidBool(_check_fromEnvironment_bool(null, "false")), false);
+  }
+
+  void test_fromEnvironment_bool_default_overridden() {
+    expect(
+        _assertValidBool(_check_fromEnvironment_bool("false", "true")), false);
+  }
+
+  void test_fromEnvironment_bool_default_parseError() {
+    expect(_assertValidBool(_check_fromEnvironment_bool("parseError", "true")),
+        true);
+  }
+
+  void test_fromEnvironment_bool_default_true() {
+    expect(_assertValidBool(_check_fromEnvironment_bool(null, "true")), true);
+  }
+
+  void test_fromEnvironment_bool_false() {
+    expect(_assertValidBool(_check_fromEnvironment_bool("false", null)), false);
+  }
+
+  void test_fromEnvironment_bool_parseError() {
+    expect(_assertValidBool(_check_fromEnvironment_bool("parseError", null)),
+        false);
+  }
+
+  void test_fromEnvironment_bool_true() {
+    expect(_assertValidBool(_check_fromEnvironment_bool("true", null)), true);
+  }
+
+  void test_fromEnvironment_bool_undeclared() {
+    _assertValidUnknown(_check_fromEnvironment_bool(null, null));
+  }
+
+  void test_fromEnvironment_int_default_overridden() {
+    expect(_assertValidInt(_check_fromEnvironment_int("234", "123")), 234);
+  }
+
+  void test_fromEnvironment_int_default_parseError() {
+    expect(
+        _assertValidInt(_check_fromEnvironment_int("parseError", "123")), 123);
+  }
+
+  void test_fromEnvironment_int_default_undeclared() {
+    expect(_assertValidInt(_check_fromEnvironment_int(null, "123")), 123);
+  }
+
+  void test_fromEnvironment_int_ok() {
+    expect(_assertValidInt(_check_fromEnvironment_int("234", null)), 234);
+  }
+
+  void test_fromEnvironment_int_parseError() {
+    _assertValidNull(_check_fromEnvironment_int("parseError", null));
+  }
+
+  void test_fromEnvironment_int_parseError_nullDefault() {
+    _assertValidNull(_check_fromEnvironment_int("parseError", "null"));
+  }
+
+  void test_fromEnvironment_int_undeclared() {
+    _assertValidUnknown(_check_fromEnvironment_int(null, null));
+  }
+
+  void test_fromEnvironment_int_undeclared_nullDefault() {
+    _assertValidNull(_check_fromEnvironment_int(null, "null"));
+  }
+
+  void test_fromEnvironment_string_default_overridden() {
+    expect(_assertValidString(_check_fromEnvironment_string("abc", "'def'")),
+        "abc");
+  }
+
+  void test_fromEnvironment_string_default_undeclared() {
+    expect(_assertValidString(_check_fromEnvironment_string(null, "'def'")),
+        "def");
+  }
+
+  void test_fromEnvironment_string_empty() {
+    expect(_assertValidString(_check_fromEnvironment_string("", null)), "");
+  }
+
+  void test_fromEnvironment_string_ok() {
+    expect(
+        _assertValidString(_check_fromEnvironment_string("abc", null)), "abc");
+  }
+
+  void test_fromEnvironment_string_undeclared() {
+    _assertValidUnknown(_check_fromEnvironment_string(null, null));
+  }
+
+  void test_fromEnvironment_string_undeclared_nullDefault() {
+    _assertValidNull(_check_fromEnvironment_string(null, "null"));
+  }
+
+  void test_instanceCreationExpression_computedField() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A(4, 5);
+class A {
+  const A(int i, int j) : k = 2 * i + j;
+  final int k;
+}''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "foo");
+    Map<String, DartObjectImpl> fields = _assertType(result, "A");
+    expect(fields, hasLength(1));
+    _assertIntField(fields, "k", 13);
+  }
+
+  void
+      test_instanceCreationExpression_computedField_namedOptionalWithDefault() {
+    _checkInstanceCreationOptionalParams(false, true, true);
+  }
+
+  void
+      test_instanceCreationExpression_computedField_namedOptionalWithoutDefault() {
+    _checkInstanceCreationOptionalParams(false, true, false);
+  }
+
+  void
+      test_instanceCreationExpression_computedField_unnamedOptionalWithDefault() {
+    _checkInstanceCreationOptionalParams(false, false, true);
+  }
+
+  void
+      test_instanceCreationExpression_computedField_unnamedOptionalWithoutDefault() {
+    _checkInstanceCreationOptionalParams(false, false, false);
+  }
+
+  void test_instanceCreationExpression_computedField_usesConstConstructor() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A(3);
+class A {
+  const A(int i) : b = const B(4);
+  final int b;
+}
+class B {
+  const B(this.k);
+  final int k;
+}''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "foo");
+    Map<String, DartObjectImpl> fieldsOfA = _assertType(result, "A");
+    expect(fieldsOfA, hasLength(1));
+    Map<String, DartObjectImpl> fieldsOfB =
+        _assertFieldType(fieldsOfA, "b", "B");
+    expect(fieldsOfB, hasLength(1));
+    _assertIntField(fieldsOfB, "k", 4);
+  }
+
+  void test_instanceCreationExpression_computedField_usesStaticConst() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A(3);
+class A {
+  const A(int i) : k = i + B.bar;
+  final int k;
+}
+class B {
+  static const bar = 4;
+}''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "foo");
+    Map<String, DartObjectImpl> fields = _assertType(result, "A");
+    expect(fields, hasLength(1));
+    _assertIntField(fields, "k", 7);
+  }
+
+  void test_instanceCreationExpression_computedField_usesTopLevelConst() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A(3);
+const bar = 4;
+class A {
+  const A(int i) : k = i + bar;
+  final int k;
+}''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "foo");
+    Map<String, DartObjectImpl> fields = _assertType(result, "A");
+    expect(fields, hasLength(1));
+    _assertIntField(fields, "k", 7);
+  }
+
+  void test_instanceCreationExpression_explicitSuper() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const B(4, 5);
+class A {
+  const A(this.x);
+  final int x;
+}
+class B extends A {
+  const B(int x, this.y) : super(x * 2);
+  final int y;
+}''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "foo");
+    Map<String, DartObjectImpl> fields = _assertType(result, "B");
+    expect(fields, hasLength(2));
+    _assertIntField(fields, "y", 5);
+    Map<String, DartObjectImpl> superclassFields =
+        _assertFieldType(fields, GenericState.SUPERCLASS_FIELD, "A");
+    expect(superclassFields, hasLength(1));
+    _assertIntField(superclassFields, "x", 8);
+  }
+
+  void test_instanceCreationExpression_fieldFormalParameter() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A(42);
+class A {
+  int x;
+  const A(this.x)
+}''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "foo");
+    Map<String, DartObjectImpl> fields = _assertType(result, "A");
+    expect(fields, hasLength(1));
+    _assertIntField(fields, "x", 42);
+  }
+
+  void
+      test_instanceCreationExpression_fieldFormalParameter_namedOptionalWithDefault() {
+    _checkInstanceCreationOptionalParams(true, true, true);
+  }
+
+  void
+      test_instanceCreationExpression_fieldFormalParameter_namedOptionalWithoutDefault() {
+    _checkInstanceCreationOptionalParams(true, true, false);
+  }
+
+  void
+      test_instanceCreationExpression_fieldFormalParameter_unnamedOptionalWithDefault() {
+    _checkInstanceCreationOptionalParams(true, false, true);
+  }
+
+  void
+      test_instanceCreationExpression_fieldFormalParameter_unnamedOptionalWithoutDefault() {
+    _checkInstanceCreationOptionalParams(true, false, false);
+  }
+
+  void test_instanceCreationExpression_implicitSuper() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const B(4);
+class A {
+  const A() : x = 3;
+  final int x;
+}
+class B extends A {
+  const B(this.y);
+  final int y;
+}''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "foo");
+    Map<String, DartObjectImpl> fields = _assertType(result, "B");
+    expect(fields, hasLength(2));
+    _assertIntField(fields, "y", 4);
+    Map<String, DartObjectImpl> superclassFields =
+        _assertFieldType(fields, GenericState.SUPERCLASS_FIELD, "A");
+    expect(superclassFields, hasLength(1));
+    _assertIntField(superclassFields, "x", 3);
+  }
+
+  void test_instanceCreationExpression_nonFactoryRedirect() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1();
+class A {
+  const A.a1() : this.a2();
+  const A.a2() : x = 5;
+  final int x;
+}''');
+    Map<String, DartObjectImpl> aFields =
+        _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+    _assertIntField(aFields, 'x', 5);
+  }
+
+  void test_instanceCreationExpression_nonFactoryRedirect_arg() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1(1);
+class A {
+  const A.a1(x) : this.a2(x + 100);
+  const A.a2(x) : y = x + 10;
+  final int y;
+}''');
+    Map<String, DartObjectImpl> aFields =
+        _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+    _assertIntField(aFields, 'y', 111);
+  }
+
+  void test_instanceCreationExpression_nonFactoryRedirect_cycle() {
+    // It is an error to have a cycle in non-factory redirects; however, we
+    // need to make sure that even if the error occurs, attempting to evaluate
+    // the constant will terminate.
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A();
+class A {
+  const A() : this.b();
+  const A.b() : this();
+}''');
+    _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
+  }
+
+  void test_instanceCreationExpression_nonFactoryRedirect_defaultArg() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1();
+class A {
+  const A.a1() : this.a2();
+  const A.a2([x = 100]) : y = x + 10;
+  final int y;
+}''');
+    Map<String, DartObjectImpl> aFields =
+        _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+    _assertIntField(aFields, 'y', 110);
+  }
+
+  void test_instanceCreationExpression_nonFactoryRedirect_toMissing() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1();
+class A {
+  const A.a1() : this.a2();
+}''');
+    // We don't care what value foo evaluates to (since there is a compile
+    // error), but we shouldn't crash, and we should figure
+    // out that it evaluates to an instance of class A.
+    _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+  }
+
+  void test_instanceCreationExpression_nonFactoryRedirect_toNonConst() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1();
+class A {
+  const A.a1() : this.a2();
+  A.a2();
+}''');
+    // We don't care what value foo evaluates to (since there is a compile
+    // error), but we shouldn't crash, and we should figure
+    // out that it evaluates to an instance of class A.
+    _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+  }
+
+  void test_instanceCreationExpression_nonFactoryRedirect_unnamed() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1();
+class A {
+  const A.a1() : this();
+  const A() : x = 5;
+  final int x;
+}''');
+    Map<String, DartObjectImpl> aFields =
+        _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+    _assertIntField(aFields, 'x', 5);
+  }
+
+  void test_instanceCreationExpression_redirect() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A();
+class A {
+  const factory A() = B;
+}
+class B implements A {
+  const B();
+}''');
+    _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "B");
+  }
+
+  void test_instanceCreationExpression_redirect_cycle() {
+    // It is an error to have a cycle in factory redirects; however, we need
+    // to make sure that even if the error occurs, attempting to evaluate the
+    // constant will terminate.
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A();
+class A {
+  const factory A() = A.b;
+  const factory A.b() = A;
+}''');
+    _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
+  }
+
+  void test_instanceCreationExpression_redirect_external() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A();
+class A {
+  external const factory A();
+}''');
+    _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
+  }
+
+  void test_instanceCreationExpression_redirect_nonConst() {
+    // It is an error for a const factory constructor redirect to a non-const
+    // constructor; however, we need to make sure that even if the error
+    // attempting to evaluate the constant won't cause a crash.
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A();
+class A {
+  const factory A() = A.b;
+  A.b();
+}''');
+    _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
+  }
+
+  void test_instanceCreationExpression_redirectWithTypeParams() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+  const factory A(var a) = B<int>;
+}
+
+class B<T> implements A {
+  final T x;
+  const B(this.x);
+}
+
+const A a = const A(10);''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "a");
+    Map<String, DartObjectImpl> fields = _assertType(result, "B<int>");
+    expect(fields, hasLength(1));
+    _assertIntField(fields, "x", 10);
+  }
+
+  void test_instanceCreationExpression_redirectWithTypeSubstitution() {
+    // To evaluate the redirection of A<int>,
+    // A's template argument (T=int) must be substituted
+    // into B's template argument (B<U> where U=T) to get B<int>.
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A<T> {
+  const factory A(var a) = B<T>;
+}
+
+class B<U> implements A {
+  final U x;
+  const B(this.x);
+}
+
+const A<int> a = const A<int>(10);''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "a");
+    Map<String, DartObjectImpl> fields = _assertType(result, "B<int>");
+    expect(fields, hasLength(1));
+    _assertIntField(fields, "x", 10);
+  }
+
+  void test_instanceCreationExpression_symbol() {
+    CompilationUnit compilationUnit =
+        resolveSource("const foo = const Symbol('a');");
+    EvaluationResultImpl evaluationResult =
+        _evaluateTopLevelVariable(compilationUnit, "foo");
+    expect(evaluationResult.value, isNotNull);
+    DartObjectImpl value = evaluationResult.value;
+    expect(value.type, typeProvider.symbolType);
+    expect(value.toSymbolValue(), "a");
+  }
+
+  void test_instanceCreationExpression_withSupertypeParams_explicit() {
+    _checkInstanceCreation_withSupertypeParams(true);
+  }
+
+  void test_instanceCreationExpression_withSupertypeParams_implicit() {
+    _checkInstanceCreation_withSupertypeParams(false);
+  }
+
+  void test_instanceCreationExpression_withTypeParams() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+class C<E> {
+  const C();
+}
+const c_int = const C<int>();
+const c_num = const C<num>();''');
+    EvaluationResultImpl c_int =
+        _evaluateTopLevelVariable(compilationUnit, "c_int");
+    _assertType(c_int, "C<int>");
+    DartObjectImpl c_int_value = c_int.value;
+    EvaluationResultImpl c_num =
+        _evaluateTopLevelVariable(compilationUnit, "c_num");
+    _assertType(c_num, "C<num>");
+    DartObjectImpl c_num_value = c_num.value;
+    expect(c_int_value == c_num_value, isFalse);
+  }
+
+  void test_isValidSymbol() {
+    expect(ConstantEvaluationEngine.isValidPublicSymbol(""), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.bar"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo\$"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo\$bar"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("iff"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("gif"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("if\$"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("\$if"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo="), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.bar="), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.+"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("void"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("_foo"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("_foo.bar"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo._bar"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("if"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("if.foo"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.if"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo=.bar"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo."), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("+.foo"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("void.foo"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.void"), isFalse);
+  }
+
+  void test_length_of_improperly_typed_string_expression() {
+    // Since type annotations are ignored in unchecked mode, the improper
+    // types on s1 and s2 shouldn't prevent us from evaluating i to
+    // 'alpha'.length.
+    CompilationUnit compilationUnit = resolveSource('''
+const int s1 = 'alpha';
+const int s2 = 'beta';
+const int i = (true ? s1 : s2).length;
+''');
+    ConstTopLevelVariableElementImpl element =
+        findTopLevelDeclaration(compilationUnit, 'i').element;
+    EvaluationResultImpl result = element.evaluationResult;
+    expect(_assertValidInt(result), 5);
+  }
+
+  void test_length_of_improperly_typed_string_identifier() {
+    // Since type annotations are ignored in unchecked mode, the improper type
+    // on s shouldn't prevent us from evaluating i to 'alpha'.length.
+    CompilationUnit compilationUnit = resolveSource('''
+const int s = 'alpha';
+const int i = s.length;
+''');
+    ConstTopLevelVariableElementImpl element =
+        findTopLevelDeclaration(compilationUnit, 'i').element;
+    EvaluationResultImpl result = element.evaluationResult;
+    expect(_assertValidInt(result), 5);
+  }
+
+  void test_non_static_const_initialized_at_declaration() {
+    // Even though non-static consts are not allowed by the language, we need
+    // to handle them for error recovery purposes.
+    CompilationUnit compilationUnit = resolveSource('''
+class A {
+  const int i = 123;
+  const A();
+}
+
+const A a = const A();
+''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, 'a');
+    Map<String, DartObjectImpl> fields = _assertType(result, "A");
+    expect(fields, hasLength(1));
+    _assertIntField(fields, "i", 123);
+  }
+
+  void test_symbolLiteral_void() {
+    CompilationUnit compilationUnit =
+        resolveSource("const voidSymbol = #void;");
+    VariableDeclaration voidSymbol =
+        findTopLevelDeclaration(compilationUnit, "voidSymbol");
+    EvaluationResultImpl voidSymbolResult =
+        (voidSymbol.element as VariableElementImpl).evaluationResult;
+    DartObjectImpl value = voidSymbolResult.value;
+    expect(value.type, typeProvider.symbolType);
+    expect(value.toSymbolValue(), "void");
+  }
+
+  Map<String, DartObjectImpl> _assertFieldType(
+      Map<String, DartObjectImpl> fields,
+      String fieldName,
+      String expectedType) {
+    DartObjectImpl field = fields[fieldName];
+    expect(field.type.displayName, expectedType);
+    return field.fields;
+  }
+
+  void _assertIntField(
+      Map<String, DartObjectImpl> fields, String fieldName, int expectedValue) {
+    DartObjectImpl field = fields[fieldName];
+    expect(field.type.name, "int");
+    expect(field.toIntValue(), expectedValue);
+  }
+
+  void _assertNullField(Map<String, DartObjectImpl> fields, String fieldName) {
+    DartObjectImpl field = fields[fieldName];
+    expect(field.isNull, isTrue);
+  }
+
+  void _assertProperDependencies(String sourceText,
+      [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) {
+    Source source = addSource(sourceText);
+    LibraryElement element = resolve2(source);
+    CompilationUnit unit =
+        analysisContext.resolveCompilationUnit(source, element);
+    expect(unit, isNotNull);
+    ConstantValueComputer computer = _makeConstantValueComputer();
+    computer.add(unit, source, source);
+    computer.computeValues();
+    assertErrors(source, expectedErrorCodes);
+  }
+
+  Map<String, DartObjectImpl> _assertType(
+      EvaluationResultImpl result, String typeName) {
+    expect(result.value, isNotNull);
+    DartObjectImpl value = result.value;
+    expect(value.type.displayName, typeName);
+    return value.fields;
+  }
+
+  bool _assertValidBool(EvaluationResultImpl result) {
+    expect(result.value, isNotNull);
+    DartObjectImpl value = result.value;
+    expect(value.type, typeProvider.boolType);
+    bool boolValue = value.toBoolValue();
+    expect(boolValue, isNotNull);
+    return boolValue;
+  }
+
+  int _assertValidInt(EvaluationResultImpl result) {
+    expect(result, isNotNull);
+    expect(result.value, isNotNull);
+    DartObjectImpl value = result.value;
+    expect(value.type, typeProvider.intType);
+    return value.toIntValue();
+  }
+
+  void _assertValidNull(EvaluationResultImpl result) {
+    expect(result.value, isNotNull);
+    DartObjectImpl value = result.value;
+    expect(value.type, typeProvider.nullType);
+  }
+
+  String _assertValidString(EvaluationResultImpl result) {
+    expect(result.value, isNotNull);
+    DartObjectImpl value = result.value;
+    expect(value.type, typeProvider.stringType);
+    return value.toStringValue();
+  }
+
+  void _assertValidUnknown(EvaluationResultImpl result) {
+    expect(result.value, isNotNull);
+    DartObjectImpl value = result.value;
+    expect(value.isUnknown, isTrue);
+  }
+
+  EvaluationResultImpl _check_fromEnvironment_bool(
+      String valueInEnvironment, String defaultExpr) {
+    String envVarName = "x";
+    String varName = "foo";
+    if (valueInEnvironment != null) {
+      analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
+    }
+    String defaultArg =
+        defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
+    CompilationUnit compilationUnit = resolveSource(
+        "const $varName = const bool.fromEnvironment('$envVarName'$defaultArg);");
+    return _evaluateTopLevelVariable(compilationUnit, varName);
+  }
+
+  EvaluationResultImpl _check_fromEnvironment_int(
+      String valueInEnvironment, String defaultExpr) {
+    String envVarName = "x";
+    String varName = "foo";
+    if (valueInEnvironment != null) {
+      analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
+    }
+    String defaultArg =
+        defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
+    CompilationUnit compilationUnit = resolveSource(
+        "const $varName = const int.fromEnvironment('$envVarName'$defaultArg);");
+    return _evaluateTopLevelVariable(compilationUnit, varName);
+  }
+
+  EvaluationResultImpl _check_fromEnvironment_string(
+      String valueInEnvironment, String defaultExpr) {
+    String envVarName = "x";
+    String varName = "foo";
+    if (valueInEnvironment != null) {
+      analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
+    }
+    String defaultArg =
+        defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
+    CompilationUnit compilationUnit = resolveSource(
+        "const $varName = const String.fromEnvironment('$envVarName'$defaultArg);");
+    return _evaluateTopLevelVariable(compilationUnit, varName);
+  }
+
+  void _checkInstanceCreation_withSupertypeParams(bool isExplicit) {
+    String superCall = isExplicit ? " : super()" : "";
+    CompilationUnit compilationUnit = resolveSource("""
+class A<T> {
+  const A();
+}
+class B<T, U> extends A<T> {
+  const B()$superCall;
+}
+class C<T, U> extends A<U> {
+  const C()$superCall;
+}
+const b_int_num = const B<int, num>();
+const c_int_num = const C<int, num>();""");
+    EvaluationResultImpl b_int_num =
+        _evaluateTopLevelVariable(compilationUnit, "b_int_num");
+    Map<String, DartObjectImpl> b_int_num_fields =
+        _assertType(b_int_num, "B<int, num>");
+    _assertFieldType(b_int_num_fields, GenericState.SUPERCLASS_FIELD, "A<int>");
+    EvaluationResultImpl c_int_num =
+        _evaluateTopLevelVariable(compilationUnit, "c_int_num");
+    Map<String, DartObjectImpl> c_int_num_fields =
+        _assertType(c_int_num, "C<int, num>");
+    _assertFieldType(c_int_num_fields, GenericState.SUPERCLASS_FIELD, "A<num>");
+  }
+
+  void _checkInstanceCreationOptionalParams(
+      bool isFieldFormal, bool isNamed, bool hasDefault) {
+    String fieldName = "j";
+    String paramName = isFieldFormal ? fieldName : "i";
+    String formalParam =
+        "${isFieldFormal ? "this." : "int "}$paramName${hasDefault ? " = 3" : ""}";
+    CompilationUnit compilationUnit = resolveSource("""
+const x = const A();
+const y = const A(${isNamed ? '$paramName: ' : ''}10);
+class A {
+  const A(${isNamed ? "{$formalParam}" : "[$formalParam]"})${isFieldFormal ? "" : " : $fieldName = $paramName"};
+  final int $fieldName;
+}""");
+    EvaluationResultImpl x = _evaluateTopLevelVariable(compilationUnit, "x");
+    Map<String, DartObjectImpl> fieldsOfX = _assertType(x, "A");
+    expect(fieldsOfX, hasLength(1));
+    if (hasDefault) {
+      _assertIntField(fieldsOfX, fieldName, 3);
+    } else {
+      _assertNullField(fieldsOfX, fieldName);
+    }
+    EvaluationResultImpl y = _evaluateTopLevelVariable(compilationUnit, "y");
+    Map<String, DartObjectImpl> fieldsOfY = _assertType(y, "A");
+    expect(fieldsOfY, hasLength(1));
+    _assertIntField(fieldsOfY, fieldName, 10);
+  }
+
+  /**
+   * Search [compilationUnit] for a class named [className], containing a
+   * method [methodName], with exactly one annotation.  Return the constant
+   * value of the annotation.
+   */
+  EvaluationResultImpl _evaluateAnnotation(
+      CompilationUnit compilationUnit, String className, String memberName) {
+    for (CompilationUnitMember member in compilationUnit.declarations) {
+      if (member is ClassDeclaration && member.name.name == className) {
+        for (ClassMember classMember in member.members) {
+          if (classMember is MethodDeclaration &&
+              classMember.name.name == memberName) {
+            expect(classMember.metadata, hasLength(1));
+            ElementAnnotationImpl elementAnnotation =
+                classMember.metadata[0].elementAnnotation;
+            return elementAnnotation.evaluationResult;
+          }
+        }
+      }
+    }
+    fail('Class member not found');
+    return null;
+  }
+
+  EvaluationResultImpl _evaluateTopLevelVariable(
+      CompilationUnit compilationUnit, String name) {
+    VariableDeclaration varDecl =
+        findTopLevelDeclaration(compilationUnit, name);
+    ConstTopLevelVariableElementImpl varElement = varDecl.element;
+    return varElement.evaluationResult;
+  }
+
+  ConstantValueComputer _makeConstantValueComputer() {
+    ConstantEvaluationValidator_ForTest validator =
+        new ConstantEvaluationValidator_ForTest(analysisContext2);
+    validator.computer = new ConstantValueComputer(
+        analysisContext2,
+        analysisContext2.typeProvider,
+        analysisContext2.declaredVariables,
+        validator,
+        analysisContext2.typeSystem);
+    return validator.computer;
+  }
+
+  void _validate(bool shouldBeValid, VariableDeclarationList declarationList) {
+    for (VariableDeclaration declaration in declarationList.variables) {
+      VariableElementImpl element = declaration.element as VariableElementImpl;
+      expect(element, isNotNull);
+      EvaluationResultImpl result = element.evaluationResult;
+      if (shouldBeValid) {
+        expect(result.value, isNotNull);
+      } else {
+        expect(result.value, isNull);
+      }
+    }
+  }
+}
+
+@reflectiveTest
+class ConstantVisitorTest extends ResolverTestCase {
+  void test_visitBinaryExpression_questionQuestion_notNull_notNull() {
+    Expression left = AstFactory.string2('a');
+    Expression right = AstFactory.string2('b');
+    Expression expression =
+        AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right);
+
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter =
+        new ErrorReporter(errorListener, _dummySource());
+    DartObjectImpl result = _evaluate(expression, errorReporter);
+    expect(result, isNotNull);
+    expect(result.isNull, isFalse);
+    expect(result.toStringValue(), 'a');
+    errorListener.assertNoErrors();
+  }
+
+  void test_visitBinaryExpression_questionQuestion_null_notNull() {
+    Expression left = AstFactory.nullLiteral();
+    Expression right = AstFactory.string2('b');
+    Expression expression =
+        AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right);
+
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter =
+        new ErrorReporter(errorListener, _dummySource());
+    DartObjectImpl result = _evaluate(expression, errorReporter);
+    expect(result, isNotNull);
+    expect(result.isNull, isFalse);
+    expect(result.toStringValue(), 'b');
+    errorListener.assertNoErrors();
+  }
+
+  void test_visitBinaryExpression_questionQuestion_null_null() {
+    Expression left = AstFactory.nullLiteral();
+    Expression right = AstFactory.nullLiteral();
+    Expression expression =
+        AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right);
+
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter =
+        new ErrorReporter(errorListener, _dummySource());
+    DartObjectImpl result = _evaluate(expression, errorReporter);
+    expect(result, isNotNull);
+    expect(result.isNull, isTrue);
+    errorListener.assertNoErrors();
+  }
+
+  void test_visitConditionalExpression_false() {
+    Expression thenExpression = AstFactory.integer(1);
+    Expression elseExpression = AstFactory.integer(0);
+    ConditionalExpression expression = AstFactory.conditionalExpression(
+        AstFactory.booleanLiteral(false), thenExpression, elseExpression);
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter =
+        new ErrorReporter(errorListener, _dummySource());
+    _assertValue(0, _evaluate(expression, errorReporter));
+    errorListener.assertNoErrors();
+  }
+
+  void test_visitConditionalExpression_nonBooleanCondition() {
+    Expression thenExpression = AstFactory.integer(1);
+    Expression elseExpression = AstFactory.integer(0);
+    NullLiteral conditionExpression = AstFactory.nullLiteral();
+    ConditionalExpression expression = AstFactory.conditionalExpression(
+        conditionExpression, thenExpression, elseExpression);
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter =
+        new ErrorReporter(errorListener, _dummySource());
+    DartObjectImpl result = _evaluate(expression, errorReporter);
+    expect(result, isNull);
+    errorListener
+        .assertErrorsWithCodes([CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL]);
+  }
+
+  void test_visitConditionalExpression_nonConstantElse() {
+    Expression thenExpression = AstFactory.integer(1);
+    Expression elseExpression = AstFactory.identifier3("x");
+    ConditionalExpression expression = AstFactory.conditionalExpression(
+        AstFactory.booleanLiteral(true), thenExpression, elseExpression);
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter =
+        new ErrorReporter(errorListener, _dummySource());
+    DartObjectImpl result = _evaluate(expression, errorReporter);
+    expect(result, isNull);
+    errorListener
+        .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]);
+  }
+
+  void test_visitConditionalExpression_nonConstantThen() {
+    Expression thenExpression = AstFactory.identifier3("x");
+    Expression elseExpression = AstFactory.integer(0);
+    ConditionalExpression expression = AstFactory.conditionalExpression(
+        AstFactory.booleanLiteral(true), thenExpression, elseExpression);
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter =
+        new ErrorReporter(errorListener, _dummySource());
+    DartObjectImpl result = _evaluate(expression, errorReporter);
+    expect(result, isNull);
+    errorListener
+        .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]);
+  }
+
+  void test_visitConditionalExpression_true() {
+    Expression thenExpression = AstFactory.integer(1);
+    Expression elseExpression = AstFactory.integer(0);
+    ConditionalExpression expression = AstFactory.conditionalExpression(
+        AstFactory.booleanLiteral(true), thenExpression, elseExpression);
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter =
+        new ErrorReporter(errorListener, _dummySource());
+    _assertValue(1, _evaluate(expression, errorReporter));
+    errorListener.assertNoErrors();
+  }
+
+  void test_visitSimpleIdentifier_className() {
+    CompilationUnit compilationUnit = resolveSource('''
+const a = C;
+class C {}
+''');
+    DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null);
+    expect(result.type, typeProvider.typeType);
+    expect(result.toTypeValue().name, 'C');
+  }
+
+  void test_visitSimpleIdentifier_dynamic() {
+    CompilationUnit compilationUnit = resolveSource('''
+const a = dynamic;
+''');
+    DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null);
+    expect(result.type, typeProvider.typeType);
+    expect(result.toTypeValue(), typeProvider.dynamicType);
+  }
+
+  void test_visitSimpleIdentifier_inEnvironment() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const a = b;
+const b = 3;''');
+    Map<String, DartObjectImpl> environment = new Map<String, DartObjectImpl>();
+    DartObjectImpl six =
+        new DartObjectImpl(typeProvider.intType, new IntState(6));
+    environment["b"] = six;
+    _assertValue(6, _evaluateConstant(compilationUnit, "a", environment));
+  }
+
+  void test_visitSimpleIdentifier_notInEnvironment() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const a = b;
+const b = 3;''');
+    Map<String, DartObjectImpl> environment = new Map<String, DartObjectImpl>();
+    DartObjectImpl six =
+        new DartObjectImpl(typeProvider.intType, new IntState(6));
+    environment["c"] = six;
+    _assertValue(3, _evaluateConstant(compilationUnit, "a", environment));
+  }
+
+  void test_visitSimpleIdentifier_withoutEnvironment() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const a = b;
+const b = 3;''');
+    _assertValue(3, _evaluateConstant(compilationUnit, "a", null));
+  }
+
+  void _assertValue(int expectedValue, DartObjectImpl result) {
+    expect(result, isNotNull);
+    expect(result.type.name, "int");
+    expect(result.toIntValue(), expectedValue);
+  }
+
+  NonExistingSource _dummySource() {
+    String path = '/test.dart';
+    return new NonExistingSource(path, toUri(path), UriKind.FILE_URI);
+  }
+
+  DartObjectImpl _evaluate(Expression expression, ErrorReporter errorReporter) {
+    return expression.accept(new ConstantVisitor(
+        new ConstantEvaluationEngine(
+            new TestTypeProvider(), new DeclaredVariables(),
+            typeSystem: new TypeSystemImpl()),
+        errorReporter));
+  }
+
+  DartObjectImpl _evaluateConstant(CompilationUnit compilationUnit, String name,
+      Map<String, DartObjectImpl> lexicalEnvironment) {
+    Source source = compilationUnit.element.source;
+    Expression expression =
+        findTopLevelConstantExpression(compilationUnit, name);
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
+    DartObjectImpl result = expression.accept(new ConstantVisitor(
+        new ConstantEvaluationEngine(typeProvider, new DeclaredVariables(),
+            typeSystem: typeSystem),
+        errorReporter,
+        lexicalEnvironment: lexicalEnvironment));
+    errorListener.assertNoErrors();
+    return result;
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/constant/test_all.dart b/pkg/analyzer/test/src/dart/constant/test_all.dart
new file mode 100644
index 0000000..a6eb5b6
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/constant/test_all.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.test.src.dart.constant.test_all;
+
+import 'package:unittest/unittest.dart';
+
+import '../../../utils.dart';
+import 'evaluation_test.dart' as evaluation;
+import 'utilities_test.dart' as utilities;
+import 'value_test.dart' as value;
+
+/// Utility for manually running all tests.
+main() {
+  initializeTestEnvironment();
+  group('constant tests', () {
+    evaluation.main();
+    utilities.main();
+    value.main();
+  });
+}
diff --git a/pkg/analyzer/test/src/dart/constant/utilities_test.dart b/pkg/analyzer/test/src/dart/constant/utilities_test.dart
new file mode 100644
index 0000000..a922cf5
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/constant/utilities_test.dart
@@ -0,0 +1,354 @@
+// 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 analyzer.test.src.dart.constant.utilities_test;
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/generated/constant.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/generated/testing/ast_factory.dart';
+import 'package:analyzer/src/generated/testing/element_factory.dart';
+import 'package:analyzer/src/generated/testing/test_type_provider.dart';
+import 'package:analyzer/src/generated/utilities_collection.dart';
+import 'package:analyzer/src/task/dart.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../../generated/engine_test.dart';
+import '../../../generated/test_support.dart';
+import '../../../reflective_tests.dart';
+import '../../../utils.dart';
+
+main() {
+  initializeTestEnvironment();
+  runReflectiveTests(ConstantFinderTest);
+  runReflectiveTests(ReferenceFinderTest);
+}
+
+@reflectiveTest
+class ConstantFinderTest {
+  AstNode _node;
+  TypeProvider _typeProvider;
+  AnalysisContext _context;
+  Source _source;
+
+  void setUp() {
+    _typeProvider = new TestTypeProvider();
+    _context = new _TestAnalysisContext();
+    _source = new TestSource();
+  }
+
+  /**
+   * Test an annotation that consists solely of an identifier (and hence
+   * represents a reference to a compile-time constant variable).
+   */
+  void test_visitAnnotation_constantVariable() {
+    CompilationUnitElement compilationUnitElement =
+        ElementFactory.compilationUnit('/test.dart', _source)..source = _source;
+    ElementFactory.library(_context, 'L').definingCompilationUnit =
+        compilationUnitElement;
+    ElementAnnotationImpl elementAnnotation =
+        new ElementAnnotationImpl(compilationUnitElement);
+    _node = elementAnnotation.annotationAst = AstFactory.annotation(
+        AstFactory.identifier3('x'))..elementAnnotation = elementAnnotation;
+    expect(_findAnnotations(), contains(_node));
+  }
+
+  /**
+   * Test an annotation that represents the invocation of a constant
+   * constructor.
+   */
+  void test_visitAnnotation_invocation() {
+    CompilationUnitElement compilationUnitElement =
+        ElementFactory.compilationUnit('/test.dart', _source)..source = _source;
+    ElementFactory.library(_context, 'L').definingCompilationUnit =
+        compilationUnitElement;
+    ElementAnnotationImpl elementAnnotation =
+        new ElementAnnotationImpl(compilationUnitElement);
+    _node = elementAnnotation.annotationAst = AstFactory.annotation2(
+        AstFactory.identifier3('A'), null, AstFactory.argumentList())
+      ..elementAnnotation = elementAnnotation;
+    expect(_findAnnotations(), contains(_node));
+  }
+
+  void test_visitAnnotation_partOf() {
+    // Analyzer ignores annotations on "part of" directives.
+    Annotation annotation = AstFactory.annotation2(
+        AstFactory.identifier3('A'), null, AstFactory.argumentList());
+    _node = AstFactory.partOfDirective2(
+        <Annotation>[annotation], AstFactory.libraryIdentifier2(<String>['L']));
+    expect(_findConstants(), isEmpty);
+  }
+
+  void test_visitConstructorDeclaration_const() {
+    ConstructorElement element = _setupConstructorDeclaration("A", true);
+    expect(_findConstants(), contains(element));
+  }
+
+  void test_visitConstructorDeclaration_nonConst() {
+    _setupConstructorDeclaration("A", false);
+    expect(_findConstants(), isEmpty);
+  }
+
+  void test_visitVariableDeclaration_const() {
+    VariableElement element = _setupVariableDeclaration("v", true, true);
+    expect(_findConstants(), contains(element));
+  }
+
+  void test_visitVariableDeclaration_final_inClass() {
+    _setupFieldDeclaration('C', 'f', Keyword.FINAL);
+    expect(_findConstants(), isEmpty);
+  }
+
+  void test_visitVariableDeclaration_final_inClassWithConstConstructor() {
+    VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
+        hasConstConstructor: true);
+    expect(_findConstants(), contains(field.element));
+  }
+
+  void test_visitVariableDeclaration_final_outsideClass() {
+    _setupVariableDeclaration('v', false, true, isFinal: true);
+    expect(_findConstants(), isEmpty);
+  }
+
+  void test_visitVariableDeclaration_noInitializer() {
+    _setupVariableDeclaration("v", true, false);
+    expect(_findConstants(), isEmpty);
+  }
+
+  void test_visitVariableDeclaration_nonConst() {
+    _setupVariableDeclaration("v", false, true);
+    expect(_findConstants(), isEmpty);
+  }
+
+  void test_visitVariableDeclaration_static_const_inClass() {
+    VariableDeclaration field =
+        _setupFieldDeclaration('C', 'f', Keyword.CONST, isStatic: true);
+    expect(_findConstants(), contains(field.element));
+  }
+
+  void
+      test_visitVariableDeclaration_static_const_inClassWithConstConstructor() {
+    VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.CONST,
+        isStatic: true, hasConstConstructor: true);
+    expect(_findConstants(), contains(field.element));
+  }
+
+  void
+      test_visitVariableDeclaration_static_final_inClassWithConstConstructor() {
+    VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
+        isStatic: true, hasConstConstructor: true);
+    expect(_findConstants(), isNot(contains(field.element)));
+  }
+
+  void
+      test_visitVariableDeclaration_uninitialized_final_inClassWithConstConstructor() {
+    VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
+        isInitialized: false, hasConstConstructor: true);
+    expect(_findConstants(), isNot(contains(field.element)));
+  }
+
+  void test_visitVariableDeclaration_uninitialized_static_const_inClass() {
+    _setupFieldDeclaration('C', 'f', Keyword.CONST,
+        isStatic: true, isInitialized: false);
+    expect(_findConstants(), isEmpty);
+  }
+
+  List<Annotation> _findAnnotations() {
+    Set<Annotation> annotations = new Set<Annotation>();
+    for (ConstantEvaluationTarget target in _findConstants()) {
+      if (target is ElementAnnotationImpl) {
+        expect(target.context, same(_context));
+        expect(target.source, same(_source));
+        annotations.add(target.annotationAst);
+      }
+    }
+    return new List<Annotation>.from(annotations);
+  }
+
+  List<ConstantEvaluationTarget> _findConstants() {
+    ConstantFinder finder = new ConstantFinder(_context, _source, _source);
+    _node.accept(finder);
+    List<ConstantEvaluationTarget> constants = finder.constantsToCompute;
+    expect(constants, isNotNull);
+    return constants;
+  }
+
+  ConstructorElement _setupConstructorDeclaration(String name, bool isConst) {
+    Keyword constKeyword = isConst ? Keyword.CONST : null;
+    ConstructorDeclaration constructorDeclaration =
+        AstFactory.constructorDeclaration2(
+            constKeyword,
+            null,
+            null,
+            name,
+            AstFactory.formalParameterList(),
+            null,
+            AstFactory.blockFunctionBody2());
+    ClassElement classElement = ElementFactory.classElement2(name);
+    ConstructorElement element =
+        ElementFactory.constructorElement(classElement, name, isConst);
+    constructorDeclaration.element = element;
+    _node = constructorDeclaration;
+    return element;
+  }
+
+  VariableDeclaration _setupFieldDeclaration(
+      String className, String fieldName, Keyword keyword,
+      {bool isInitialized: true,
+      bool isStatic: false,
+      bool hasConstConstructor: false}) {
+    VariableDeclaration variableDeclaration = isInitialized
+        ? AstFactory.variableDeclaration2(fieldName, AstFactory.integer(0))
+        : AstFactory.variableDeclaration(fieldName);
+    VariableElement fieldElement = ElementFactory.fieldElement(
+        fieldName,
+        isStatic,
+        keyword == Keyword.FINAL,
+        keyword == Keyword.CONST,
+        _typeProvider.intType);
+    variableDeclaration.name.staticElement = fieldElement;
+    FieldDeclaration fieldDeclaration = AstFactory.fieldDeclaration2(
+        isStatic, keyword, <VariableDeclaration>[variableDeclaration]);
+    ClassDeclaration classDeclaration =
+        AstFactory.classDeclaration(null, className, null, null, null, null);
+    classDeclaration.members.add(fieldDeclaration);
+    _node = classDeclaration;
+    ClassElementImpl classElement = ElementFactory.classElement2(className);
+    classElement.fields = <FieldElement>[fieldElement];
+    classDeclaration.name.staticElement = classElement;
+    if (hasConstConstructor) {
+      ConstructorDeclaration constructorDeclaration =
+          AstFactory.constructorDeclaration2(
+              Keyword.CONST,
+              null,
+              AstFactory.identifier3(className),
+              null,
+              AstFactory.formalParameterList(),
+              null,
+              AstFactory.blockFunctionBody2());
+      classDeclaration.members.add(constructorDeclaration);
+      ConstructorElement constructorElement =
+          ElementFactory.constructorElement(classElement, '', true);
+      constructorDeclaration.element = constructorElement;
+      classElement.constructors = <ConstructorElement>[constructorElement];
+    } else {
+      classElement.constructors = ConstructorElement.EMPTY_LIST;
+    }
+    return variableDeclaration;
+  }
+
+  VariableElement _setupVariableDeclaration(
+      String name, bool isConst, bool isInitialized,
+      {isFinal: false}) {
+    VariableDeclaration variableDeclaration = isInitialized
+        ? AstFactory.variableDeclaration2(name, AstFactory.integer(0))
+        : AstFactory.variableDeclaration(name);
+    SimpleIdentifier identifier = variableDeclaration.name;
+    VariableElement element = ElementFactory.localVariableElement(identifier);
+    identifier.staticElement = element;
+    Keyword keyword = isConst ? Keyword.CONST : isFinal ? Keyword.FINAL : null;
+    AstFactory.variableDeclarationList2(keyword, [variableDeclaration]);
+    _node = variableDeclaration;
+    return element;
+  }
+}
+
+@reflectiveTest
+class ReferenceFinderTest {
+  DirectedGraph<ConstantEvaluationTarget> _referenceGraph;
+  VariableElement _head;
+  Element _tail;
+
+  void setUp() {
+    _referenceGraph = new DirectedGraph<ConstantEvaluationTarget>();
+    _head = ElementFactory.topLevelVariableElement2("v1");
+  }
+
+  void test_visitSimpleIdentifier_const() {
+    _visitNode(_makeTailVariable("v2", true));
+    _assertOneArc(_tail);
+  }
+
+  void test_visitSuperConstructorInvocation_const() {
+    _visitNode(_makeTailSuperConstructorInvocation("A", true));
+    _assertOneArc(_tail);
+  }
+
+  void test_visitSuperConstructorInvocation_nonConst() {
+    _visitNode(_makeTailSuperConstructorInvocation("A", false));
+    _assertOneArc(_tail);
+  }
+
+  void test_visitSuperConstructorInvocation_unresolved() {
+    SuperConstructorInvocation superConstructorInvocation =
+        AstFactory.superConstructorInvocation();
+    _visitNode(superConstructorInvocation);
+    _assertNoArcs();
+  }
+
+  void _assertNoArcs() {
+    Set<ConstantEvaluationTarget> tails = _referenceGraph.getTails(_head);
+    expect(tails, hasLength(0));
+  }
+
+  void _assertOneArc(Element tail) {
+    Set<ConstantEvaluationTarget> tails = _referenceGraph.getTails(_head);
+    expect(tails, hasLength(1));
+    expect(tails.first, same(tail));
+  }
+
+  ReferenceFinder _createReferenceFinder(ConstantEvaluationTarget source) =>
+      new ReferenceFinder((ConstantEvaluationTarget dependency) {
+        _referenceGraph.addEdge(source, dependency);
+      });
+  SuperConstructorInvocation _makeTailSuperConstructorInvocation(
+      String name, bool isConst) {
+    List<ConstructorInitializer> initializers =
+        new List<ConstructorInitializer>();
+    ConstructorDeclaration constructorDeclaration =
+        AstFactory.constructorDeclaration(AstFactory.identifier3(name), null,
+            AstFactory.formalParameterList(), initializers);
+    if (isConst) {
+      constructorDeclaration.constKeyword = new KeywordToken(Keyword.CONST, 0);
+    }
+    ClassElementImpl classElement = ElementFactory.classElement2(name);
+    SuperConstructorInvocation superConstructorInvocation =
+        AstFactory.superConstructorInvocation();
+    ConstructorElementImpl constructorElement =
+        ElementFactory.constructorElement(classElement, name, isConst);
+    _tail = constructorElement;
+    superConstructorInvocation.staticElement = constructorElement;
+    return superConstructorInvocation;
+  }
+
+  SimpleIdentifier _makeTailVariable(String name, bool isConst) {
+    VariableDeclaration variableDeclaration =
+        AstFactory.variableDeclaration(name);
+    ConstLocalVariableElementImpl variableElement =
+        ElementFactory.constLocalVariableElement(name);
+    _tail = variableElement;
+    variableElement.const3 = isConst;
+    AstFactory.variableDeclarationList2(
+        isConst ? Keyword.CONST : Keyword.VAR, [variableDeclaration]);
+    SimpleIdentifier identifier = AstFactory.identifier3(name);
+    identifier.staticElement = variableElement;
+    return identifier;
+  }
+
+  void _visitNode(AstNode node) {
+    node.accept(_createReferenceFinder(_head));
+  }
+}
+
+class _TestAnalysisContext extends TestAnalysisContext {
+  @override
+  InternalAnalysisContext getContextFor(Source source) => this;
+}
diff --git a/pkg/analyzer/test/src/dart/constant/value_test.dart b/pkg/analyzer/test/src/dart/constant/value_test.dart
new file mode 100644
index 0000000..cb64c4c
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/constant/value_test.dart
@@ -0,0 +1,2029 @@
+// 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 analyzer.test.src.dart.constant.value_test;
+
+import 'package:analyzer/src/generated/constant.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/testing/test_type_provider.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../../generated/test_support.dart';
+import '../../../reflective_tests.dart';
+import '../../../utils.dart';
+
+main() {
+  initializeTestEnvironment();
+  runReflectiveTests(DartObjectImplTest);
+}
+
+const int LONG_MAX_VALUE = 0x7fffffffffffffff;
+
+@reflectiveTest
+class DartObjectImplTest extends EngineTestCase {
+  TypeProvider _typeProvider = new TestTypeProvider();
+
+  void test_add_knownDouble_knownDouble() {
+    _assertAdd(_doubleValue(3.0), _doubleValue(1.0), _doubleValue(2.0));
+  }
+
+  void test_add_knownDouble_knownInt() {
+    _assertAdd(_doubleValue(3.0), _doubleValue(1.0), _intValue(2));
+  }
+
+  void test_add_knownDouble_unknownDouble() {
+    _assertAdd(_doubleValue(null), _doubleValue(1.0), _doubleValue(null));
+  }
+
+  void test_add_knownDouble_unknownInt() {
+    _assertAdd(_doubleValue(null), _doubleValue(1.0), _intValue(null));
+  }
+
+  void test_add_knownInt_knownInt() {
+    _assertAdd(_intValue(3), _intValue(1), _intValue(2));
+  }
+
+  void test_add_knownInt_knownString() {
+    _assertAdd(null, _intValue(1), _stringValue("2"));
+  }
+
+  void test_add_knownInt_unknownDouble() {
+    _assertAdd(_doubleValue(null), _intValue(1), _doubleValue(null));
+  }
+
+  void test_add_knownInt_unknownInt() {
+    _assertAdd(_intValue(null), _intValue(1), _intValue(null));
+  }
+
+  void test_add_knownString_knownInt() {
+    _assertAdd(null, _stringValue("1"), _intValue(2));
+  }
+
+  void test_add_knownString_knownString() {
+    _assertAdd(_stringValue("ab"), _stringValue("a"), _stringValue("b"));
+  }
+
+  void test_add_knownString_unknownString() {
+    _assertAdd(_stringValue(null), _stringValue("a"), _stringValue(null));
+  }
+
+  void test_add_unknownDouble_knownDouble() {
+    _assertAdd(_doubleValue(null), _doubleValue(null), _doubleValue(2.0));
+  }
+
+  void test_add_unknownDouble_knownInt() {
+    _assertAdd(_doubleValue(null), _doubleValue(null), _intValue(2));
+  }
+
+  void test_add_unknownInt_knownDouble() {
+    _assertAdd(_doubleValue(null), _intValue(null), _doubleValue(2.0));
+  }
+
+  void test_add_unknownInt_knownInt() {
+    _assertAdd(_intValue(null), _intValue(null), _intValue(2));
+  }
+
+  void test_add_unknownString_knownString() {
+    _assertAdd(_stringValue(null), _stringValue(null), _stringValue("b"));
+  }
+
+  void test_add_unknownString_unknownString() {
+    _assertAdd(_stringValue(null), _stringValue(null), _stringValue(null));
+  }
+
+  void test_bitAnd_knownInt_knownInt() {
+    _assertBitAnd(_intValue(2), _intValue(6), _intValue(3));
+  }
+
+  void test_bitAnd_knownInt_knownString() {
+    _assertBitAnd(null, _intValue(6), _stringValue("3"));
+  }
+
+  void test_bitAnd_knownInt_unknownInt() {
+    _assertBitAnd(_intValue(null), _intValue(6), _intValue(null));
+  }
+
+  void test_bitAnd_knownString_knownInt() {
+    _assertBitAnd(null, _stringValue("6"), _intValue(3));
+  }
+
+  void test_bitAnd_unknownInt_knownInt() {
+    _assertBitAnd(_intValue(null), _intValue(null), _intValue(3));
+  }
+
+  void test_bitAnd_unknownInt_unknownInt() {
+    _assertBitAnd(_intValue(null), _intValue(null), _intValue(null));
+  }
+
+  void test_bitNot_knownInt() {
+    _assertBitNot(_intValue(-4), _intValue(3));
+  }
+
+  void test_bitNot_knownString() {
+    _assertBitNot(null, _stringValue("6"));
+  }
+
+  void test_bitNot_unknownInt() {
+    _assertBitNot(_intValue(null), _intValue(null));
+  }
+
+  void test_bitOr_knownInt_knownInt() {
+    _assertBitOr(_intValue(7), _intValue(6), _intValue(3));
+  }
+
+  void test_bitOr_knownInt_knownString() {
+    _assertBitOr(null, _intValue(6), _stringValue("3"));
+  }
+
+  void test_bitOr_knownInt_unknownInt() {
+    _assertBitOr(_intValue(null), _intValue(6), _intValue(null));
+  }
+
+  void test_bitOr_knownString_knownInt() {
+    _assertBitOr(null, _stringValue("6"), _intValue(3));
+  }
+
+  void test_bitOr_unknownInt_knownInt() {
+    _assertBitOr(_intValue(null), _intValue(null), _intValue(3));
+  }
+
+  void test_bitOr_unknownInt_unknownInt() {
+    _assertBitOr(_intValue(null), _intValue(null), _intValue(null));
+  }
+
+  void test_bitXor_knownInt_knownInt() {
+    _assertBitXor(_intValue(5), _intValue(6), _intValue(3));
+  }
+
+  void test_bitXor_knownInt_knownString() {
+    _assertBitXor(null, _intValue(6), _stringValue("3"));
+  }
+
+  void test_bitXor_knownInt_unknownInt() {
+    _assertBitXor(_intValue(null), _intValue(6), _intValue(null));
+  }
+
+  void test_bitXor_knownString_knownInt() {
+    _assertBitXor(null, _stringValue("6"), _intValue(3));
+  }
+
+  void test_bitXor_unknownInt_knownInt() {
+    _assertBitXor(_intValue(null), _intValue(null), _intValue(3));
+  }
+
+  void test_bitXor_unknownInt_unknownInt() {
+    _assertBitXor(_intValue(null), _intValue(null), _intValue(null));
+  }
+
+  void test_concatenate_knownInt_knownString() {
+    _assertConcatenate(null, _intValue(2), _stringValue("def"));
+  }
+
+  void test_concatenate_knownString_knownInt() {
+    _assertConcatenate(null, _stringValue("abc"), _intValue(3));
+  }
+
+  void test_concatenate_knownString_knownString() {
+    _assertConcatenate(
+        _stringValue("abcdef"), _stringValue("abc"), _stringValue("def"));
+  }
+
+  void test_concatenate_knownString_unknownString() {
+    _assertConcatenate(
+        _stringValue(null), _stringValue("abc"), _stringValue(null));
+  }
+
+  void test_concatenate_unknownString_knownString() {
+    _assertConcatenate(
+        _stringValue(null), _stringValue(null), _stringValue("def"));
+  }
+
+  void test_divide_knownDouble_knownDouble() {
+    _assertDivide(_doubleValue(3.0), _doubleValue(6.0), _doubleValue(2.0));
+  }
+
+  void test_divide_knownDouble_knownInt() {
+    _assertDivide(_doubleValue(3.0), _doubleValue(6.0), _intValue(2));
+  }
+
+  void test_divide_knownDouble_unknownDouble() {
+    _assertDivide(_doubleValue(null), _doubleValue(6.0), _doubleValue(null));
+  }
+
+  void test_divide_knownDouble_unknownInt() {
+    _assertDivide(_doubleValue(null), _doubleValue(6.0), _intValue(null));
+  }
+
+  void test_divide_knownInt_knownInt() {
+    _assertDivide(_doubleValue(3.0), _intValue(6), _intValue(2));
+  }
+
+  void test_divide_knownInt_knownString() {
+    _assertDivide(null, _intValue(6), _stringValue("2"));
+  }
+
+  void test_divide_knownInt_unknownDouble() {
+    _assertDivide(_doubleValue(null), _intValue(6), _doubleValue(null));
+  }
+
+  void test_divide_knownInt_unknownInt() {
+    _assertDivide(_doubleValue(null), _intValue(6), _intValue(null));
+  }
+
+  void test_divide_knownString_knownInt() {
+    _assertDivide(null, _stringValue("6"), _intValue(2));
+  }
+
+  void test_divide_unknownDouble_knownDouble() {
+    _assertDivide(_doubleValue(null), _doubleValue(null), _doubleValue(2.0));
+  }
+
+  void test_divide_unknownDouble_knownInt() {
+    _assertDivide(_doubleValue(null), _doubleValue(null), _intValue(2));
+  }
+
+  void test_divide_unknownInt_knownDouble() {
+    _assertDivide(_doubleValue(null), _intValue(null), _doubleValue(2.0));
+  }
+
+  void test_divide_unknownInt_knownInt() {
+    _assertDivide(_doubleValue(null), _intValue(null), _intValue(2));
+  }
+
+  void test_equalEqual_bool_false() {
+    _assertEqualEqual(_boolValue(false), _boolValue(false), _boolValue(true));
+  }
+
+  void test_equalEqual_bool_true() {
+    _assertEqualEqual(_boolValue(true), _boolValue(true), _boolValue(true));
+  }
+
+  void test_equalEqual_bool_unknown() {
+    _assertEqualEqual(_boolValue(null), _boolValue(null), _boolValue(false));
+  }
+
+  void test_equalEqual_double_false() {
+    _assertEqualEqual(_boolValue(false), _doubleValue(2.0), _doubleValue(4.0));
+  }
+
+  void test_equalEqual_double_true() {
+    _assertEqualEqual(_boolValue(true), _doubleValue(2.0), _doubleValue(2.0));
+  }
+
+  void test_equalEqual_double_unknown() {
+    _assertEqualEqual(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
+  }
+
+  void test_equalEqual_int_false() {
+    _assertEqualEqual(_boolValue(false), _intValue(-5), _intValue(5));
+  }
+
+  void test_equalEqual_int_true() {
+    _assertEqualEqual(_boolValue(true), _intValue(5), _intValue(5));
+  }
+
+  void test_equalEqual_int_unknown() {
+    _assertEqualEqual(_boolValue(null), _intValue(null), _intValue(3));
+  }
+
+  void test_equalEqual_list_empty() {
+    _assertEqualEqual(null, _listValue(), _listValue());
+  }
+
+  void test_equalEqual_list_false() {
+    _assertEqualEqual(null, _listValue(), _listValue());
+  }
+
+  void test_equalEqual_map_empty() {
+    _assertEqualEqual(null, _mapValue(), _mapValue());
+  }
+
+  void test_equalEqual_map_false() {
+    _assertEqualEqual(null, _mapValue(), _mapValue());
+  }
+
+  void test_equalEqual_null() {
+    _assertEqualEqual(_boolValue(true), _nullValue(), _nullValue());
+  }
+
+  void test_equalEqual_string_false() {
+    _assertEqualEqual(
+        _boolValue(false), _stringValue("abc"), _stringValue("def"));
+  }
+
+  void test_equalEqual_string_true() {
+    _assertEqualEqual(
+        _boolValue(true), _stringValue("abc"), _stringValue("abc"));
+  }
+
+  void test_equalEqual_string_unknown() {
+    _assertEqualEqual(
+        _boolValue(null), _stringValue(null), _stringValue("def"));
+  }
+
+  void test_equals_list_false_differentSizes() {
+    expect(
+        _listValue([_boolValue(true)]) ==
+            _listValue([_boolValue(true), _boolValue(false)]),
+        isFalse);
+  }
+
+  void test_equals_list_false_sameSize() {
+    expect(_listValue([_boolValue(true)]) == _listValue([_boolValue(false)]),
+        isFalse);
+  }
+
+  void test_equals_list_true_empty() {
+    expect(_listValue(), _listValue());
+  }
+
+  void test_equals_list_true_nonEmpty() {
+    expect(_listValue([_boolValue(true)]), _listValue([_boolValue(true)]));
+  }
+
+  void test_equals_map_true_empty() {
+    expect(_mapValue(), _mapValue());
+  }
+
+  void test_equals_symbol_false() {
+    expect(_symbolValue("a") == _symbolValue("b"), isFalse);
+  }
+
+  void test_equals_symbol_true() {
+    expect(_symbolValue("a"), _symbolValue("a"));
+  }
+
+  void test_getValue_bool_false() {
+    expect(_boolValue(false).toBoolValue(), false);
+  }
+
+  void test_getValue_bool_true() {
+    expect(_boolValue(true).toBoolValue(), true);
+  }
+
+  void test_getValue_bool_unknown() {
+    expect(_boolValue(null).toBoolValue(), isNull);
+  }
+
+  void test_getValue_double_known() {
+    double value = 2.3;
+    expect(_doubleValue(value).toDoubleValue(), value);
+  }
+
+  void test_getValue_double_unknown() {
+    expect(_doubleValue(null).toDoubleValue(), isNull);
+  }
+
+  void test_getValue_int_known() {
+    int value = 23;
+    expect(_intValue(value).toIntValue(), value);
+  }
+
+  void test_getValue_int_unknown() {
+    expect(_intValue(null).toIntValue(), isNull);
+  }
+
+  void test_getValue_list_empty() {
+    Object result = _listValue().toListValue();
+    _assertInstanceOfObjectArray(result);
+    List<Object> array = result as List<Object>;
+    expect(array, hasLength(0));
+  }
+
+  void test_getValue_list_valid() {
+    Object result = _listValue([_intValue(23)]).toListValue();
+    _assertInstanceOfObjectArray(result);
+    List<Object> array = result as List<Object>;
+    expect(array, hasLength(1));
+  }
+
+  void test_getValue_map_empty() {
+    Object result = _mapValue().toMapValue();
+    EngineTestCase.assertInstanceOf((obj) => obj is Map, Map, result);
+    Map map = result as Map;
+    expect(map, hasLength(0));
+  }
+
+  void test_getValue_map_valid() {
+    Object result =
+        _mapValue([_stringValue("key"), _stringValue("value")]).toMapValue();
+    EngineTestCase.assertInstanceOf((obj) => obj is Map, Map, result);
+    Map map = result as Map;
+    expect(map, hasLength(1));
+  }
+
+  void test_getValue_null() {
+    expect(_nullValue().isNull, isTrue);
+  }
+
+  void test_getValue_string_known() {
+    String value = "twenty-three";
+    expect(_stringValue(value).toStringValue(), value);
+  }
+
+  void test_getValue_string_unknown() {
+    expect(_stringValue(null).toStringValue(), isNull);
+  }
+
+  void test_greaterThan_knownDouble_knownDouble_false() {
+    _assertGreaterThan(_boolValue(false), _doubleValue(1.0), _doubleValue(2.0));
+  }
+
+  void test_greaterThan_knownDouble_knownDouble_true() {
+    _assertGreaterThan(_boolValue(true), _doubleValue(2.0), _doubleValue(1.0));
+  }
+
+  void test_greaterThan_knownDouble_knownInt_false() {
+    _assertGreaterThan(_boolValue(false), _doubleValue(1.0), _intValue(2));
+  }
+
+  void test_greaterThan_knownDouble_knownInt_true() {
+    _assertGreaterThan(_boolValue(true), _doubleValue(2.0), _intValue(1));
+  }
+
+  void test_greaterThan_knownDouble_unknownDouble() {
+    _assertGreaterThan(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
+  }
+
+  void test_greaterThan_knownDouble_unknownInt() {
+    _assertGreaterThan(_boolValue(null), _doubleValue(1.0), _intValue(null));
+  }
+
+  void test_greaterThan_knownInt_knownInt_false() {
+    _assertGreaterThan(_boolValue(false), _intValue(1), _intValue(2));
+  }
+
+  void test_greaterThan_knownInt_knownInt_true() {
+    _assertGreaterThan(_boolValue(true), _intValue(2), _intValue(1));
+  }
+
+  void test_greaterThan_knownInt_knownString() {
+    _assertGreaterThan(null, _intValue(1), _stringValue("2"));
+  }
+
+  void test_greaterThan_knownInt_unknownDouble() {
+    _assertGreaterThan(_boolValue(null), _intValue(1), _doubleValue(null));
+  }
+
+  void test_greaterThan_knownInt_unknownInt() {
+    _assertGreaterThan(_boolValue(null), _intValue(1), _intValue(null));
+  }
+
+  void test_greaterThan_knownString_knownInt() {
+    _assertGreaterThan(null, _stringValue("1"), _intValue(2));
+  }
+
+  void test_greaterThan_unknownDouble_knownDouble() {
+    _assertGreaterThan(_boolValue(null), _doubleValue(null), _doubleValue(2.0));
+  }
+
+  void test_greaterThan_unknownDouble_knownInt() {
+    _assertGreaterThan(_boolValue(null), _doubleValue(null), _intValue(2));
+  }
+
+  void test_greaterThan_unknownInt_knownDouble() {
+    _assertGreaterThan(_boolValue(null), _intValue(null), _doubleValue(2.0));
+  }
+
+  void test_greaterThan_unknownInt_knownInt() {
+    _assertGreaterThan(_boolValue(null), _intValue(null), _intValue(2));
+  }
+
+  void test_greaterThanOrEqual_knownDouble_knownDouble_false() {
+    _assertGreaterThanOrEqual(
+        _boolValue(false), _doubleValue(1.0), _doubleValue(2.0));
+  }
+
+  void test_greaterThanOrEqual_knownDouble_knownDouble_true() {
+    _assertGreaterThanOrEqual(
+        _boolValue(true), _doubleValue(2.0), _doubleValue(1.0));
+  }
+
+  void test_greaterThanOrEqual_knownDouble_knownInt_false() {
+    _assertGreaterThanOrEqual(
+        _boolValue(false), _doubleValue(1.0), _intValue(2));
+  }
+
+  void test_greaterThanOrEqual_knownDouble_knownInt_true() {
+    _assertGreaterThanOrEqual(
+        _boolValue(true), _doubleValue(2.0), _intValue(1));
+  }
+
+  void test_greaterThanOrEqual_knownDouble_unknownDouble() {
+    _assertGreaterThanOrEqual(
+        _boolValue(null), _doubleValue(1.0), _doubleValue(null));
+  }
+
+  void test_greaterThanOrEqual_knownDouble_unknownInt() {
+    _assertGreaterThanOrEqual(
+        _boolValue(null), _doubleValue(1.0), _intValue(null));
+  }
+
+  void test_greaterThanOrEqual_knownInt_knownInt_false() {
+    _assertGreaterThanOrEqual(_boolValue(false), _intValue(1), _intValue(2));
+  }
+
+  void test_greaterThanOrEqual_knownInt_knownInt_true() {
+    _assertGreaterThanOrEqual(_boolValue(true), _intValue(2), _intValue(2));
+  }
+
+  void test_greaterThanOrEqual_knownInt_knownString() {
+    _assertGreaterThanOrEqual(null, _intValue(1), _stringValue("2"));
+  }
+
+  void test_greaterThanOrEqual_knownInt_unknownDouble() {
+    _assertGreaterThanOrEqual(
+        _boolValue(null), _intValue(1), _doubleValue(null));
+  }
+
+  void test_greaterThanOrEqual_knownInt_unknownInt() {
+    _assertGreaterThanOrEqual(_boolValue(null), _intValue(1), _intValue(null));
+  }
+
+  void test_greaterThanOrEqual_knownString_knownInt() {
+    _assertGreaterThanOrEqual(null, _stringValue("1"), _intValue(2));
+  }
+
+  void test_greaterThanOrEqual_unknownDouble_knownDouble() {
+    _assertGreaterThanOrEqual(
+        _boolValue(null), _doubleValue(null), _doubleValue(2.0));
+  }
+
+  void test_greaterThanOrEqual_unknownDouble_knownInt() {
+    _assertGreaterThanOrEqual(
+        _boolValue(null), _doubleValue(null), _intValue(2));
+  }
+
+  void test_greaterThanOrEqual_unknownInt_knownDouble() {
+    _assertGreaterThanOrEqual(
+        _boolValue(null), _intValue(null), _doubleValue(2.0));
+  }
+
+  void test_greaterThanOrEqual_unknownInt_knownInt() {
+    _assertGreaterThanOrEqual(_boolValue(null), _intValue(null), _intValue(2));
+  }
+
+  void test_hasKnownValue_bool_false() {
+    expect(_boolValue(false).hasKnownValue, isTrue);
+  }
+
+  void test_hasKnownValue_bool_true() {
+    expect(_boolValue(true).hasKnownValue, isTrue);
+  }
+
+  void test_hasKnownValue_bool_unknown() {
+    expect(_boolValue(null).hasKnownValue, isFalse);
+  }
+
+  void test_hasKnownValue_double_known() {
+    expect(_doubleValue(2.3).hasKnownValue, isTrue);
+  }
+
+  void test_hasKnownValue_double_unknown() {
+    expect(_doubleValue(null).hasKnownValue, isFalse);
+  }
+
+  void test_hasKnownValue_dynamic() {
+    expect(_dynamicValue().hasKnownValue, isTrue);
+  }
+
+  void test_hasKnownValue_int_known() {
+    expect(_intValue(23).hasKnownValue, isTrue);
+  }
+
+  void test_hasKnownValue_int_unknown() {
+    expect(_intValue(null).hasKnownValue, isFalse);
+  }
+
+  void test_hasKnownValue_list_empty() {
+    expect(_listValue().hasKnownValue, isTrue);
+  }
+
+  void test_hasKnownValue_list_invalidElement() {
+    expect(_listValue([_dynamicValue]).hasKnownValue, isTrue);
+  }
+
+  void test_hasKnownValue_list_valid() {
+    expect(_listValue([_intValue(23)]).hasKnownValue, isTrue);
+  }
+
+  void test_hasKnownValue_map_empty() {
+    expect(_mapValue().hasKnownValue, isTrue);
+  }
+
+  void test_hasKnownValue_map_invalidKey() {
+    expect(_mapValue([_dynamicValue(), _stringValue("value")]).hasKnownValue,
+        isTrue);
+  }
+
+  void test_hasKnownValue_map_invalidValue() {
+    expect(_mapValue([_stringValue("key"), _dynamicValue()]).hasKnownValue,
+        isTrue);
+  }
+
+  void test_hasKnownValue_map_valid() {
+    expect(
+        _mapValue([_stringValue("key"), _stringValue("value")]).hasKnownValue,
+        isTrue);
+  }
+
+  void test_hasKnownValue_null() {
+    expect(_nullValue().hasKnownValue, isTrue);
+  }
+
+  void test_hasKnownValue_num() {
+    expect(_numValue().hasKnownValue, isFalse);
+  }
+
+  void test_hasKnownValue_string_known() {
+    expect(_stringValue("twenty-three").hasKnownValue, isTrue);
+  }
+
+  void test_hasKnownValue_string_unknown() {
+    expect(_stringValue(null).hasKnownValue, isFalse);
+  }
+
+  void test_identical_bool_false() {
+    _assertIdentical(_boolValue(false), _boolValue(false), _boolValue(true));
+  }
+
+  void test_identical_bool_true() {
+    _assertIdentical(_boolValue(true), _boolValue(true), _boolValue(true));
+  }
+
+  void test_identical_bool_unknown() {
+    _assertIdentical(_boolValue(null), _boolValue(null), _boolValue(false));
+  }
+
+  void test_identical_double_false() {
+    _assertIdentical(_boolValue(false), _doubleValue(2.0), _doubleValue(4.0));
+  }
+
+  void test_identical_double_true() {
+    _assertIdentical(_boolValue(true), _doubleValue(2.0), _doubleValue(2.0));
+  }
+
+  void test_identical_double_unknown() {
+    _assertIdentical(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
+  }
+
+  void test_identical_int_false() {
+    _assertIdentical(_boolValue(false), _intValue(-5), _intValue(5));
+  }
+
+  void test_identical_int_true() {
+    _assertIdentical(_boolValue(true), _intValue(5), _intValue(5));
+  }
+
+  void test_identical_int_unknown() {
+    _assertIdentical(_boolValue(null), _intValue(null), _intValue(3));
+  }
+
+  void test_identical_list_empty() {
+    _assertIdentical(_boolValue(true), _listValue(), _listValue());
+  }
+
+  void test_identical_list_false() {
+    _assertIdentical(
+        _boolValue(false), _listValue(), _listValue([_intValue(3)]));
+  }
+
+  void test_identical_map_empty() {
+    _assertIdentical(_boolValue(true), _mapValue(), _mapValue());
+  }
+
+  void test_identical_map_false() {
+    _assertIdentical(_boolValue(false), _mapValue(),
+        _mapValue([_intValue(1), _intValue(2)]));
+  }
+
+  void test_identical_null() {
+    _assertIdentical(_boolValue(true), _nullValue(), _nullValue());
+  }
+
+  void test_identical_string_false() {
+    _assertIdentical(
+        _boolValue(false), _stringValue("abc"), _stringValue("def"));
+  }
+
+  void test_identical_string_true() {
+    _assertIdentical(
+        _boolValue(true), _stringValue("abc"), _stringValue("abc"));
+  }
+
+  void test_identical_string_unknown() {
+    _assertIdentical(_boolValue(null), _stringValue(null), _stringValue("def"));
+  }
+
+  void test_integerDivide_knownDouble_knownDouble() {
+    _assertIntegerDivide(_intValue(3), _doubleValue(6.0), _doubleValue(2.0));
+  }
+
+  void test_integerDivide_knownDouble_knownInt() {
+    _assertIntegerDivide(_intValue(3), _doubleValue(6.0), _intValue(2));
+  }
+
+  void test_integerDivide_knownDouble_unknownDouble() {
+    _assertIntegerDivide(
+        _intValue(null), _doubleValue(6.0), _doubleValue(null));
+  }
+
+  void test_integerDivide_knownDouble_unknownInt() {
+    _assertIntegerDivide(_intValue(null), _doubleValue(6.0), _intValue(null));
+  }
+
+  void test_integerDivide_knownInt_knownInt() {
+    _assertIntegerDivide(_intValue(3), _intValue(6), _intValue(2));
+  }
+
+  void test_integerDivide_knownInt_knownString() {
+    _assertIntegerDivide(null, _intValue(6), _stringValue("2"));
+  }
+
+  void test_integerDivide_knownInt_unknownDouble() {
+    _assertIntegerDivide(_intValue(null), _intValue(6), _doubleValue(null));
+  }
+
+  void test_integerDivide_knownInt_unknownInt() {
+    _assertIntegerDivide(_intValue(null), _intValue(6), _intValue(null));
+  }
+
+  void test_integerDivide_knownString_knownInt() {
+    _assertIntegerDivide(null, _stringValue("6"), _intValue(2));
+  }
+
+  void test_integerDivide_unknownDouble_knownDouble() {
+    _assertIntegerDivide(
+        _intValue(null), _doubleValue(null), _doubleValue(2.0));
+  }
+
+  void test_integerDivide_unknownDouble_knownInt() {
+    _assertIntegerDivide(_intValue(null), _doubleValue(null), _intValue(2));
+  }
+
+  void test_integerDivide_unknownInt_knownDouble() {
+    _assertIntegerDivide(_intValue(null), _intValue(null), _doubleValue(2.0));
+  }
+
+  void test_integerDivide_unknownInt_knownInt() {
+    _assertIntegerDivide(_intValue(null), _intValue(null), _intValue(2));
+  }
+
+  void test_isBoolNumStringOrNull_bool_false() {
+    expect(_boolValue(false).isBoolNumStringOrNull, isTrue);
+  }
+
+  void test_isBoolNumStringOrNull_bool_true() {
+    expect(_boolValue(true).isBoolNumStringOrNull, isTrue);
+  }
+
+  void test_isBoolNumStringOrNull_bool_unknown() {
+    expect(_boolValue(null).isBoolNumStringOrNull, isTrue);
+  }
+
+  void test_isBoolNumStringOrNull_double_known() {
+    expect(_doubleValue(2.3).isBoolNumStringOrNull, isTrue);
+  }
+
+  void test_isBoolNumStringOrNull_double_unknown() {
+    expect(_doubleValue(null).isBoolNumStringOrNull, isTrue);
+  }
+
+  void test_isBoolNumStringOrNull_dynamic() {
+    expect(_dynamicValue().isBoolNumStringOrNull, isTrue);
+  }
+
+  void test_isBoolNumStringOrNull_int_known() {
+    expect(_intValue(23).isBoolNumStringOrNull, isTrue);
+  }
+
+  void test_isBoolNumStringOrNull_int_unknown() {
+    expect(_intValue(null).isBoolNumStringOrNull, isTrue);
+  }
+
+  void test_isBoolNumStringOrNull_list() {
+    expect(_listValue().isBoolNumStringOrNull, isFalse);
+  }
+
+  void test_isBoolNumStringOrNull_null() {
+    expect(_nullValue().isBoolNumStringOrNull, isTrue);
+  }
+
+  void test_isBoolNumStringOrNull_num() {
+    expect(_numValue().isBoolNumStringOrNull, isTrue);
+  }
+
+  void test_isBoolNumStringOrNull_string_known() {
+    expect(_stringValue("twenty-three").isBoolNumStringOrNull, isTrue);
+  }
+
+  void test_isBoolNumStringOrNull_string_unknown() {
+    expect(_stringValue(null).isBoolNumStringOrNull, isTrue);
+  }
+
+  void test_lessThan_knownDouble_knownDouble_false() {
+    _assertLessThan(_boolValue(false), _doubleValue(2.0), _doubleValue(1.0));
+  }
+
+  void test_lessThan_knownDouble_knownDouble_true() {
+    _assertLessThan(_boolValue(true), _doubleValue(1.0), _doubleValue(2.0));
+  }
+
+  void test_lessThan_knownDouble_knownInt_false() {
+    _assertLessThan(_boolValue(false), _doubleValue(2.0), _intValue(1));
+  }
+
+  void test_lessThan_knownDouble_knownInt_true() {
+    _assertLessThan(_boolValue(true), _doubleValue(1.0), _intValue(2));
+  }
+
+  void test_lessThan_knownDouble_unknownDouble() {
+    _assertLessThan(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
+  }
+
+  void test_lessThan_knownDouble_unknownInt() {
+    _assertLessThan(_boolValue(null), _doubleValue(1.0), _intValue(null));
+  }
+
+  void test_lessThan_knownInt_knownInt_false() {
+    _assertLessThan(_boolValue(false), _intValue(2), _intValue(1));
+  }
+
+  void test_lessThan_knownInt_knownInt_true() {
+    _assertLessThan(_boolValue(true), _intValue(1), _intValue(2));
+  }
+
+  void test_lessThan_knownInt_knownString() {
+    _assertLessThan(null, _intValue(1), _stringValue("2"));
+  }
+
+  void test_lessThan_knownInt_unknownDouble() {
+    _assertLessThan(_boolValue(null), _intValue(1), _doubleValue(null));
+  }
+
+  void test_lessThan_knownInt_unknownInt() {
+    _assertLessThan(_boolValue(null), _intValue(1), _intValue(null));
+  }
+
+  void test_lessThan_knownString_knownInt() {
+    _assertLessThan(null, _stringValue("1"), _intValue(2));
+  }
+
+  void test_lessThan_unknownDouble_knownDouble() {
+    _assertLessThan(_boolValue(null), _doubleValue(null), _doubleValue(2.0));
+  }
+
+  void test_lessThan_unknownDouble_knownInt() {
+    _assertLessThan(_boolValue(null), _doubleValue(null), _intValue(2));
+  }
+
+  void test_lessThan_unknownInt_knownDouble() {
+    _assertLessThan(_boolValue(null), _intValue(null), _doubleValue(2.0));
+  }
+
+  void test_lessThan_unknownInt_knownInt() {
+    _assertLessThan(_boolValue(null), _intValue(null), _intValue(2));
+  }
+
+  void test_lessThanOrEqual_knownDouble_knownDouble_false() {
+    _assertLessThanOrEqual(
+        _boolValue(false), _doubleValue(2.0), _doubleValue(1.0));
+  }
+
+  void test_lessThanOrEqual_knownDouble_knownDouble_true() {
+    _assertLessThanOrEqual(
+        _boolValue(true), _doubleValue(1.0), _doubleValue(2.0));
+  }
+
+  void test_lessThanOrEqual_knownDouble_knownInt_false() {
+    _assertLessThanOrEqual(_boolValue(false), _doubleValue(2.0), _intValue(1));
+  }
+
+  void test_lessThanOrEqual_knownDouble_knownInt_true() {
+    _assertLessThanOrEqual(_boolValue(true), _doubleValue(1.0), _intValue(2));
+  }
+
+  void test_lessThanOrEqual_knownDouble_unknownDouble() {
+    _assertLessThanOrEqual(
+        _boolValue(null), _doubleValue(1.0), _doubleValue(null));
+  }
+
+  void test_lessThanOrEqual_knownDouble_unknownInt() {
+    _assertLessThanOrEqual(
+        _boolValue(null), _doubleValue(1.0), _intValue(null));
+  }
+
+  void test_lessThanOrEqual_knownInt_knownInt_false() {
+    _assertLessThanOrEqual(_boolValue(false), _intValue(2), _intValue(1));
+  }
+
+  void test_lessThanOrEqual_knownInt_knownInt_true() {
+    _assertLessThanOrEqual(_boolValue(true), _intValue(1), _intValue(2));
+  }
+
+  void test_lessThanOrEqual_knownInt_knownString() {
+    _assertLessThanOrEqual(null, _intValue(1), _stringValue("2"));
+  }
+
+  void test_lessThanOrEqual_knownInt_unknownDouble() {
+    _assertLessThanOrEqual(_boolValue(null), _intValue(1), _doubleValue(null));
+  }
+
+  void test_lessThanOrEqual_knownInt_unknownInt() {
+    _assertLessThanOrEqual(_boolValue(null), _intValue(1), _intValue(null));
+  }
+
+  void test_lessThanOrEqual_knownString_knownInt() {
+    _assertLessThanOrEqual(null, _stringValue("1"), _intValue(2));
+  }
+
+  void test_lessThanOrEqual_unknownDouble_knownDouble() {
+    _assertLessThanOrEqual(
+        _boolValue(null), _doubleValue(null), _doubleValue(2.0));
+  }
+
+  void test_lessThanOrEqual_unknownDouble_knownInt() {
+    _assertLessThanOrEqual(_boolValue(null), _doubleValue(null), _intValue(2));
+  }
+
+  void test_lessThanOrEqual_unknownInt_knownDouble() {
+    _assertLessThanOrEqual(
+        _boolValue(null), _intValue(null), _doubleValue(2.0));
+  }
+
+  void test_lessThanOrEqual_unknownInt_knownInt() {
+    _assertLessThanOrEqual(_boolValue(null), _intValue(null), _intValue(2));
+  }
+
+  void test_logicalAnd_false_false() {
+    _assertLogicalAnd(_boolValue(false), _boolValue(false), _boolValue(false));
+  }
+
+  void test_logicalAnd_false_null() {
+    try {
+      _assertLogicalAnd(_boolValue(false), _boolValue(false), _nullValue());
+      fail("Expected EvaluationException");
+    } on EvaluationException {}
+  }
+
+  void test_logicalAnd_false_string() {
+    try {
+      _assertLogicalAnd(
+          _boolValue(false), _boolValue(false), _stringValue("false"));
+      fail("Expected EvaluationException");
+    } on EvaluationException {}
+  }
+
+  void test_logicalAnd_false_true() {
+    _assertLogicalAnd(_boolValue(false), _boolValue(false), _boolValue(true));
+  }
+
+  void test_logicalAnd_null_false() {
+    try {
+      _assertLogicalAnd(_boolValue(false), _nullValue(), _boolValue(false));
+      fail("Expected EvaluationException");
+    } on EvaluationException {}
+  }
+
+  void test_logicalAnd_null_true() {
+    try {
+      _assertLogicalAnd(_boolValue(false), _nullValue(), _boolValue(true));
+      fail("Expected EvaluationException");
+    } on EvaluationException {}
+  }
+
+  void test_logicalAnd_string_false() {
+    try {
+      _assertLogicalAnd(
+          _boolValue(false), _stringValue("true"), _boolValue(false));
+      fail("Expected EvaluationException");
+    } on EvaluationException {}
+  }
+
+  void test_logicalAnd_string_true() {
+    try {
+      _assertLogicalAnd(
+          _boolValue(false), _stringValue("false"), _boolValue(true));
+      fail("Expected EvaluationException");
+    } on EvaluationException {}
+  }
+
+  void test_logicalAnd_true_false() {
+    _assertLogicalAnd(_boolValue(false), _boolValue(true), _boolValue(false));
+  }
+
+  void test_logicalAnd_true_null() {
+    _assertLogicalAnd(null, _boolValue(true), _nullValue());
+  }
+
+  void test_logicalAnd_true_string() {
+    try {
+      _assertLogicalAnd(
+          _boolValue(false), _boolValue(true), _stringValue("true"));
+      fail("Expected EvaluationException");
+    } on EvaluationException {}
+  }
+
+  void test_logicalAnd_true_true() {
+    _assertLogicalAnd(_boolValue(true), _boolValue(true), _boolValue(true));
+  }
+
+  void test_logicalNot_false() {
+    _assertLogicalNot(_boolValue(true), _boolValue(false));
+  }
+
+  void test_logicalNot_null() {
+    _assertLogicalNot(null, _nullValue());
+  }
+
+  void test_logicalNot_string() {
+    try {
+      _assertLogicalNot(_boolValue(true), _stringValue(null));
+      fail("Expected EvaluationException");
+    } on EvaluationException {}
+  }
+
+  void test_logicalNot_true() {
+    _assertLogicalNot(_boolValue(false), _boolValue(true));
+  }
+
+  void test_logicalNot_unknown() {
+    _assertLogicalNot(_boolValue(null), _boolValue(null));
+  }
+
+  void test_logicalOr_false_false() {
+    _assertLogicalOr(_boolValue(false), _boolValue(false), _boolValue(false));
+  }
+
+  void test_logicalOr_false_null() {
+    _assertLogicalOr(null, _boolValue(false), _nullValue());
+  }
+
+  void test_logicalOr_false_string() {
+    try {
+      _assertLogicalOr(
+          _boolValue(false), _boolValue(false), _stringValue("false"));
+      fail("Expected EvaluationException");
+    } on EvaluationException {}
+  }
+
+  void test_logicalOr_false_true() {
+    _assertLogicalOr(_boolValue(true), _boolValue(false), _boolValue(true));
+  }
+
+  void test_logicalOr_null_false() {
+    try {
+      _assertLogicalOr(_boolValue(false), _nullValue(), _boolValue(false));
+      fail("Expected EvaluationException");
+    } on EvaluationException {}
+  }
+
+  void test_logicalOr_null_true() {
+    try {
+      _assertLogicalOr(_boolValue(true), _nullValue(), _boolValue(true));
+      fail("Expected EvaluationException");
+    } on EvaluationException {}
+  }
+
+  void test_logicalOr_string_false() {
+    try {
+      _assertLogicalOr(
+          _boolValue(false), _stringValue("true"), _boolValue(false));
+      fail("Expected EvaluationException");
+    } on EvaluationException {}
+  }
+
+  void test_logicalOr_string_true() {
+    try {
+      _assertLogicalOr(
+          _boolValue(true), _stringValue("false"), _boolValue(true));
+      fail("Expected EvaluationException");
+    } on EvaluationException {}
+  }
+
+  void test_logicalOr_true_false() {
+    _assertLogicalOr(_boolValue(true), _boolValue(true), _boolValue(false));
+  }
+
+  void test_logicalOr_true_null() {
+    try {
+      _assertLogicalOr(_boolValue(true), _boolValue(true), _nullValue());
+      fail("Expected EvaluationException");
+    } on EvaluationException {}
+  }
+
+  void test_logicalOr_true_string() {
+    try {
+      _assertLogicalOr(
+          _boolValue(true), _boolValue(true), _stringValue("true"));
+      fail("Expected EvaluationException");
+    } on EvaluationException {}
+  }
+
+  void test_logicalOr_true_true() {
+    _assertLogicalOr(_boolValue(true), _boolValue(true), _boolValue(true));
+  }
+
+  void test_minus_knownDouble_knownDouble() {
+    _assertMinus(_doubleValue(1.0), _doubleValue(4.0), _doubleValue(3.0));
+  }
+
+  void test_minus_knownDouble_knownInt() {
+    _assertMinus(_doubleValue(1.0), _doubleValue(4.0), _intValue(3));
+  }
+
+  void test_minus_knownDouble_unknownDouble() {
+    _assertMinus(_doubleValue(null), _doubleValue(4.0), _doubleValue(null));
+  }
+
+  void test_minus_knownDouble_unknownInt() {
+    _assertMinus(_doubleValue(null), _doubleValue(4.0), _intValue(null));
+  }
+
+  void test_minus_knownInt_knownInt() {
+    _assertMinus(_intValue(1), _intValue(4), _intValue(3));
+  }
+
+  void test_minus_knownInt_knownString() {
+    _assertMinus(null, _intValue(4), _stringValue("3"));
+  }
+
+  void test_minus_knownInt_unknownDouble() {
+    _assertMinus(_doubleValue(null), _intValue(4), _doubleValue(null));
+  }
+
+  void test_minus_knownInt_unknownInt() {
+    _assertMinus(_intValue(null), _intValue(4), _intValue(null));
+  }
+
+  void test_minus_knownString_knownInt() {
+    _assertMinus(null, _stringValue("4"), _intValue(3));
+  }
+
+  void test_minus_unknownDouble_knownDouble() {
+    _assertMinus(_doubleValue(null), _doubleValue(null), _doubleValue(3.0));
+  }
+
+  void test_minus_unknownDouble_knownInt() {
+    _assertMinus(_doubleValue(null), _doubleValue(null), _intValue(3));
+  }
+
+  void test_minus_unknownInt_knownDouble() {
+    _assertMinus(_doubleValue(null), _intValue(null), _doubleValue(3.0));
+  }
+
+  void test_minus_unknownInt_knownInt() {
+    _assertMinus(_intValue(null), _intValue(null), _intValue(3));
+  }
+
+  void test_negated_double_known() {
+    _assertNegated(_doubleValue(2.0), _doubleValue(-2.0));
+  }
+
+  void test_negated_double_unknown() {
+    _assertNegated(_doubleValue(null), _doubleValue(null));
+  }
+
+  void test_negated_int_known() {
+    _assertNegated(_intValue(-3), _intValue(3));
+  }
+
+  void test_negated_int_unknown() {
+    _assertNegated(_intValue(null), _intValue(null));
+  }
+
+  void test_negated_string() {
+    _assertNegated(null, _stringValue(null));
+  }
+
+  void test_notEqual_bool_false() {
+    _assertNotEqual(_boolValue(false), _boolValue(true), _boolValue(true));
+  }
+
+  void test_notEqual_bool_true() {
+    _assertNotEqual(_boolValue(true), _boolValue(false), _boolValue(true));
+  }
+
+  void test_notEqual_bool_unknown() {
+    _assertNotEqual(_boolValue(null), _boolValue(null), _boolValue(false));
+  }
+
+  void test_notEqual_double_false() {
+    _assertNotEqual(_boolValue(false), _doubleValue(2.0), _doubleValue(2.0));
+  }
+
+  void test_notEqual_double_true() {
+    _assertNotEqual(_boolValue(true), _doubleValue(2.0), _doubleValue(4.0));
+  }
+
+  void test_notEqual_double_unknown() {
+    _assertNotEqual(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
+  }
+
+  void test_notEqual_int_false() {
+    _assertNotEqual(_boolValue(false), _intValue(5), _intValue(5));
+  }
+
+  void test_notEqual_int_true() {
+    _assertNotEqual(_boolValue(true), _intValue(-5), _intValue(5));
+  }
+
+  void test_notEqual_int_unknown() {
+    _assertNotEqual(_boolValue(null), _intValue(null), _intValue(3));
+  }
+
+  void test_notEqual_null() {
+    _assertNotEqual(_boolValue(false), _nullValue(), _nullValue());
+  }
+
+  void test_notEqual_string_false() {
+    _assertNotEqual(
+        _boolValue(false), _stringValue("abc"), _stringValue("abc"));
+  }
+
+  void test_notEqual_string_true() {
+    _assertNotEqual(_boolValue(true), _stringValue("abc"), _stringValue("def"));
+  }
+
+  void test_notEqual_string_unknown() {
+    _assertNotEqual(_boolValue(null), _stringValue(null), _stringValue("def"));
+  }
+
+  void test_performToString_bool_false() {
+    _assertPerformToString(_stringValue("false"), _boolValue(false));
+  }
+
+  void test_performToString_bool_true() {
+    _assertPerformToString(_stringValue("true"), _boolValue(true));
+  }
+
+  void test_performToString_bool_unknown() {
+    _assertPerformToString(_stringValue(null), _boolValue(null));
+  }
+
+  void test_performToString_double_known() {
+    _assertPerformToString(_stringValue("2.0"), _doubleValue(2.0));
+  }
+
+  void test_performToString_double_unknown() {
+    _assertPerformToString(_stringValue(null), _doubleValue(null));
+  }
+
+  void test_performToString_int_known() {
+    _assertPerformToString(_stringValue("5"), _intValue(5));
+  }
+
+  void test_performToString_int_unknown() {
+    _assertPerformToString(_stringValue(null), _intValue(null));
+  }
+
+  void test_performToString_null() {
+    _assertPerformToString(_stringValue("null"), _nullValue());
+  }
+
+  void test_performToString_string_known() {
+    _assertPerformToString(_stringValue("abc"), _stringValue("abc"));
+  }
+
+  void test_performToString_string_unknown() {
+    _assertPerformToString(_stringValue(null), _stringValue(null));
+  }
+
+  void test_remainder_knownDouble_knownDouble() {
+    _assertRemainder(_doubleValue(1.0), _doubleValue(7.0), _doubleValue(2.0));
+  }
+
+  void test_remainder_knownDouble_knownInt() {
+    _assertRemainder(_doubleValue(1.0), _doubleValue(7.0), _intValue(2));
+  }
+
+  void test_remainder_knownDouble_unknownDouble() {
+    _assertRemainder(_doubleValue(null), _doubleValue(7.0), _doubleValue(null));
+  }
+
+  void test_remainder_knownDouble_unknownInt() {
+    _assertRemainder(_doubleValue(null), _doubleValue(6.0), _intValue(null));
+  }
+
+  void test_remainder_knownInt_knownInt() {
+    _assertRemainder(_intValue(1), _intValue(7), _intValue(2));
+  }
+
+  void test_remainder_knownInt_knownString() {
+    _assertRemainder(null, _intValue(7), _stringValue("2"));
+  }
+
+  void test_remainder_knownInt_unknownDouble() {
+    _assertRemainder(_doubleValue(null), _intValue(7), _doubleValue(null));
+  }
+
+  void test_remainder_knownInt_unknownInt() {
+    _assertRemainder(_intValue(null), _intValue(7), _intValue(null));
+  }
+
+  void test_remainder_knownString_knownInt() {
+    _assertRemainder(null, _stringValue("7"), _intValue(2));
+  }
+
+  void test_remainder_unknownDouble_knownDouble() {
+    _assertRemainder(_doubleValue(null), _doubleValue(null), _doubleValue(2.0));
+  }
+
+  void test_remainder_unknownDouble_knownInt() {
+    _assertRemainder(_doubleValue(null), _doubleValue(null), _intValue(2));
+  }
+
+  void test_remainder_unknownInt_knownDouble() {
+    _assertRemainder(_doubleValue(null), _intValue(null), _doubleValue(2.0));
+  }
+
+  void test_remainder_unknownInt_knownInt() {
+    _assertRemainder(_intValue(null), _intValue(null), _intValue(2));
+  }
+
+  void test_shiftLeft_knownInt_knownInt() {
+    _assertShiftLeft(_intValue(48), _intValue(6), _intValue(3));
+  }
+
+  void test_shiftLeft_knownInt_knownString() {
+    _assertShiftLeft(null, _intValue(6), _stringValue(null));
+  }
+
+  void test_shiftLeft_knownInt_tooLarge() {
+    _assertShiftLeft(
+        _intValue(null),
+        _intValue(6),
+        new DartObjectImpl(
+            _typeProvider.intType, new IntState(LONG_MAX_VALUE)));
+  }
+
+  void test_shiftLeft_knownInt_unknownInt() {
+    _assertShiftLeft(_intValue(null), _intValue(6), _intValue(null));
+  }
+
+  void test_shiftLeft_knownString_knownInt() {
+    _assertShiftLeft(null, _stringValue(null), _intValue(3));
+  }
+
+  void test_shiftLeft_unknownInt_knownInt() {
+    _assertShiftLeft(_intValue(null), _intValue(null), _intValue(3));
+  }
+
+  void test_shiftLeft_unknownInt_unknownInt() {
+    _assertShiftLeft(_intValue(null), _intValue(null), _intValue(null));
+  }
+
+  void test_shiftRight_knownInt_knownInt() {
+    _assertShiftRight(_intValue(6), _intValue(48), _intValue(3));
+  }
+
+  void test_shiftRight_knownInt_knownString() {
+    _assertShiftRight(null, _intValue(48), _stringValue(null));
+  }
+
+  void test_shiftRight_knownInt_tooLarge() {
+    _assertShiftRight(
+        _intValue(null),
+        _intValue(48),
+        new DartObjectImpl(
+            _typeProvider.intType, new IntState(LONG_MAX_VALUE)));
+  }
+
+  void test_shiftRight_knownInt_unknownInt() {
+    _assertShiftRight(_intValue(null), _intValue(48), _intValue(null));
+  }
+
+  void test_shiftRight_knownString_knownInt() {
+    _assertShiftRight(null, _stringValue(null), _intValue(3));
+  }
+
+  void test_shiftRight_unknownInt_knownInt() {
+    _assertShiftRight(_intValue(null), _intValue(null), _intValue(3));
+  }
+
+  void test_shiftRight_unknownInt_unknownInt() {
+    _assertShiftRight(_intValue(null), _intValue(null), _intValue(null));
+  }
+
+  void test_stringLength_int() {
+    try {
+      _assertStringLength(_intValue(null), _intValue(0));
+      fail("Expected EvaluationException");
+    } on EvaluationException {}
+  }
+
+  void test_stringLength_knownString() {
+    _assertStringLength(_intValue(3), _stringValue("abc"));
+  }
+
+  void test_stringLength_unknownString() {
+    _assertStringLength(_intValue(null), _stringValue(null));
+  }
+
+  void test_times_knownDouble_knownDouble() {
+    _assertTimes(_doubleValue(6.0), _doubleValue(2.0), _doubleValue(3.0));
+  }
+
+  void test_times_knownDouble_knownInt() {
+    _assertTimes(_doubleValue(6.0), _doubleValue(2.0), _intValue(3));
+  }
+
+  void test_times_knownDouble_unknownDouble() {
+    _assertTimes(_doubleValue(null), _doubleValue(2.0), _doubleValue(null));
+  }
+
+  void test_times_knownDouble_unknownInt() {
+    _assertTimes(_doubleValue(null), _doubleValue(2.0), _intValue(null));
+  }
+
+  void test_times_knownInt_knownInt() {
+    _assertTimes(_intValue(6), _intValue(2), _intValue(3));
+  }
+
+  void test_times_knownInt_knownString() {
+    _assertTimes(null, _intValue(2), _stringValue("3"));
+  }
+
+  void test_times_knownInt_unknownDouble() {
+    _assertTimes(_doubleValue(null), _intValue(2), _doubleValue(null));
+  }
+
+  void test_times_knownInt_unknownInt() {
+    _assertTimes(_intValue(null), _intValue(2), _intValue(null));
+  }
+
+  void test_times_knownString_knownInt() {
+    _assertTimes(null, _stringValue("2"), _intValue(3));
+  }
+
+  void test_times_unknownDouble_knownDouble() {
+    _assertTimes(_doubleValue(null), _doubleValue(null), _doubleValue(3.0));
+  }
+
+  void test_times_unknownDouble_knownInt() {
+    _assertTimes(_doubleValue(null), _doubleValue(null), _intValue(3));
+  }
+
+  void test_times_unknownInt_knownDouble() {
+    _assertTimes(_doubleValue(null), _intValue(null), _doubleValue(3.0));
+  }
+
+  void test_times_unknownInt_knownInt() {
+    _assertTimes(_intValue(null), _intValue(null), _intValue(3));
+  }
+
+  /**
+   * Assert that the result of adding the [left] and [right] operands is the
+   * [expected] value, or that the operation throws an exception if the expected
+   * value is `null`.
+   */
+  void _assertAdd(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.add(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.add(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of bit-anding the [left] and [right] operands is the
+   * [expected] value, or that the operation throws an exception if the expected
+   * value is `null`.
+   */
+  void _assertBitAnd(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.bitAnd(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.bitAnd(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the bit-not of the [operand] is the [expected] value, or that
+   * the operation throws an exception if the expected value is `null`.
+   */
+  void _assertBitNot(DartObjectImpl expected, DartObjectImpl operand) {
+    if (expected == null) {
+      try {
+        operand.bitNot(_typeProvider);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = operand.bitNot(_typeProvider);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of bit-oring the [left] and [right] operands is the
+   * [expected] value, or that the operation throws an exception if the expected
+   * value is `null`.
+   */
+  void _assertBitOr(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.bitOr(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.bitOr(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of bit-xoring the [left] and [right] operands is the
+   * [expected] value, or that the operation throws an exception if the expected
+   * value is `null`.
+   */
+  void _assertBitXor(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.bitXor(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.bitXor(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of concatenating the [left] and [right] operands is
+   * the [expected] value, or that the operation throws an exception if the
+   * expected value is `null`.
+   */
+  void _assertConcatenate(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.concatenate(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.concatenate(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of dividing the [left] and [right] operands is the
+   * [expected] value, or that the operation throws an exception if the expected
+   * value is `null`.
+   */
+  void _assertDivide(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.divide(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.divide(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of comparing the [left] and [right] operands for
+   * equality is the [expected] value, or that the operation throws an exception
+   * if the expected value is `null`.
+   */
+  void _assertEqualEqual(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.equalEqual(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.equalEqual(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of comparing the [left] and [right] operands is the
+   * [expected] value, or that the operation throws an exception if the expected
+   * value is `null`.
+   */
+  void _assertGreaterThan(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.greaterThan(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.greaterThan(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of comparing the [left] and [right] operands is the
+   * [expected] value, or that the operation throws an exception if the expected
+   * value is `null`.
+   */
+  void _assertGreaterThanOrEqual(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.greaterThanOrEqual(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.greaterThanOrEqual(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of comparing the [left] and [right] operands using
+   * identical() is the expected value.
+   */
+  void _assertIdentical(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    DartObjectImpl result = left.isIdentical(_typeProvider, right);
+    expect(result, isNotNull);
+    expect(result, expected);
+  }
+
+  void _assertInstanceOfObjectArray(Object result) {
+    // TODO(scheglov) implement
+  }
+
+  /**
+   * Assert that the result of dividing the [left] and [right] operands as
+   * integers is the [expected] value, or that the operation throws an exception
+   * if the expected value is `null`.
+   */
+  void _assertIntegerDivide(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.integerDivide(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.integerDivide(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of comparing the [left] and [right] operands is the
+   * [expected] value, or that the operation throws an exception if the expected
+   * value is `null`.
+   */
+  void _assertLessThan(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.lessThan(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.lessThan(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of comparing the [left] and [right] operands is the
+   * [expected] value, or that the operation throws an exception if the expected
+   * value is `null`.
+   */
+  void _assertLessThanOrEqual(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.lessThanOrEqual(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.lessThanOrEqual(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of logical-anding the [left] and [right] operands is
+   * the [expected] value, or that the operation throws an exception if the
+   * expected value is `null`.
+   */
+  void _assertLogicalAnd(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.logicalAnd(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.logicalAnd(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the logical-not of the [operand] is the [expected] value, or
+   * that the operation throws an exception if the expected value is `null`.
+   */
+  void _assertLogicalNot(DartObjectImpl expected, DartObjectImpl operand) {
+    if (expected == null) {
+      try {
+        operand.logicalNot(_typeProvider);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = operand.logicalNot(_typeProvider);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of logical-oring the [left] and [right] operands is
+   * the [expected] value, or that the operation throws an exception if the
+   * expected value is `null`.
+   */
+  void _assertLogicalOr(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.logicalOr(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.logicalOr(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of subtracting the [left] and [right] operands is
+   * the [expected] value, or that the operation throws an exception if the
+   * expected value is `null`.
+   */
+  void _assertMinus(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.minus(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.minus(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the negation of the [operand] is the [expected] value, or that
+   * the operation throws an exception if the expected value is `null`.
+   */
+  void _assertNegated(DartObjectImpl expected, DartObjectImpl operand) {
+    if (expected == null) {
+      try {
+        operand.negated(_typeProvider);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = operand.negated(_typeProvider);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of comparing the [left] and [right] operands for
+   * inequality is the [expected] value, or that the operation throws an
+   * exception if the expected value is `null`.
+   */
+  void _assertNotEqual(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.notEqual(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.notEqual(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that converting the [operand] to a string is the [expected] value,
+   * or that the operation throws an exception if the expected value is `null`.
+   */
+  void _assertPerformToString(DartObjectImpl expected, DartObjectImpl operand) {
+    if (expected == null) {
+      try {
+        operand.performToString(_typeProvider);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = operand.performToString(_typeProvider);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of taking the remainder of the [left] and [right]
+   * operands is the [expected] value, or that the operation throws an exception
+   * if the expected value is `null`.
+   */
+  void _assertRemainder(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.remainder(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.remainder(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of multiplying the [left] and [right] operands is
+   * the [expected] value, or that the operation throws an exception if the
+   * expected value is `null`.
+   */
+  void _assertShiftLeft(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.shiftLeft(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.shiftLeft(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of multiplying the [left] and [right] operands is
+   * the [expected] value, or that the operation throws an exception if the
+   * expected value is `null`.
+   */
+  void _assertShiftRight(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.shiftRight(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.shiftRight(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the length of the [operand] is the [expected] value, or that
+   * the operation throws an exception if the expected value is `null`.
+   */
+  void _assertStringLength(DartObjectImpl expected, DartObjectImpl operand) {
+    if (expected == null) {
+      try {
+        operand.stringLength(_typeProvider);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = operand.stringLength(_typeProvider);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  /**
+   * Assert that the result of multiplying the [left] and [right] operands is
+   * the [expected] value, or that the operation throws an exception if the
+   * expected value is `null`.
+   */
+  void _assertTimes(
+      DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+    if (expected == null) {
+      try {
+        left.times(_typeProvider, right);
+        fail("Expected an EvaluationException");
+      } on EvaluationException {}
+    } else {
+      DartObjectImpl result = left.times(_typeProvider, right);
+      expect(result, isNotNull);
+      expect(result, expected);
+    }
+  }
+
+  DartObjectImpl _boolValue(bool value) {
+    if (value == null) {
+      return new DartObjectImpl(
+          _typeProvider.boolType, BoolState.UNKNOWN_VALUE);
+    } else if (identical(value, false)) {
+      return new DartObjectImpl(_typeProvider.boolType, BoolState.FALSE_STATE);
+    } else if (identical(value, true)) {
+      return new DartObjectImpl(_typeProvider.boolType, BoolState.TRUE_STATE);
+    }
+    fail("Invalid boolean value used in test");
+    return null;
+  }
+
+  DartObjectImpl _doubleValue(double value) {
+    if (value == null) {
+      return new DartObjectImpl(
+          _typeProvider.doubleType, DoubleState.UNKNOWN_VALUE);
+    } else {
+      return new DartObjectImpl(
+          _typeProvider.doubleType, new DoubleState(value));
+    }
+  }
+
+  DartObjectImpl _dynamicValue() {
+    return new DartObjectImpl(
+        _typeProvider.nullType, DynamicState.DYNAMIC_STATE);
+  }
+
+  DartObjectImpl _intValue(int value) {
+    if (value == null) {
+      return new DartObjectImpl(_typeProvider.intType, IntState.UNKNOWN_VALUE);
+    } else {
+      return new DartObjectImpl(_typeProvider.intType, new IntState(value));
+    }
+  }
+
+  DartObjectImpl _listValue(
+      [List<DartObjectImpl> elements = DartObjectImpl.EMPTY_LIST]) {
+    return new DartObjectImpl(_typeProvider.listType, new ListState(elements));
+  }
+
+  DartObjectImpl _mapValue(
+      [List<DartObjectImpl> keyElementPairs = DartObjectImpl.EMPTY_LIST]) {
+    Map<DartObjectImpl, DartObjectImpl> map =
+        new Map<DartObjectImpl, DartObjectImpl>();
+    int count = keyElementPairs.length;
+    for (int i = 0; i < count;) {
+      map[keyElementPairs[i++]] = keyElementPairs[i++];
+    }
+    return new DartObjectImpl(_typeProvider.mapType, new MapState(map));
+  }
+
+  DartObjectImpl _nullValue() {
+    return new DartObjectImpl(_typeProvider.nullType, NullState.NULL_STATE);
+  }
+
+  DartObjectImpl _numValue() {
+    return new DartObjectImpl(_typeProvider.nullType, NumState.UNKNOWN_VALUE);
+  }
+
+  DartObjectImpl _stringValue(String value) {
+    if (value == null) {
+      return new DartObjectImpl(
+          _typeProvider.stringType, StringState.UNKNOWN_VALUE);
+    } else {
+      return new DartObjectImpl(
+          _typeProvider.stringType, new StringState(value));
+    }
+  }
+
+  DartObjectImpl _symbolValue(String value) {
+    return new DartObjectImpl(_typeProvider.symbolType, new SymbolState(value));
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index c097cff..17f71cc 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -8,6 +8,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/element/handle.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisContext, AnalysisOptionsImpl;
@@ -119,6 +120,24 @@
     }
   }
 
+  void test_constructors_mixinApplicationWithHandle() {
+    AnalysisContext context = createAnalysisContext();
+    context.sourceFactory = new SourceFactory([]);
+
+    ElementLocation location = new ElementLocationImpl.con2('');
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    classA.mixinApplication = true;
+    TestElementResynthesizer resynthesizer =
+        new TestElementResynthesizer(context, {location: classA});
+    ClassElementHandle classAHandle =
+        new ClassElementHandle(resynthesizer, location);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", new InterfaceTypeImpl(classAHandle));
+    classB.mixinApplication = true;
+
+    expect(classB.constructors, hasLength(1));
+  }
+
   void test_getAllSupertypes_interface() {
     ClassElement classA = ElementFactory.classElement2("A");
     ClassElement classB = ElementFactory.classElement("B", classA.type);
@@ -3703,6 +3722,24 @@
         library.visibleLibraries, unorderedEquals(<LibraryElement>[library]));
   }
 
+  void test_invalidateLibraryCycles_withHandle() {
+    AnalysisContext context = createAnalysisContext();
+    context.sourceFactory = new SourceFactory([]);
+    LibraryElementImpl library = ElementFactory.library(context, "foo");
+    LibraryElementImpl importedLibrary = ElementFactory.library(context, "bar");
+    ElementLocation location = new ElementLocationImpl.con2('');
+    TestElementResynthesizer resynthesizer =
+        new TestElementResynthesizer(context, {location: importedLibrary});
+    LibraryElement importedLibraryHandle =
+        new LibraryElementHandle(resynthesizer, location);
+    ImportElementImpl import =
+        ElementFactory.importFor(importedLibraryHandle, null);
+    library.imports = <ImportElement>[import];
+    library.libraryCycle; // Force computation of the cycle.
+
+    library.invalidateLibraryCycles();
+  }
+
   void test_isUpToDate() {
     AnalysisContext context = createAnalysisContext();
     context.sourceFactory = new SourceFactory([]);
@@ -3938,6 +3975,18 @@
   }
 }
 
+class TestElementResynthesizer extends ElementResynthesizer {
+  Map<ElementLocation, Element> locationMap;
+
+  TestElementResynthesizer(AnalysisContext context, this.locationMap)
+      : super(context);
+
+  @override
+  Element getElement(ElementLocation location) {
+    return locationMap[location];
+  }
+}
+
 @reflectiveTest
 class TypeParameterTypeImplTest extends EngineTestCase {
   void test_creation() {
diff --git a/pkg/analyzer/test/src/dart/test_all.dart b/pkg/analyzer/test/src/dart/test_all.dart
index ec4f182..15a0849 100644
--- a/pkg/analyzer/test/src/dart/test_all.dart
+++ b/pkg/analyzer/test/src/dart/test_all.dart
@@ -7,12 +7,16 @@
 import 'package:unittest/unittest.dart';
 
 import '../../utils.dart';
+import 'ast/test_all.dart' as ast;
+import 'constant/test_all.dart' as constant;
 import 'element/test_all.dart' as element;
 
 /// Utility for manually running all tests.
 main() {
   initializeTestEnvironment();
   group('dart tests', () {
+    ast.main();
+    constant.main();
     element.main();
   });
 }
diff --git a/pkg/analyzer/test/src/summary/incremental_cache_test.dart b/pkg/analyzer/test/src/summary/incremental_cache_test.dart
new file mode 100644
index 0000000..bf7620a
--- /dev/null
+++ b/pkg/analyzer/test/src/summary/incremental_cache_test.dart
@@ -0,0 +1,187 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/incremental_cache.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../reflective_tests.dart';
+import '../abstract_single_unit.dart';
+
+main() {
+  groupSep = ' | ';
+  runReflectiveTests(IncrementalCacheTest);
+}
+
+/**
+ * TODO(scheglov) write more tests for invalidation.
+ */
+@reflectiveTest
+class IncrementalCacheTest extends AbstractSingleUnitTest {
+  _TestCacheStorage storage = new _TestCacheStorage();
+  IncrementalCache cache;
+
+  Source putLibrary(String path, String code) {
+    Source source = addSource(path, code);
+    LibraryElement libraryElement = context.computeLibraryElement(source);
+    cache.putLibrary(libraryElement);
+    return source;
+  }
+
+  void putTestLibrary(String code) {
+    resolveTestUnit(code);
+    cache.putLibrary(testLibraryElement);
+  }
+
+  @override
+  void setUp() {
+    super.setUp();
+    cache = new IncrementalCache(storage, context, <int>[]);
+  }
+
+  void test_getLibraryClosureBundles_emptyCache() {
+    resolveTestUnit('main() {}');
+    // the cache is empty, no bundles
+    List<LibraryBundleWithId> bundles =
+        cache.getLibraryClosureBundles(testSource);
+    expect(bundles, isNull);
+  }
+
+  void test_getLibraryClosureBundles_exportLib() {
+    Source aSource = putLibrary('/a.dart', '');
+    putTestLibrary(r'''
+import 'a.dart';
+main() {}
+''');
+    List<LibraryBundleWithId> bundles =
+        cache.getLibraryClosureBundles(testSource);
+    expect(bundles, isNotNull);
+    expect(_getBundleSources(bundles), [testSource, aSource].toSet());
+    // remove the 'a.dart' bundle, 'test.dart' loading fails
+    cache.clearInternalCaches();
+    storage.map.remove(_findBundleForSource(bundles, aSource).id);
+    expect(cache.getLibraryClosureBundles(testSource), isNull);
+  }
+
+  void test_getLibraryClosureBundles_importLib() {
+    Source aSource = putLibrary('/a.dart', '');
+    putTestLibrary(r'''
+import 'a.dart';
+main() {}
+''');
+    List<LibraryBundleWithId> bundles =
+        cache.getLibraryClosureBundles(testSource);
+    expect(bundles, isNotNull);
+    expect(_getBundleSources(bundles), [testSource, aSource].toSet());
+    // remove the 'a.dart' bundle, 'test.dart' loading fails
+    cache.clearInternalCaches();
+    storage.map.remove(_findBundleForSource(bundles, aSource).id);
+    expect(cache.getLibraryClosureBundles(testSource), isNull);
+  }
+
+  void test_getLibraryClosureBundles_importLib2() {
+    Source aSource = putLibrary('/a.dart', '');
+    Source bSource = putLibrary('/b.dart', "import 'a.dart';");
+    putTestLibrary(r'''
+import 'b.dart';
+main() {}
+''');
+    List<LibraryBundleWithId> bundles =
+        cache.getLibraryClosureBundles(testSource);
+    expect(bundles, isNotNull);
+    expect(_getBundleSources(bundles), [testSource, aSource, bSource].toSet());
+    // remove the 'a.dart' bundle, 'test.dart' loading fails
+    cache.clearInternalCaches();
+    storage.map.remove(_findBundleForSource(bundles, aSource).id);
+    expect(cache.getLibraryClosureBundles(testSource), isNull);
+  }
+
+  void test_getLibraryClosureBundles_importSdk() {
+    putTestLibrary(r'''
+import 'dart:async';
+main() {}
+''');
+    List<LibraryBundleWithId> bundles =
+        cache.getLibraryClosureBundles(testSource);
+    expect(bundles, isNotNull);
+    expect(_getBundleSources(bundles), [testSource].toSet());
+  }
+
+  void test_getLibraryClosureBundles_onlyLibrary() {
+    putTestLibrary(r'''
+main() {}
+''');
+    // the cache is empty, no bundles
+    List<LibraryBundleWithId> bundles =
+        cache.getLibraryClosureBundles(testSource);
+    expect(bundles, isNotNull);
+  }
+
+  void test_getSourceKind_library() {
+    putTestLibrary(r'''
+main() {}
+''');
+    expect(cache.getSourceKind(testSource), SourceKind.LIBRARY);
+  }
+
+  void test_getSourceKind_library_usedAsPart() {
+    verifyNoTestUnitErrors = false;
+    Source fooSource = addSource(
+        '/foo.dart',
+        r'''
+import 'dart:math';
+''');
+    putTestLibrary(r'''
+part 'foo.dart';
+main() {}
+''');
+    expect(cache.getSourceKind(testSource), SourceKind.LIBRARY);
+    // not a part, but also not enough information to write it as a library
+    expect(cache.getSourceKind(fooSource), isNull);
+  }
+
+  void test_getSourceKind_notCached() {
+    resolveTestUnit(r'''
+main() {}
+''');
+    expect(cache.getSourceKind(testSource), isNull);
+  }
+
+  void test_getSourceKind_part() {
+    Source partSource = addSource('/foo.dart', 'part of lib;');
+    putTestLibrary(r'''
+library lib;
+part 'foo.dart';
+''');
+    expect(cache.getSourceKind(testSource), SourceKind.LIBRARY);
+    expect(cache.getSourceKind(partSource), SourceKind.PART);
+  }
+
+  LibraryBundleWithId _findBundleForSource(
+      List<LibraryBundleWithId> bundles, Source source) {
+    return bundles.singleWhere((b) => b.source == source);
+  }
+
+  Set<Source> _getBundleSources(List<LibraryBundleWithId> bundles) {
+    return bundles.map((b) => b.source).toSet();
+  }
+}
+
+/**
+ * A [Map] based [CacheStorage].
+ */
+class _TestCacheStorage implements CacheStorage {
+  final Map<String, List<int>> map = <String, List<int>>{};
+
+  @override
+  List<int> get(String key) {
+    return map[key];
+  }
+
+  @override
+  void put(String key, List<int> bytes) {
+    map[key] = bytes;
+  }
+}
diff --git a/pkg/analyzer/test/src/summary/index_unit_test.dart b/pkg/analyzer/test/src/summary/index_unit_test.dart
index a8a3f4f..f9639e2 100644
--- a/pkg/analyzer/test/src/summary/index_unit_test.dart
+++ b/pkg/analyzer/test/src/summary/index_unit_test.dart
@@ -763,6 +763,43 @@
     assertThat(enumElement.getGetter('B'))..isReferencedAt('B);', true);
   }
 
+  void test_isReferencedBy_FieldElement_synthetic_hasGetter() {
+    verifyNoTestUnitErrors = false;
+    _indexTestUnit('''
+class A {
+  A() : f = 42;
+  int get f => 0;
+}
+''');
+    ClassElement element2 = findElement('A');
+    assertThat(element2.getField('f')).isWrittenAt('f = 42', true);
+  }
+
+  void test_isReferencedBy_FieldElement_synthetic_hasGetterSetter() {
+    verifyNoTestUnitErrors = false;
+    _indexTestUnit('''
+class A {
+  A() : f = 42;
+  int get f => 0;
+  set f(_) {}
+}
+''');
+    ClassElement element2 = findElement('A');
+    assertThat(element2.getField('f')).isWrittenAt('f = 42', true);
+  }
+
+  void test_isReferencedBy_FieldElement_synthetic_hasSetter() {
+    verifyNoTestUnitErrors = false;
+    _indexTestUnit('''
+class A {
+  A() : f = 42;
+  set f(_) {}
+}
+''');
+    ClassElement element2 = findElement('A');
+    assertThat(element2.getField('f')).isWrittenAt('f = 42', true);
+  }
+
   void test_isReferencedBy_FunctionElement() {
     _indexTestUnit('''
 foo() {}
@@ -908,6 +945,22 @@
       ..isWrittenAt('field = 5', true);
   }
 
+  void test_usedName_inLibraryIdentifier() {
+    verifyNoTestUnitErrors = false;
+    _indexTestUnit('''
+library aaa.bbb.ccc;
+class C {
+  var bbb;
+}
+main(p) {
+  p.bbb = 1;
+}
+''');
+    assertThatName('bbb')
+      ..isNotUsed('bbb.ccc', IndexRelationKind.IS_READ_BY)
+      ..isUsedQ('bbb = 1;', IndexRelationKind.IS_WRITTEN_BY);
+  }
+
   void test_usedName_qualified_resolved() {
     verifyNoTestUnitErrors = false;
     _indexTestUnit('''
@@ -922,10 +975,10 @@
 }
 ''');
     assertThatName('x')
-      ..isNotUsed('x;', IndexRelationKind.IS_READ_BY)
-      ..isNotUsed('x = 1;', IndexRelationKind.IS_WRITTEN_BY)
-      ..isNotUsed('x += 2;', IndexRelationKind.IS_READ_WRITTEN_BY)
-      ..isNotUsed('x();', IndexRelationKind.IS_INVOKED_BY);
+      ..isNotUsedQ('x;', IndexRelationKind.IS_READ_BY)
+      ..isNotUsedQ('x = 1;', IndexRelationKind.IS_WRITTEN_BY)
+      ..isNotUsedQ('x += 2;', IndexRelationKind.IS_READ_WRITTEN_BY)
+      ..isNotUsedQ('x();', IndexRelationKind.IS_INVOKED_BY);
   }
 
   void test_usedName_qualified_unresolved() {
@@ -959,10 +1012,10 @@
 }
 ''');
     assertThatName('x')
-      ..isNotUsed('x;', IndexRelationKind.IS_READ_BY)
-      ..isNotUsed('x = 1;', IndexRelationKind.IS_WRITTEN_BY)
-      ..isNotUsed('x += 2;', IndexRelationKind.IS_READ_WRITTEN_BY)
-      ..isNotUsed('x();', IndexRelationKind.IS_INVOKED_BY);
+      ..isNotUsedQ('x;', IndexRelationKind.IS_READ_BY)
+      ..isNotUsedQ('x = 1;', IndexRelationKind.IS_WRITTEN_BY)
+      ..isNotUsedQ('x += 2;', IndexRelationKind.IS_READ_WRITTEN_BY)
+      ..isNotUsedQ('x();', IndexRelationKind.IS_INVOKED_BY);
   }
 
   void test_usedName_unqualified_unresolved() {
@@ -1201,6 +1254,11 @@
 
   void isNotUsed(String search, IndexRelationKind kind) {
     test._assertUsedName(
+        name, kind, test._expectedLocation(search, false), true);
+  }
+
+  void isNotUsedQ(String search, IndexRelationKind kind) {
+    test._assertUsedName(
         name, kind, test._expectedLocation(search, true), true);
   }
 
diff --git a/pkg/analyzer/test/src/summary/resynthesize_test.dart b/pkg/analyzer/test/src/summary/resynthesize_test.dart
index d1f2b88..0d810b4 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_test.dart
@@ -7,6 +7,7 @@
 import 'dart:convert';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/constant/value.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
@@ -14,7 +15,6 @@
 import 'package:analyzer/src/dart/element/handle.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/constant.dart' show DartObject;
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart'
     show Namespace, TypeProvider;
diff --git a/pkg/analyzer/test/src/summary/test_all.dart b/pkg/analyzer/test/src/summary/test_all.dart
index fe80a5a..08af93d 100644
--- a/pkg/analyzer/test/src/summary/test_all.dart
+++ b/pkg/analyzer/test/src/summary/test_all.dart
@@ -8,6 +8,7 @@
 
 import '../../utils.dart';
 import 'flat_buffers_test.dart' as flat_buffers_test;
+import 'incremental_cache_test.dart' as incremental_cache_test;
 import 'index_unit_test.dart' as index_unit_test;
 import 'name_filter_test.dart' as name_filter_test;
 import 'prelinker_test.dart' as prelinker_test;
@@ -22,6 +23,7 @@
   initializeTestEnvironment();
   group('summary tests', () {
     flat_buffers_test.main();
+    incremental_cache_test.main();
     index_unit_test.main();
     name_filter_test.main();
     prelinker_test.main();
diff --git a/pkg/analyzer/test/src/task/driver_test.dart b/pkg/analyzer/test/src/task/driver_test.dart
index 221636a..bd21675 100644
--- a/pkg/analyzer/test/src/task/driver_test.dart
+++ b/pkg/analyzer/test/src/task/driver_test.dart
@@ -124,6 +124,32 @@
     expect(analysisDriver.createNextWorkOrder(), isNull);
   }
 
+  test_createWorkOrderForResult_aboutToComputeResult() {
+    AnalysisTarget target = new TestSource();
+    ResultDescriptor result = new ResultDescriptor('result', null);
+    TaskDescriptor descriptor = new TaskDescriptor(
+        'task',
+        (context, target) => new TestAnalysisTask(context, target),
+        (target) => {},
+        [result]);
+    taskManager.addTaskDescriptor(descriptor);
+    context.getCacheEntry(target).setState(result, CacheState.INVALID);
+    // has result
+    {
+      when(context.aboutToComputeResult(anyObject, result)).thenReturn(true);
+      WorkOrder workOrder =
+          analysisDriver.createWorkOrderForResult(target, result);
+      expect(workOrder, isNull);
+    }
+    // no result
+    {
+      when(context.aboutToComputeResult(anyObject, result)).thenReturn(false);
+      WorkOrder workOrder =
+          analysisDriver.createWorkOrderForResult(target, result);
+      expect(workOrder, isNotNull);
+    }
+  }
+
   test_createWorkOrderForResult_error() {
     AnalysisTarget target = new TestSource();
     ResultDescriptor result = new ResultDescriptor('result', null);
@@ -649,57 +675,6 @@
     expect(item.target, target);
   }
 
-  test_gatherInputs_complete() {
-    AnalysisTarget target = new TestSource();
-    TaskDescriptor descriptor = new TaskDescriptor(
-        'task',
-        (context, target) => new TestAnalysisTask(context, target),
-        (target) => {},
-        [new ResultDescriptor('output', null)]);
-    WorkItem item = new WorkItem(context, target, descriptor, null, 0, null);
-    WorkItem result = item.gatherInputs(taskManager, []);
-    expect(result, isNull);
-    expect(item.exception, isNull);
-  }
-
-  test_gatherInputs_incomplete() {
-    AnalysisTarget target = new TestSource();
-    ResultDescriptor resultA = new ResultDescriptor('resultA', null);
-    ResultDescriptor resultB = new ResultDescriptor('resultB', null);
-    // prepare tasks
-    TaskDescriptor task1 = new TaskDescriptor(
-        'task',
-        (context, target) =>
-            new TestAnalysisTask(context, target, results: [resultA]),
-        (target) => {},
-        [resultA]);
-    TaskDescriptor task2 = new TaskDescriptor(
-        'task',
-        (context, target) => new TestAnalysisTask(context, target),
-        (target) => {'one': resultA.of(target)},
-        [resultB]);
-    taskManager.addTaskDescriptor(task1);
-    taskManager.addTaskDescriptor(task2);
-    // gather inputs
-    WorkItem item = new WorkItem(context, target, task2, null, 0, null);
-    WorkItem inputItem = item.gatherInputs(taskManager, []);
-    expect(inputItem, isNotNull);
-  }
-
-  test_gatherInputs_invalid() {
-    AnalysisTarget target = new TestSource();
-    ResultDescriptor inputResult = new ResultDescriptor('input', null);
-    TaskDescriptor descriptor = new TaskDescriptor(
-        'task',
-        (context, target) => new TestAnalysisTask(context, target),
-        (target) => {'one': inputResult.of(target)},
-        [new ResultDescriptor('output', null)]);
-    WorkItem item = new WorkItem(context, target, descriptor, null, 0, null);
-    WorkItem result = item.gatherInputs(taskManager, []);
-    expect(result, isNull);
-    expect(item.exception, isNotNull);
-  }
-
   test_gatherInputs_aboutToComputeResult_hasResult() {
     AnalysisTarget target = new TestSource();
     ResultDescriptor resultA = new ResultDescriptor('resultA', null);
@@ -754,6 +729,57 @@
     expect(inputItem.target, target);
     expect(inputItem.descriptor, task1);
   }
+
+  test_gatherInputs_complete() {
+    AnalysisTarget target = new TestSource();
+    TaskDescriptor descriptor = new TaskDescriptor(
+        'task',
+        (context, target) => new TestAnalysisTask(context, target),
+        (target) => {},
+        [new ResultDescriptor('output', null)]);
+    WorkItem item = new WorkItem(context, target, descriptor, null, 0, null);
+    WorkItem result = item.gatherInputs(taskManager, []);
+    expect(result, isNull);
+    expect(item.exception, isNull);
+  }
+
+  test_gatherInputs_incomplete() {
+    AnalysisTarget target = new TestSource();
+    ResultDescriptor resultA = new ResultDescriptor('resultA', null);
+    ResultDescriptor resultB = new ResultDescriptor('resultB', null);
+    // prepare tasks
+    TaskDescriptor task1 = new TaskDescriptor(
+        'task',
+        (context, target) =>
+            new TestAnalysisTask(context, target, results: [resultA]),
+        (target) => {},
+        [resultA]);
+    TaskDescriptor task2 = new TaskDescriptor(
+        'task',
+        (context, target) => new TestAnalysisTask(context, target),
+        (target) => {'one': resultA.of(target)},
+        [resultB]);
+    taskManager.addTaskDescriptor(task1);
+    taskManager.addTaskDescriptor(task2);
+    // gather inputs
+    WorkItem item = new WorkItem(context, target, task2, null, 0, null);
+    WorkItem inputItem = item.gatherInputs(taskManager, []);
+    expect(inputItem, isNotNull);
+  }
+
+  test_gatherInputs_invalid() {
+    AnalysisTarget target = new TestSource();
+    ResultDescriptor inputResult = new ResultDescriptor('input', null);
+    TaskDescriptor descriptor = new TaskDescriptor(
+        'task',
+        (context, target) => new TestAnalysisTask(context, target),
+        (target) => {'one': inputResult.of(target)},
+        [new ResultDescriptor('output', null)]);
+    WorkItem item = new WorkItem(context, target, descriptor, null, 0, null);
+    WorkItem result = item.gatherInputs(taskManager, []);
+    expect(result, isNull);
+    expect(item.exception, isNotNull);
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 09738bd..8c4eb3c 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -87,6 +87,73 @@
     ''');
   });
 
+  test('for-in casts supertype sequence to iterable', () {
+    checkFile('''
+      main() {
+        dynamic d;
+        for (var i in /*info:DYNAMIC_CAST*/d) {}
+
+        Object o;
+        for (var i in /*info:DOWN_CAST_IMPLICIT*/o) {}
+      }
+    ''');
+  });
+
+  test('await for-in casts supertype sequence to stream', () {
+    checkFile('''
+      main() async {
+        dynamic d;
+        await for (var i in /*info:DYNAMIC_CAST*/d) {}
+
+        Object o;
+        await for (var i in /*info:DOWN_CAST_IMPLICIT*/o) {}
+      }
+    ''');
+  });
+
+  test('for-in casts iterable element to variable', () {
+    checkFile('''
+      main() {
+        // Don't choke if sequence is not iterable.
+        for (var i in /*warning:FOR_IN_OF_INVALID_TYPE*/1234) {}
+
+        // Dynamic cast.
+        for (String /*info:DYNAMIC_CAST*/s in <dynamic>[]) {}
+
+        // Identity cast.
+        for (String s in <String>[]) {}
+
+        // Untyped.
+        for (var s in <String>[]) {}
+
+        // Downcast.
+        for (int /*info:DOWN_CAST_IMPLICIT*/i in <num>[]) {}
+      }
+    ''');
+  });
+
+  test('await for-in casts stream element to variable', () {
+    checkFile('''
+      import 'dart:async';
+      main() async {
+        // Don't choke if sequence is not stream.
+        await for (var i in /*warning:FOR_IN_OF_INVALID_TYPE*/1234) {}
+
+        // Dynamic cast.
+        await for (String /*info:DYNAMIC_CAST*/s in new Stream<dynamic>()) {}
+
+        // Identity cast.
+        await for (String s in new Stream<String>()) {}
+
+        // Untyped.
+        await for (var s in new Stream<String>()) {}
+
+        // Downcast.
+        await for (int /*info:DOWN_CAST_IMPLICIT*/i in new Stream<num>()) {}
+      }
+    ''');
+  });
+
   test('dynamic invocation', () {
     checkFile('''
       class A {
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 3290d9b..58944b6 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -484,12 +484,12 @@
         }
 
         Iterable iter = list;
-        for (Foo x in /*warning:DOWN_CAST_COMPOSITE*/iter) {
+        for (Foo /*info:DYNAMIC_CAST*/x in iter) {
           var y = x;
         }
 
         dynamic iter2 = list;
-        for (Foo x in /*warning:DOWN_CAST_COMPOSITE*/iter2) {
+        for (Foo /*info:DYNAMIC_CAST*/x in /*info:DYNAMIC_CAST*/iter2) {
           var y = x;
         }
 
diff --git a/pkg/analyzer/test/test_all.dart b/pkg/analyzer/test/test_all.dart
index 8155789..7e45412 100644
--- a/pkg/analyzer/test/test_all.dart
+++ b/pkg/analyzer/test/test_all.dart
@@ -7,6 +7,7 @@
 import 'package:unittest/unittest.dart';
 
 import 'cancelable_future_test.dart' as cancelable_future_test;
+import 'context/test_all.dart' as context;
 import 'enum_test.dart' as enum_test;
 import 'file_system/test_all.dart' as file_system;
 import 'generated/test_all.dart' as generated;
@@ -21,6 +22,7 @@
   initializeTestEnvironment();
   group('analysis engine', () {
     cancelable_future_test.main();
+    context.main();
     enum_test.main();
     file_system.main();
     generated.main();
diff --git a/pkg/analyzer_cli/.analysis_options b/pkg/analyzer_cli/.analysis_options
new file mode 100644
index 0000000..78831a9
--- /dev/null
+++ b/pkg/analyzer_cli/.analysis_options
@@ -0,0 +1,3 @@
+analyzer:
+  exclude:
+    - 'test/data'
diff --git a/pkg/analyzer_cli/lib/src/analyzer_impl.dart b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
index 56eaa2f..95bed11 100644
--- a/pkg/analyzer_cli/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
@@ -40,6 +40,9 @@
 
   final AnalysisContext context;
 
+  /// Accumulated analysis statistics.
+  final AnalysisStats stats;
+
   final Source librarySource;
 
   /// All [Source]s references by the analyzed library.
@@ -59,7 +62,8 @@
   /// specified the "--package-warnings" option.
   String _selfPackageName;
 
-  AnalyzerImpl(this.context, this.librarySource, this.options, this.startTime);
+  AnalyzerImpl(this.context, this.librarySource, this.options, this.stats,
+      this.startTime);
 
   /// Returns the maximal [ErrorSeverity] of the recorded errors.
   ErrorSeverity get maxErrorSeverity {
@@ -76,8 +80,8 @@
     return status;
   }
 
-  void addCompilationUnitSource(CompilationUnitElement unit,
-      Set<LibraryElement> libraries, Set<CompilationUnitElement> units) {
+  void addCompilationUnitSource(
+      CompilationUnitElement unit, Set<CompilationUnitElement> units) {
     if (unit == null || units.contains(unit)) {
       return;
     }
@@ -91,21 +95,13 @@
       return;
     }
     // Maybe skip library.
-    {
-      UriKind uriKind = library.source.uriKind;
-      // Optionally skip package: libraries.
-      if (!options.showPackageWarnings && _isOtherPackage(library.source.uri)) {
-        return;
-      }
-      // Optionally skip SDK libraries.
-      if (!options.showSdkWarnings && uriKind == UriKind.DART_URI) {
-        return;
-      }
+    if (!_isAnalyzedLibrary(library)) {
+      return;
     }
     // Add compilation units.
-    addCompilationUnitSource(library.definingCompilationUnit, libraries, units);
+    addCompilationUnitSource(library.definingCompilationUnit, units);
     for (CompilationUnitElement child in library.parts) {
-      addCompilationUnitSource(child, libraries, units);
+      addCompilationUnitSource(child, units);
     }
     // Add referenced libraries.
     for (LibraryElement child in library.importedLibraries) {
@@ -181,18 +177,34 @@
     return status;
   }
 
-  /// Determine whether the given URI refers to a package other than the package
-  /// being analyzed.
-  bool _isOtherPackage(Uri uri) {
-    if (uri.scheme != 'package') {
+  /// Returns true if we want to report diagnostics for this library.
+  bool _isAnalyzedLibrary(LibraryElement library) {
+    switch (library.source.uriKind) {
+      case UriKind.DART_URI:
+        return options.showSdkWarnings;
+      case UriKind.PACKAGE_URI:
+        return _isAnalyzedPackage(library.source.uri);
+      default:
+        return true;
+    }
+  }
+
+  /// Determine whether the given URI refers to a package being analyzed.
+  bool _isAnalyzedPackage(Uri uri) {
+    if (uri.scheme != 'package' || uri.pathSegments.isEmpty) {
       return false;
     }
-    if (_selfPackageName != null &&
-        uri.pathSegments.length > 0 &&
-        uri.pathSegments[0] == _selfPackageName) {
+
+    String packageName = uri.pathSegments.first;
+    if (packageName == _selfPackageName) {
+      return true;
+    } else if (!options.showPackageWarnings) {
       return false;
+    } else if (options.showPackageWarningsPrefix == null) {
+      return true;
+    } else {
+      return packageName.startsWith(options.showPackageWarningsPrefix);
     }
-    return true;
   }
 
   _printColdPerf() {
@@ -220,7 +232,8 @@
     StringSink sink = options.machineFormat ? errorSink : outSink;
 
     // Print errors.
-    ErrorFormatter formatter = new ErrorFormatter(sink, options, _processError);
+    ErrorFormatter formatter =
+        new ErrorFormatter(sink, options, stats, _processError);
     formatter.formatErrors(errorInfos);
   }
 
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index dc40c0d..eb1df03 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -33,6 +33,7 @@
 import 'package:analyzer/src/services/lint.dart';
 import 'package:analyzer/src/task/options.dart';
 import 'package:analyzer_cli/src/analyzer_impl.dart';
+import 'package:analyzer_cli/src/error_formatter.dart';
 import 'package:analyzer_cli/src/options.dart';
 import 'package:analyzer_cli/src/package_analyzer.dart';
 import 'package:analyzer_cli/src/perf_report.dart';
@@ -79,6 +80,9 @@
   /// `null` if [_analyzeAll] hasn't been called yet.
   AnalysisContext _context;
 
+  /// The total number of source files loaded by an AnalysisContext.
+  int _analyzedFileCount = 0;
+
   /// If [_context] is not `null`, the [CommandLineOptions] that guided its
   /// creation.
   CommandLineOptions _previousOptions;
@@ -89,6 +93,9 @@
   @override
   ResolverProvider packageResolverProvider;
 
+  /// Collected analysis statistics.
+  final AnalysisStats stats = new AnalysisStats();
+
   /// This Driver's current analysis context.
   ///
   /// *Visible for testing.*
@@ -96,11 +103,14 @@
 
   @override
   void set userDefinedPlugins(List<Plugin> plugins) {
-    _userDefinedPlugins = plugins == null ? <Plugin>[] : plugins;
+    _userDefinedPlugins = plugins ?? <Plugin>[];
   }
 
   @override
   void start(List<String> args) {
+    if (_context != null) {
+      throw new StateError("start() can only be called once");
+    }
     int startTime = new DateTime.now().millisecondsSinceEpoch;
 
     StringUtilities.INTERNER = new MappedInterner();
@@ -133,8 +143,13 @@
       }
     }
 
+    if (_context != null) {
+      _analyzedFileCount += _context.sources.length;
+    }
+
     if (options.perfReport != null) {
-      String json = makePerfReport(startTime, currentTimeMillis(), options);
+      String json = makePerfReport(
+          startTime, currentTimeMillis(), options, _analyzedFileCount, stats);
       new File(options.perfReport).writeAsStringSync(json);
     }
   }
@@ -162,32 +177,32 @@
     // Add all the files to be analyzed en masse to the context.  Skip any
     // files that were added earlier (whether explicitly or implicitly) to
     // avoid causing those files to be unnecessarily re-read.
-    Set<Source> knownSources = _context.sources.toSet();
+    Set<Source> knownSources = context.sources.toSet();
     List<Source> sourcesToAnalyze = <Source>[];
     ChangeSet changeSet = new ChangeSet();
     for (String sourcePath in options.sourceFiles) {
       sourcePath = sourcePath.trim();
-      // Check that file exists.
-      if (!new File(sourcePath).existsSync()) {
-        errorSink.writeln('File not found: $sourcePath');
+
+      // Collect files for analysis.
+      // Note that these files will all be analyzed in the same context.
+      // This should be updated when the ContextManager re-work is complete
+      // (See: https://github.com/dart-lang/sdk/issues/24133)
+      Iterable<File> files = _collectFiles(sourcePath);
+      if (files.isEmpty) {
+        errorSink.writeln('No dart files found at: $sourcePath');
         exitCode = ErrorSeverity.ERROR.ordinal;
-        //Fail fast; don't analyze more files
         return ErrorSeverity.ERROR;
       }
-      // Check that file is Dart file.
-      if (!AnalysisEngine.isDartFileName(sourcePath)) {
-        errorSink.writeln('$sourcePath is not a Dart file');
-        exitCode = ErrorSeverity.ERROR.ordinal;
-        // Fail fast; don't analyze more files.
-        return ErrorSeverity.ERROR;
+
+      for (File file in files) {
+        Source source = _computeLibrarySource(file.absolute.path);
+        if (!knownSources.contains(source)) {
+          changeSet.addedSource(source);
+        }
+        sourcesToAnalyze.add(source);
       }
-      Source source = _computeLibrarySource(sourcePath);
-      if (!knownSources.contains(source)) {
-        changeSet.addedSource(source);
-      }
-      sourcesToAnalyze.add(source);
     }
-    _context.applyChanges(changeSet);
+    context.applyChanges(changeSet);
 
     // Analyze the libraries.
     ErrorSeverity allResult = ErrorSeverity.NONE;
@@ -219,13 +234,17 @@
       }
     }
 
+    if (!options.machineFormat) {
+      stats.print(outSink);
+    }
+
     return allResult;
   }
 
   /// Perform package analysis according to the given [options].
   ErrorSeverity _analyzePackage(CommandLineOptions options) {
     return _analyzeAllTag.makeCurrentWhile(() {
-      return new PackageAnalyzer(options).analyze();
+      return new PackageAnalyzer(options, stats).analyze();
     });
   }
 
@@ -259,6 +278,10 @@
     if (options.showPackageWarnings != _previousOptions.showPackageWarnings) {
       return false;
     }
+    if (options.showPackageWarningsPrefix !=
+        _previousOptions.showPackageWarningsPrefix) {
+      return false;
+    }
     if (options.showSdkWarnings != _previousOptions.showSdkWarnings) {
       return false;
     }
@@ -292,38 +315,14 @@
       return (Source source) => true;
     }
 
-    // Determine the set of packages requiring a full parse.  Use null to
-    // represent the case where all packages require a full parse.
-    Set<String> packagesRequiringFullParse;
-    if (options.showPackageWarnings) {
-      // We are showing warnings from all packages so all packages require a
-      // full parse.
-      packagesRequiringFullParse = null;
-    } else {
-      // We aren't showing warnings for dependent packages, but we may still
-      // need to show warnings for "self" packages, so we need to do a full
-      // parse in any package containing files mentioned on the command line.
-      // TODO(paulberry): implement this.  As a temporary workaround, we're
-      // fully parsing all packages.
-      packagesRequiringFullParse = null;
-    }
     return (Source source) {
       if (options.sourceFiles.contains(source.fullName)) {
         return true;
       } else if (source.uri.scheme == 'dart') {
         return options.showSdkWarnings;
-      } else if (source.uri.scheme == 'package') {
-        if (packagesRequiringFullParse == null) {
-          return true;
-        } else if (source.uri.pathSegments.length == 0) {
-          // We should never see a URI like this, but fully parse it to be
-          // safe.
-          return true;
-        } else {
-          return packagesRequiringFullParse
-              .contains(source.uri.pathSegments[0]);
-        }
       } else {
+        // TODO(paulberry): diet parse 'package:' imports when we don't want
+        // diagnostics. (Full parse is still needed for "self" packages.)
         return true;
       }
     };
@@ -451,6 +450,29 @@
     return new SourceFactory(resolvers, packages);
   }
 
+  /// Collect all analyzable files at [filePath], recursively if it's a
+  /// directory, ignoring links.
+  Iterable<File> _collectFiles(String filePath) {
+    List<File> files = <File>[];
+    File file = new File(filePath);
+    if (file.existsSync()) {
+      files.add(file);
+    } else {
+      Directory directory = new Directory(filePath);
+      if (directory.existsSync()) {
+        for (FileSystemEntity entry
+            in directory.listSync(recursive: true, followLinks: false)) {
+          String relative = path.relative(entry.path, from: directory.path);
+          if (AnalysisEngine.isDartFileName(entry.path) &&
+              !_isInHiddenDir(relative)) {
+            files.add(entry);
+          }
+        }
+      }
+    }
+    return files;
+  }
+
   /// Convert the given [sourcePath] (which may be relative to the current
   /// working directory) to a [Source] object that can be fed to the analysis
   /// context.
@@ -477,18 +499,22 @@
     }
     _previousOptions = options;
 
+    // Save stats from previous context before clobbering it.
+    if (_context != null) {
+      _analyzedFileCount += _context.sources.length;
+    }
+
     // Create a context.
-    AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
-    _context = context;
+    _context = AnalysisEngine.instance.createAnalysisContext();
 
     // Choose a package resolution policy and a diet parsing policy based on
     // the command-line options.
     SourceFactory sourceFactory = _chooseUriResolutionPolicy(
-        options, (context as InternalAnalysisContext).embedderYamlLocator);
+        options, (_context as InternalAnalysisContext).embedderYamlLocator);
     AnalyzeFunctionBodiesPredicate dietParsingPolicy =
         _chooseDietParsingPolicy(options);
 
-    context.sourceFactory = sourceFactory;
+    _context.sourceFactory = sourceFactory;
 
     setAnalysisContextOptions(_context, options,
         (AnalysisOptionsImpl contextOptions) {
@@ -525,6 +551,10 @@
     return folderMap;
   }
 
+  /// Returns `true` if this relative path is a hidden directory.
+  bool _isInHiddenDir(String relative) =>
+      path.split(relative).any((part) => part.startsWith("."));
+
   void _processPlugins() {
     List<Plugin> plugins = <Plugin>[];
     plugins.addAll(AnalysisEngine.instance.requiredPlugins);
@@ -541,7 +571,7 @@
   ErrorSeverity _runAnalyzer(Source source, CommandLineOptions options) {
     int startTime = currentTimeMillis();
     AnalyzerImpl analyzer =
-        new AnalyzerImpl(_context, source, options, startTime);
+        new AnalyzerImpl(_context, source, options, stats, startTime);
     var errorSeverity = analyzer.analyzeSync();
     if (errorSeverity == ErrorSeverity.ERROR) {
       exitCode = errorSeverity.ordinal;
@@ -685,7 +715,7 @@
             '>>> BATCH END (${totalTests - testsFailed}/$totalTests) ${time}ms');
         exitCode = batchResult.ordinal;
       }
-      // Prepare aruments.
+      // Prepare arguments.
       var args;
       {
         var lineArgs = line.split(new RegExp('\\s+'));
diff --git a/pkg/analyzer_cli/lib/src/error_formatter.dart b/pkg/analyzer_cli/lib/src/error_formatter.dart
index 0154d73..c43fcd8 100644
--- a/pkg/analyzer_cli/lib/src/error_formatter.dart
+++ b/pkg/analyzer_cli/lib/src/error_formatter.dart
@@ -13,19 +13,105 @@
 ProcessedSeverity _identity(AnalysisError error) =>
     new ProcessedSeverity(error.errorCode.errorSeverity);
 
+String _pluralize(String word, int count) => count == 1 ? word : word + "s";
+
 /// Returns desired severity for the given [error] (or `null` if it's to be
 /// suppressed).
 typedef ProcessedSeverity _SeverityProcessor(AnalysisError error);
 
+/// Analysis statistics counter.
+class AnalysisStats {
+  /// The total number of diagnostics sent to [formatErrors].
+  int unfilteredCount;
+
+  int errorCount;
+  int hintCount;
+  int lintCount;
+  int warnCount;
+
+  AnalysisStats() {
+    init();
+  }
+
+  /// The total number of diagnostics reported to the user.
+  int get filteredCount => errorCount + warnCount + hintCount + lintCount;
+
+  /// (Re)set initial values.
+  void init() {
+    unfilteredCount = 0;
+    errorCount = 0;
+    hintCount = 0;
+    lintCount = 0;
+    warnCount = 0;
+  }
+
+  /// Print statistics to [out].
+  void print(StringSink out) {
+    var hasErrors = errorCount != 0;
+    var hasWarns = warnCount != 0;
+    var hasHints = hintCount != 0;
+    var hasLints = lintCount != 0;
+    bool hasContent = false;
+    if (hasErrors) {
+      out.write(errorCount);
+      out.write(' ');
+      out.write(_pluralize("error", errorCount));
+      hasContent = true;
+    }
+    if (hasWarns) {
+      if (hasContent) {
+        if (!hasHints && !hasLints) {
+          out.write(' and ');
+        } else {
+          out.write(", ");
+        }
+      }
+      out.write(warnCount);
+      out.write(' ');
+      out.write(_pluralize("warning", warnCount));
+      hasContent = true;
+    }
+    if (hasHints) {
+      if (hasContent) {
+        if (!hasLints) {
+          out.write(' and ');
+        } else {
+          out.write(", ");
+        }
+      }
+      out.write(hintCount);
+      out.write(' ');
+      out.write(_pluralize("hint", hintCount));
+      hasContent = true;
+    }
+    if (hasLints) {
+      if (hasContent) {
+        out.write(" and ");
+      }
+      out.write(lintCount);
+      out.write(' ');
+      out.write(_pluralize("lint", lintCount));
+      hasContent = true;
+    }
+    if (hasContent) {
+      out.writeln(" found.");
+    } else {
+      out.writeln("No issues found");
+    }
+  }
+}
+
 /// Helper for formatting [AnalysisError]s.
 /// The two format options are a user consumable format and a machine consumable
 /// format.
 class ErrorFormatter {
   final StringSink out;
   final CommandLineOptions options;
+  final AnalysisStats stats;
   final _SeverityProcessor processSeverity;
 
-  ErrorFormatter(this.out, this.options, [this.processSeverity = _identity]);
+  ErrorFormatter(this.out, this.options, this.stats,
+      [this.processSeverity = _identity]);
 
   /// Compute the severity for this [error] or `null` if this error should be
   /// filtered.
@@ -83,6 +169,8 @@
   }
 
   void formatErrors(List<AnalysisErrorInfo> errorInfos) {
+    stats.unfilteredCount += errorInfos.length;
+
     var errors = new List<AnalysisError>();
     var errorToLine = new Map<AnalysisError, LineInfo>();
     for (AnalysisErrorInfo errorInfo in errorInfos) {
@@ -112,84 +200,26 @@
       return error1.offset - error2.offset;
     });
     // Format errors.
-    int errorCount = 0;
-    int warnCount = 0;
-    int hintCount = 0;
-    int lintCount = 0;
     for (AnalysisError error in errors) {
       ProcessedSeverity processedSeverity = processSeverity(error);
       ErrorSeverity severity = processedSeverity.severity;
       if (severity == ErrorSeverity.ERROR) {
-        errorCount++;
+        stats.errorCount++;
       } else if (severity == ErrorSeverity.WARNING) {
         /// Only treat a warning as an error if it's not been set by a
         /// proccesser.
         if (!processedSeverity.overridden && options.warningsAreFatal) {
-          errorCount++;
+          stats.errorCount++;
         } else {
-          warnCount++;
+          stats.warnCount++;
         }
       } else if (error.errorCode.type == ErrorType.HINT) {
-        hintCount++;
+        stats.hintCount++;
       } else if (error.errorCode.type == ErrorType.LINT) {
-        lintCount++;
+        stats.lintCount++;
       }
       formatError(errorToLine, error);
     }
-    // Print statistics.
-    if (!options.machineFormat) {
-      var hasErrors = errorCount != 0;
-      var hasWarns = warnCount != 0;
-      var hasHints = hintCount != 0;
-      var hasLints = lintCount != 0;
-      bool hasContent = false;
-      if (hasErrors) {
-        out.write(errorCount);
-        out.write(' ');
-        out.write(pluralize("error", errorCount));
-        hasContent = true;
-      }
-      if (hasWarns) {
-        if (hasContent) {
-          if (!hasHints && !hasLints) {
-            out.write(' and ');
-          } else {
-            out.write(", ");
-          }
-        }
-        out.write(warnCount);
-        out.write(' ');
-        out.write(pluralize("warning", warnCount));
-        hasContent = true;
-      }
-      if (hasHints) {
-        if (hasContent) {
-          if (!hasLints) {
-            out.write(' and ');
-          } else {
-            out.write(", ");
-          }
-        }
-        out.write(hintCount);
-        out.write(' ');
-        out.write(pluralize("hint", hintCount));
-        hasContent = true;
-      }
-      if (hasLints) {
-        if (hasContent) {
-          out.write(" and ");
-        }
-        out.write(lintCount);
-        out.write(' ');
-        out.write(pluralize("lint", lintCount));
-        hasContent = true;
-      }
-      if (hasContent) {
-        out.writeln(" found.");
-      } else {
-        out.writeln("No issues found");
-      }
-    }
   }
 
   static String escapePipe(String input) {
@@ -202,17 +232,9 @@
     }
     return result.toString();
   }
-
-  static String pluralize(String word, int count) {
-    if (count == 1) {
-      return word;
-    } else {
-      return word + "s";
-    }
-  }
 }
 
-/// A severity with awareness of whether it was overriden by a processor.
+/// A severity with awareness of whether it was overridden by a processor.
 class ProcessedSeverity {
   ErrorSeverity severity;
   bool overridden;
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index ec62ce3..3f100af 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -111,6 +111,9 @@
   /// Whether to show package: warnings
   final bool showPackageWarnings;
 
+  /// If not null, show package: warnings only for matching packages.
+  final String showPackageWarningsPrefix;
+
   /// Whether to show SDK warnings
   final bool showSdkWarnings;
 
@@ -151,8 +154,10 @@
         packageRootPath = args['package-root'],
         perfReport = args['x-perf-report'],
         shouldBatch = args['batch'],
-        showPackageWarnings =
-            args['show-package-warnings'] || args['package-warnings'],
+        showPackageWarnings = args['show-package-warnings'] ||
+            args['package-warnings'] ||
+            args['x-package-warnings-prefix'] != null,
+        showPackageWarningsPrefix = args['x-package-warnings-prefix'],
         showSdkWarnings = args['show-sdk-warnings'] || args['warnings'],
         sourceFiles = args.rest,
         warningsAreFatal = args['fatal-warnings'],
@@ -281,6 +286,10 @@
           help: 'Show warnings from SDK imports (deprecated).',
           defaultsTo: false,
           negatable: false)
+      ..addOption('x-package-warnings-prefix',
+          help:
+              'Show warnings from package: imports that match the given prefix',
+          hide: true)
       ..addOption('x-perf-report',
           help: 'Writes a performance report to the given file (experimental).')
       ..addFlag('help',
diff --git a/pkg/analyzer_cli/lib/src/package_analyzer.dart b/pkg/analyzer_cli/lib/src/package_analyzer.dart
index 418db25..fd173a3 100644
--- a/pkg/analyzer_cli/lib/src/package_analyzer.dart
+++ b/pkg/analyzer_cli/lib/src/package_analyzer.dart
@@ -31,6 +31,7 @@
  */
 class PackageAnalyzer {
   final CommandLineOptions options;
+  final AnalysisStats stats;
 
   String packagePath;
   String packageLibPath;
@@ -39,7 +40,7 @@
   InternalAnalysisContext context;
   final List<Source> explicitSources = <Source>[];
 
-  PackageAnalyzer(this.options);
+  PackageAnalyzer(this.options, this.stats);
 
   /**
    * Perform package analysis according to the given [options].
@@ -181,11 +182,13 @@
     ErrorFormatter formatter = new ErrorFormatter(
         sink,
         options,
+        stats,
         (AnalysisError error) =>
             AnalyzerImpl.processError(error, options, context));
     for (Source source in explicitSources) {
       AnalysisErrorInfo errorInfo = context.getErrors(source);
       formatter.formatErrors([errorInfo]);
     }
+    stats.print(sink);
   }
 }
diff --git a/pkg/analyzer_cli/lib/src/perf_report.dart b/pkg/analyzer_cli/lib/src/perf_report.dart
index 208e560..f92ae9a 100644
--- a/pkg/analyzer_cli/lib/src/perf_report.dart
+++ b/pkg/analyzer_cli/lib/src/perf_report.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/src/generated/utilities_general.dart'
     show PerformanceTag;
 import 'package:analyzer/task/model.dart' show AnalysisTask;
+import 'package:analyzer_cli/src/error_formatter.dart';
 import 'package:analyzer_cli/src/options.dart' show CommandLineOptions;
 
 const _JSON = const JsonEncoder.withIndent("  ");
@@ -39,7 +40,8 @@
   }
 }();
 
-String makePerfReport(int startTime, int endTime, CommandLineOptions options) {
+String makePerfReport(int startTime, int endTime, CommandLineOptions options,
+    int analyzedFileCount, AnalysisStats stats) {
   int totalTime = endTime - startTime;
   int otherTime = totalTime;
 
@@ -53,6 +55,7 @@
     'dartSdkPath': options.dartSdkPath,
     'strongMode': options.strongMode,
     'showPackageWarnings': options.showPackageWarnings,
+    'showPackageWarningsPrefix': options.showPackageWarningsPrefix,
     'showSdkWarnings': options.showSdkWarnings,
     'definedVariables': options.definedVariables,
     'packageRootPath': options.packageRootPath,
@@ -89,6 +92,9 @@
     'options': optionsJson,
     'totalElapsedTime': totalTime,
     'totalTaskTime': totalTaskTime,
+    'analyzedFiles': analyzedFileCount,
+    'generatedDiagnostics': stats.unfilteredCount,
+    'reportedDiagnostics': stats.filteredCount,
     'performanceTags': perfTagsJson,
     'tasks': taskRows.map((r) => r.toJson()).toList(),
   };
diff --git a/pkg/analyzer_cli/test/all.dart b/pkg/analyzer_cli/test/all.dart
index 9f08563..1fd1dd7 100644
--- a/pkg/analyzer_cli/test/all.dart
+++ b/pkg/analyzer_cli/test/all.dart
@@ -6,6 +6,7 @@
 import 'driver_test.dart' as driver;
 import 'error_test.dart' as error;
 import 'options_test.dart' as options;
+import 'package_prefix_test.dart' as package_prefix;
 import 'perf_report_test.dart' as perf;
 import 'plugin_manager_test.dart' as plugin_manager;
 import 'reporter_test.dart' as reporter;
@@ -26,4 +27,5 @@
   plugin_manager.main();
   reporter.main();
   super_mixin.main();
+  package_prefix.main();
 }
diff --git a/pkg/analyzer_cli/test/data/package_prefix/main.dart b/pkg/analyzer_cli/test/data/package_prefix/main.dart
new file mode 100644
index 0000000..4f1f313
--- /dev/null
+++ b/pkg/analyzer_cli/test/data/package_prefix/main.dart
@@ -0,0 +1,14 @@
+// Test data for package_prefix_test.dart
+//
+// To test manually:
+//
+// This should show a hint about an unused import in foo:
+// dart ../../../bin/analyzer.dart --packages=packagelist \
+//   --x-package-warnings-prefix=f main.dart
+
+import "package:foo/foo.dart";
+import "package:bar/bar.dart";
+
+main() {
+  print("$foo$bar");
+}
diff --git a/pkg/analyzer_cli/test/data/package_prefix/packagelist b/pkg/analyzer_cli/test/data/package_prefix/packagelist
new file mode 100644
index 0000000..85a25f7
--- /dev/null
+++ b/pkg/analyzer_cli/test/data/package_prefix/packagelist
@@ -0,0 +1,2 @@
+bar:pkg/bar/
+foo:pkg/foo/
diff --git a/pkg/analyzer_cli/test/data/package_prefix/pkg/bar/bar.dart b/pkg/analyzer_cli/test/data/package_prefix/pkg/bar/bar.dart
new file mode 100644
index 0000000..0890e0a
--- /dev/null
+++ b/pkg/analyzer_cli/test/data/package_prefix/pkg/bar/bar.dart
@@ -0,0 +1,3 @@
+import "dart:async"; // should trigger unused import
+
+var bar = "bar";
diff --git a/pkg/analyzer_cli/test/data/package_prefix/pkg/foo/foo.dart b/pkg/analyzer_cli/test/data/package_prefix/pkg/foo/foo.dart
new file mode 100644
index 0000000..ee511f5
--- /dev/null
+++ b/pkg/analyzer_cli/test/data/package_prefix/pkg/foo/foo.dart
@@ -0,0 +1,3 @@
+import "dart:async"; // should trigger unused import
+
+var foo = "foo";
diff --git a/pkg/analyzer_cli/test/package_prefix_test.dart b/pkg/analyzer_cli/test/package_prefix_test.dart
new file mode 100644
index 0000000..1ba203f
--- /dev/null
+++ b/pkg/analyzer_cli/test/package_prefix_test.dart
@@ -0,0 +1,73 @@
+import 'dart:io' show exitCode;
+
+import 'package:analyzer_cli/src/driver.dart' show Driver, outSink, errorSink;
+import 'package:analyzer_cli/src/options.dart' show ExitHandler, exitHandler;
+import 'package:unittest/unittest.dart';
+
+import 'utils.dart' show testDirectory;
+
+main() {
+  group('--x-package-warnings-prefix', () {
+    _Runner runner;
+
+    setUp(() {
+      runner = new _Runner.setUp();
+    });
+
+    tearDown(() {
+      runner.tearDown();
+      runner = null;
+    });
+
+    test('shows only the hint whose package matches the prefix', () {
+      runner.run([
+        "--packages",
+        "$testDirectory/data/package_prefix/packagelist",
+        "--x-package-warnings-prefix=f",
+        "$testDirectory/data/package_prefix/main.dart"
+      ]);
+      print("ran it");
+      expect(runner.stdout, contains('1 hint found'));
+      expect(runner.stdout, contains('Unused import'));
+      expect(runner.stdout, contains('package_prefix/pkg/foo/foo.dart'));
+      expect(runner.stdout, isNot(contains('bar.dart')));
+    });
+  });
+}
+
+class _Runner {
+  final _stdout = new StringBuffer();
+  final _stderr = new StringBuffer();
+
+  final StringSink _savedOutSink;
+  final StringSink _savedErrorSink;
+  final int _savedExitCode;
+  final ExitHandler _savedExitHandler;
+
+  _Runner.setUp()
+      : _savedOutSink = outSink,
+        _savedErrorSink = errorSink,
+        _savedExitHandler = exitHandler,
+        _savedExitCode = exitCode {
+    outSink = _stdout;
+    errorSink = _stderr;
+    exitHandler = (_) {};
+  }
+
+  void run(List<String> args) {
+    new Driver().start(args);
+    if (stderr.isNotEmpty) {
+      fail("Unexpected output to stderr:\n$stderr");
+    }
+  }
+
+  String get stdout => _stdout.toString();
+  String get stderr => _stderr.toString();
+
+  void tearDown() {
+    outSink = _savedOutSink;
+    errorSink = _savedErrorSink;
+    exitCode = _savedExitCode;
+    exitHandler = _savedExitHandler;
+  }
+}
diff --git a/pkg/analyzer_cli/test/perf_report_test.dart b/pkg/analyzer_cli/test/perf_report_test.dart
index f668485..19d91a1 100644
--- a/pkg/analyzer_cli/test/perf_report_test.dart
+++ b/pkg/analyzer_cli/test/perf_report_test.dart
@@ -6,6 +6,7 @@
 
 import 'dart:convert' show JSON;
 
+import 'package:analyzer_cli/src/error_formatter.dart' show AnalysisStats;
 import 'package:analyzer_cli/src/options.dart';
 import 'package:analyzer_cli/src/perf_report.dart';
 import 'package:unittest/unittest.dart';
@@ -13,7 +14,7 @@
 main() {
   test('makePerfReport', () {
     var options = CommandLineOptions.parse(["somefile.dart"]);
-    var encoded = makePerfReport(1000, 1234, options);
+    var encoded = makePerfReport(1000, 1234, options, 0, new AnalysisStats());
 
     var json = JSON.decode(encoded);
     expect(json['totalElapsedTime'], 234);
diff --git a/pkg/analyzer_cli/test/reporter_test.dart b/pkg/analyzer_cli/test/reporter_test.dart
index 94b0896..3a0853b 100644
--- a/pkg/analyzer_cli/test/reporter_test.dart
+++ b/pkg/analyzer_cli/test/reporter_test.dart
@@ -14,7 +14,9 @@
 main() {
   group('reporter', () {
     var out = new StringBuffer();
+    var stats = new AnalysisStats();
 
+    setUp(() => stats.init());
     tearDown(() => out.clear());
 
     // Options
@@ -23,28 +25,32 @@
     when(options.hintsAreFatal).thenReturn(false);
     when(options.machineFormat).thenReturn(false);
 
-    var reporter = new ErrorFormatter(out, options);
+    var reporter = new ErrorFormatter(out, options, stats);
 
     test('error', () {
       var error = mockError(ErrorType.SYNTACTIC_ERROR, ErrorSeverity.ERROR);
       reporter.formatErrors([error]);
 
-      expect(
-          out.toString(),
-          '''[error] MSG (/foo/bar/baz.dart, line 3, col 3)
-1 error found.
-''');
+      expect(out.toString().trim(),
+          '[error] MSG (/foo/bar/baz.dart, line 3, col 3)');
     });
 
     test('hint', () {
       var error = mockError(ErrorType.HINT, ErrorSeverity.INFO);
       reporter.formatErrors([error]);
 
+      expect(out.toString().trim(),
+          '[hint] MSG (/foo/bar/baz.dart, line 3, col 3)');
+    });
+
+    test('stats', () {
+      var error = mockError(ErrorType.HINT, ErrorSeverity.INFO);
+      reporter.formatErrors([error]);
+      stats.print(out);
       expect(
-          out.toString(),
+          out.toString().trim(),
           '''[hint] MSG (/foo/bar/baz.dart, line 3, col 3)
-1 hint found.
-''');
+1 hint found.''');
     });
   });
 }
diff --git a/pkg/compiler/lib/compiler.dart b/pkg/compiler/lib/compiler.dart
index 763dc4a..445e2ca 100644
--- a/pkg/compiler/lib/compiler.dart
+++ b/pkg/compiler/lib/compiler.dart
@@ -115,7 +115,7 @@
      Uri packageConfig,
      PackagesDiscoveryProvider packagesDiscoveryProvider]) {
 
-  new_api.CompilerOptions compilerOptions = new new_api.CompilerOptions(
+  new_api.CompilerOptions compilerOptions = new new_api.CompilerOptions.parse(
       entryPoint: script,
       libraryRoot: libraryRoot,
       packageRoot: packageRoot,
diff --git a/pkg/compiler/lib/compiler_new.dart b/pkg/compiler/lib/compiler_new.dart
index b6c1e4f..fa405da 100644
--- a/pkg/compiler/lib/compiler_new.dart
+++ b/pkg/compiler/lib/compiler_new.dart
@@ -9,6 +9,9 @@
 
 import 'dart:async';
 import 'src/apiimpl.dart';
+import 'src/commandline_options.dart';
+import 'src/diagnostics/diagnostic_listener.dart' show DiagnosticOptions;
+
 import 'compiler.dart' show Diagnostic, PackagesDiscoveryProvider;
 export 'compiler.dart' show Diagnostic, PackagesDiscoveryProvider;
 
@@ -71,8 +74,8 @@
   /// Experimental: [code] gives access to an id for the messages. Currently it
   /// is the [Message] used to create the diagnostic, if available, from which
   /// the [MessageKind] is accessible.
-  void report(var code,
-              Uri uri, int begin, int end, String text, Diagnostic kind);
+  void report(
+      var code, Uri uri, int begin, int end, String text, Diagnostic kind);
 }
 
 /// Information resulting from the compilation.
@@ -92,52 +95,422 @@
 
 /// Object for passing options to the compiler.
 class CompilerOptions {
+  /// The entry point of the application that is being compiled.
   final Uri entryPoint;
+
+  /// Root location where SDK libraries are found.
   final Uri libraryRoot;
+
+  /// Package root location.
+  ///
+  /// If not null then [packageConfig] should be null.
   final Uri packageRoot;
+
+  /// Location of the package configuration file.
+  ///
+  /// If not null then [packageRoot] should be null.
   final Uri packageConfig;
+
+  // TODO(sigmund): Move out of here, maybe to CompilerInput. Options should not
+  // hold code, just configuration options.
   final PackagesDiscoveryProvider packagesDiscoveryProvider;
-  final List<String> options;
+
+  /// Resolved constant "environment" values passed to the compiler via the `-D`
+  /// flags.
   final Map<String, dynamic> environment;
 
-  /// Creates an option object for the compiler.
-  // TODO(johnniwinther): Expand comment when [options] are explicit as named
-  // arguments.
-  factory CompilerOptions(
+  /// Whether we allow mocking compilation of libraries such as dart:io and
+  /// dart:html for unit testing purposes.
+  final bool allowMockCompilation;
+
+  /// Whether the native extension syntax is supported by the frontend.
+  final bool allowNativeExtensions;
+
+  /// Whether to resolve all functions in the program, not just those reachable
+  /// from main. This implies [analyzeOnly] is true as well.
+  final bool analyzeAll;
+
+  /// Whether to disable tree-shaking for the main script. This marks all
+  /// functions in the main script as reachable (not just a function named
+  /// `main`).
+  // TODO(sigmund): rename. The current name seems to indicate that only the
+  // main function is retained, which is the opposite of what this does.
+  final bool analyzeMain;
+
+  /// Whether to run the compiler just for the purpose of analysis. That is, to
+  /// run resolution and type-checking alone, but otherwise do not generate any
+  /// code.
+  final bool analyzeOnly;
+
+  /// Whether to skip analysis of method bodies and field initializers. Implies
+  /// [analyzeOnly].
+  final bool analyzeSignaturesOnly;
+
+  /// ID associated with this sdk build.
+  final String buildId;
+
+  /// Whether there is a build-id available so we can use it on error messages
+  /// and in the emitted output of the compiler.
+  bool get hasBuildId => buildId != _UNDETERMINED_BUILD_ID;
+
+  /// Location where to generate a map containing details of how deferred
+  /// libraries are subdivided.
+  final Uri deferredMapUri;
+
+  /// Whether to disable inlining during the backend optimizations.
+  // TODO(sigmund): negate, so all flags are positive
+  final bool disableInlining;
+
+  /// Several options to configure diagnostic messages.
+  // TODO(sigmund): should we simply embed those options here?
+  final DiagnosticOptions diagnosticOptions;
+
+  /// Whether to disable global type inference.
+  final bool disableTypeInference;
+
+  /// Whether to emit a .json file with a summary of the information used by the
+  /// compiler during optimization. This includes resolution details,
+  /// dependencies between elements, results of type inference, and the output
+  /// code for each function.
+  final bool dumpInfo;
+
+  /// Whether we allow passing an extra argument to `assert`, containing a
+  /// reason for why an assertion fails. (experimental)
+  final bool enableAssertMessage;
+
+  /// Whether to enable the experimental conditional directives feature.
+  final bool enableConditionalDirectives;
+
+  /// Whether the user specified a flag to allow the use of dart:mirrors. This
+  /// silences a warning produced by the compiler.
+  final bool enableExperimentalMirrors;
+
+  /// Whether to enable minification
+  // TODO(sigmund): rename to minify
+  final bool enableMinification;
+
+  /// Whether to model which native classes are live based on annotations on the
+  /// core libraries. If false, all native classes will be included by default.
+  final bool enableNativeLiveTypeAnalysis;
+
+  /// Whether to generate code containing checked-mode assignability checks.
+  final bool enableTypeAssertions;
+
+  /// Whether to generate code containing user's `assert` statements.
+  final bool enableUserAssertions;
+
+  /// Whether to generate output even when there are compile-time errors.
+  final bool generateCodeWithCompileTimeErrors;
+
+  /// Whether to generate a source-map file together with the output program.
+  final bool generateSourceMap;
+
+  /// Whether some values are cached for reuse in incremental compilation.
+  /// Incremental compilation allows calling `Compiler.run` more than once
+  /// (experimental).
+  final bool hasIncrementalSupport;
+
+  /// URI of the main output if the compiler is generating source maps.
+  final Uri outputUri;
+
+  /// Location of the platform configuration file.
+  final Uri platformConfigUri;
+
+  /// Whether to emit URIs in the reflection metadata.
+  final bool preserveUris;
+
+  /// URI where the compiler should generate the output source map file.
+  final Uri sourceMapUri;
+
+  /// The compiler is run from the build bot.
+  final bool testMode;
+
+  /// Whether to trust JS-interop annotations. (experimental)
+  final bool trustJSInteropTypeAnnotations;
+
+  /// Whether to trust primitive types during inference and optimizations.
+  final bool trustPrimitives;
+
+  /// Whether to trust type annotations during inference and optimizations.
+  final bool trustTypeAnnotations;
+
+  /// Whether to generate code compliant with content security policy (CSP).
+  final bool useContentSecurityPolicy;
+
+  /// Use the experimental CPS based backend.
+  final bool useCpsIr;
+
+  /// When obfuscating for minification, whether to use the frequency of a name
+  /// as an heuristic to pick shorter names.
+  final bool useFrequencyNamer;
+
+  /// Whether to use the new source-information implementation for source-maps.
+  /// (experimental)
+  final bool useNewSourceInfo;
+
+  /// Whether the user requested to use the fast startup emitter. The full
+  /// emitter might still be used if the program uses dart:mirrors.
+  final bool useStartupEmitter;
+
+  /// Enable verbose printing during compilation. Includes progress messages
+  /// during each phase and a time-breakdown between phases at the end.
+  final bool verbose;
+
+
+  // -------------------------------------------------
+  // Options for deprecated features
+  // -------------------------------------------------
+  // TODO(sigmund): delete these as we delete the underlying features
+
+  /// Whether to preserve comments while scanning (only use for dart:mirrors).
+  final bool preserveComments;
+
+  /// Whether to emit JavaScript (false enables dart2dart).
+  final bool emitJavaScript;
+
+  /// When using dart2dart, whether to use the multi file format.
+  final bool dart2dartMultiFile;
+
+  /// Strip option used by dart2dart.
+  final List<String> strips;
+
+  /// Create an options object by parsing flags from [options].
+  factory CompilerOptions.parse(
       {Uri entryPoint,
-       Uri libraryRoot,
-       Uri packageRoot,
-       Uri packageConfig,
-       PackagesDiscoveryProvider packagesDiscoveryProvider,
-       List<String> options: const <String>[],
-       Map<String, dynamic> environment: const <String, dynamic>{}}) {
-    if (entryPoint == null) {
-      throw new ArgumentError("entryPoint must be non-null");
-    }
-    if (!libraryRoot.path.endsWith("/")) {
-      throw new ArgumentError("libraryRoot must end with a /");
-    }
-    if (packageRoot != null && !packageRoot.path.endsWith("/")) {
-      throw new ArgumentError("packageRoot must end with a /");
-    }
-    return new CompilerOptions._(
-        entryPoint,
-        libraryRoot,
-        packageRoot,
-        packageConfig,
-        packagesDiscoveryProvider,
-        options,
-        environment);
+      Uri libraryRoot,
+      Uri packageRoot,
+      Uri packageConfig,
+      PackagesDiscoveryProvider packagesDiscoveryProvider,
+      Map<String, dynamic> environment: const <String, dynamic>{},
+      List<String> options}) {
+    return new CompilerOptions(
+        entryPoint: entryPoint,
+        libraryRoot: libraryRoot,
+        packageRoot: packageRoot,
+        packageConfig: packageConfig,
+        packagesDiscoveryProvider: packagesDiscoveryProvider,
+        environment: environment,
+        allowMockCompilation: _hasOption(options, Flags.allowMockCompilation),
+        allowNativeExtensions: _hasOption(options, Flags.allowNativeExtensions),
+        analyzeAll: _hasOption(options, Flags.analyzeAll),
+        analyzeMain: _hasOption(options, Flags.analyzeMain),
+        analyzeOnly: _hasOption(options, Flags.analyzeOnly),
+        analyzeSignaturesOnly: _hasOption(options, Flags.analyzeSignaturesOnly),
+        buildId: _extractStringOption(
+            options, '--build-id=', _UNDETERMINED_BUILD_ID),
+        dart2dartMultiFile: _hasOption(options, '--output-type=dart-multi'),
+        deferredMapUri: _extractUriOption(options, '--deferred-map='),
+        diagnosticOptions: new DiagnosticOptions(
+            suppressWarnings: _hasOption(options, Flags.suppressWarnings),
+            fatalWarnings: _hasOption(options, Flags.fatalWarnings),
+            suppressHints: _hasOption(options, Flags.suppressHints),
+            terseDiagnostics: _hasOption(options, Flags.terse),
+            shownPackageWarnings:
+                _extractOptionalCsvOption(options, Flags.showPackageWarnings)),
+        disableInlining: _hasOption(options, Flags.disableInlining),
+        disableTypeInference: _hasOption(options, Flags.disableTypeInference),
+        dumpInfo: _hasOption(options, Flags.dumpInfo),
+        emitJavaScript: !(_hasOption(options, '--output-type=dart') ||
+            _hasOption(options, '--output-type=dart-multi')),
+        enableAssertMessage: _hasOption(options, Flags.enableAssertMessage),
+        enableConditionalDirectives:
+            _hasOption(options, Flags.conditionalDirectives),
+        enableExperimentalMirrors:
+            _hasOption(options, Flags.enableExperimentalMirrors),
+        enableMinification: _hasOption(options, Flags.minify),
+        enableNativeLiveTypeAnalysis:
+            !_hasOption(options, Flags.disableNativeLiveTypeAnalysis),
+        enableTypeAssertions: _hasOption(options, Flags.enableCheckedMode),
+        enableUserAssertions: _hasOption(options, Flags.enableCheckedMode),
+        generateCodeWithCompileTimeErrors:
+            _hasOption(options, Flags.generateCodeWithCompileTimeErrors),
+        generateSourceMap: !_hasOption(options, Flags.noSourceMaps),
+        hasIncrementalSupport: _forceIncrementalSupport ||
+            _hasOption(options, Flags.incrementalSupport),
+        outputUri: _extractUriOption(options, '--out='),
+        platformConfigUri: _resolvePlatformConfigFromOptions(
+            libraryRoot, options),
+        preserveComments: _hasOption(options, Flags.preserveComments),
+        preserveUris: _hasOption(options, Flags.preserveUris),
+        sourceMapUri: _extractUriOption(options, '--source-map='),
+        strips: _extractCsvOption(options, '--force-strip='),
+        testMode: _hasOption(options, Flags.testMode),
+        trustJSInteropTypeAnnotations:
+            _hasOption(options, Flags.trustJSInteropTypeAnnotations),
+        trustPrimitives: _hasOption(options, Flags.trustPrimitives),
+        trustTypeAnnotations: _hasOption(options, Flags.trustTypeAnnotations),
+        useContentSecurityPolicy:
+            _hasOption(options, Flags.useContentSecurityPolicy),
+        useCpsIr: _hasOption(options, Flags.useCpsIr),
+        useFrequencyNamer:
+            !_hasOption(options, Flags.noFrequencyBasedMinification),
+        useNewSourceInfo: _hasOption(options, Flags.useNewSourceInfo),
+        useStartupEmitter: _hasOption(options, Flags.fastStartup),
+        verbose: _hasOption(options, Flags.verbose));
   }
 
-  CompilerOptions._(
-      this.entryPoint,
-      this.libraryRoot,
-      this.packageRoot,
-      this.packageConfig,
-      this.packagesDiscoveryProvider,
-      this.options,
-      this.environment);
+  /// Creates an option object for the compiler.
+  ///
+  /// This validates and normalizes dependent options to be consistent. For
+  /// example, if [analyzeAll] is true, the resulting options object will also
+  /// have [analyzeOnly] as true.
+  factory CompilerOptions(
+      {Uri entryPoint,
+      Uri libraryRoot,
+      Uri packageRoot,
+      Uri packageConfig,
+      PackagesDiscoveryProvider packagesDiscoveryProvider,
+      Map<String, dynamic> environment: const <String, dynamic>{},
+      bool allowMockCompilation: false,
+      bool allowNativeExtensions: false,
+      bool analyzeAll: false,
+      bool analyzeMain: false,
+      bool analyzeOnly: false,
+      bool analyzeSignaturesOnly: false,
+      String buildId: _UNDETERMINED_BUILD_ID,
+      bool dart2dartMultiFile: false,
+      Uri deferredMapUri: null,
+      DiagnosticOptions diagnosticOptions: const DiagnosticOptions(),
+      bool disableInlining: false,
+      bool disableTypeInference: false,
+      bool dumpInfo: false,
+      bool emitJavaScript: true,
+      bool enableAssertMessage: false,
+      bool enableConditionalDirectives: false,
+      bool enableExperimentalMirrors: false,
+      bool enableMinification: false,
+      bool enableNativeLiveTypeAnalysis: true,
+      bool enableTypeAssertions: false,
+      bool enableUserAssertions: false,
+      bool generateCodeWithCompileTimeErrors: false,
+      bool generateSourceMap: true,
+      bool hasIncrementalSupport: false,
+      Uri outputUri: null,
+      Uri platformConfigUri: null,
+      bool preserveComments: false,
+      bool preserveUris: false,
+      Uri sourceMapUri: null,
+      List<String> strips: const [],
+      bool testMode: false,
+      bool trustJSInteropTypeAnnotations: false,
+      bool trustPrimitives: false,
+      bool trustTypeAnnotations: false,
+      bool useContentSecurityPolicy: false,
+      bool useCpsIr: false,
+      bool useFrequencyNamer: true,
+      bool useNewSourceInfo: false,
+      bool useStartupEmitter: false,
+      bool verbose: false}) {
+    // TODO(sigmund): should entrypoint be here? should we validate it is not
+    // null? In unittests we use the same compiler to analyze or build multiple
+    // entrypoints.
+    if (libraryRoot == null) {
+      throw new ArgumentError("[libraryRoot] is null.");
+    }
+    if (!libraryRoot.path.endsWith("/")) {
+      throw new ArgumentError("[libraryRoot] must end with a /");
+    }
+    if (packageRoot != null && packageConfig != null) {
+      throw new ArgumentError("Only one of [packageRoot] or [packageConfig] "
+          "may be given.");
+    }
+    if (packageRoot != null && !packageRoot.path.endsWith("/")) {
+      throw new ArgumentError("[packageRoot] must end with a /");
+    }
+    if (!analyzeOnly) {
+      if (allowNativeExtensions) {
+        throw new ArgumentError(
+            "${Flags.allowNativeExtensions} is only supported in combination "
+            "with ${Flags.analyzeOnly}");
+      }
+    }
+    return new CompilerOptions._(entryPoint, libraryRoot, packageRoot,
+        packageConfig, packagesDiscoveryProvider, environment,
+        allowMockCompilation: allowMockCompilation,
+        allowNativeExtensions: allowNativeExtensions,
+        analyzeAll: analyzeAll,
+        analyzeMain: analyzeMain,
+        analyzeOnly: analyzeOnly || analyzeSignaturesOnly || analyzeAll,
+        analyzeSignaturesOnly: analyzeSignaturesOnly,
+        buildId: buildId,
+        dart2dartMultiFile: dart2dartMultiFile,
+        deferredMapUri: deferredMapUri,
+        diagnosticOptions: diagnosticOptions,
+        disableInlining: disableInlining || hasIncrementalSupport,
+        disableTypeInference: disableTypeInference || !emitJavaScript,
+        dumpInfo: dumpInfo,
+        emitJavaScript: emitJavaScript,
+        enableAssertMessage: enableAssertMessage,
+        enableConditionalDirectives: enableConditionalDirectives,
+        enableExperimentalMirrors: enableExperimentalMirrors,
+        enableMinification: enableMinification,
+        enableNativeLiveTypeAnalysis: enableNativeLiveTypeAnalysis,
+        enableTypeAssertions: enableTypeAssertions,
+        enableUserAssertions: enableUserAssertions,
+        generateCodeWithCompileTimeErrors: generateCodeWithCompileTimeErrors,
+        generateSourceMap: generateSourceMap,
+        hasIncrementalSupport: hasIncrementalSupport,
+        outputUri: outputUri,
+        platformConfigUri: platformConfigUri ?? _resolvePlatformConfig(
+           libraryRoot, null, !emitJavaScript, const []),
+        preserveComments: preserveComments,
+        preserveUris: preserveUris,
+        sourceMapUri: sourceMapUri,
+        strips: strips,
+        testMode: testMode,
+        trustJSInteropTypeAnnotations: trustJSInteropTypeAnnotations,
+        trustPrimitives: trustPrimitives,
+        trustTypeAnnotations: trustTypeAnnotations,
+        useContentSecurityPolicy: useContentSecurityPolicy,
+        useCpsIr: useCpsIr,
+        useFrequencyNamer: useFrequencyNamer,
+        useNewSourceInfo: useNewSourceInfo,
+        useStartupEmitter: useStartupEmitter,
+        verbose: verbose);
+  }
+
+  CompilerOptions._(this.entryPoint, this.libraryRoot, this.packageRoot,
+      this.packageConfig, this.packagesDiscoveryProvider, this.environment,
+      {this.allowMockCompilation: false,
+      this.allowNativeExtensions: false,
+      this.analyzeAll: false,
+      this.analyzeMain: false,
+      this.analyzeOnly: false,
+      this.analyzeSignaturesOnly: false,
+      this.buildId: _UNDETERMINED_BUILD_ID,
+      this.dart2dartMultiFile: false,
+      this.deferredMapUri: null,
+      this.diagnosticOptions: null,
+      this.disableInlining: false,
+      this.disableTypeInference: false,
+      this.dumpInfo: false,
+      this.emitJavaScript: true,
+      this.enableAssertMessage: false,
+      this.enableConditionalDirectives: false,
+      this.enableExperimentalMirrors: false,
+      this.enableMinification: false,
+      this.enableNativeLiveTypeAnalysis: false,
+      this.enableTypeAssertions: false,
+      this.enableUserAssertions: false,
+      this.generateCodeWithCompileTimeErrors: false,
+      this.generateSourceMap: true,
+      this.hasIncrementalSupport: false,
+      this.outputUri: null,
+      this.platformConfigUri: null,
+      this.preserveComments: false,
+      this.preserveUris: false,
+      this.sourceMapUri: null,
+      this.strips: const [],
+      this.testMode: false,
+      this.trustJSInteropTypeAnnotations: false,
+      this.trustPrimitives: false,
+      this.trustTypeAnnotations: false,
+      this.useContentSecurityPolicy: false,
+      this.useCpsIr: false,
+      this.useFrequencyNamer: false,
+      this.useNewSourceInfo: false,
+      this.useStartupEmitter: false,
+      this.verbose: false});
 }
 
 /// Returns a future that completes to a [CompilationResult] when the Dart
@@ -154,7 +527,6 @@
     CompilerInput compilerInput,
     CompilerDiagnostics compilerDiagnostics,
     CompilerOutput compilerOutput) {
-
   if (compilerOptions == null) {
     throw new ArgumentError("compilerOptions must be non-null");
   }
@@ -169,16 +541,92 @@
   }
 
   CompilerImpl compiler = new CompilerImpl(
-      compilerInput,
-      compilerOutput,
-      compilerDiagnostics,
-      compilerOptions.libraryRoot,
-      compilerOptions.packageRoot,
-      compilerOptions.options,
-      compilerOptions.environment,
-      compilerOptions.packageConfig,
-      compilerOptions.packagesDiscoveryProvider);
+      compilerInput, compilerOutput, compilerDiagnostics, compilerOptions);
   return compiler.run(compilerOptions.entryPoint).then((bool success) {
     return new CompilationResult(compiler, isSuccess: success);
   });
 }
+
+String _extractStringOption(
+    List<String> options, String prefix, String defaultValue) {
+  for (String option in options) {
+    if (option.startsWith(prefix)) {
+      return option.substring(prefix.length);
+    }
+  }
+  return defaultValue;
+}
+
+Uri _extractUriOption(List<String> options, String prefix) {
+  var option = _extractStringOption(options, prefix, null);
+  return (option == null) ? null : Uri.parse(option);
+}
+
+// CSV: Comma separated values.
+List<String> _extractCsvOption(List<String> options, String prefix) {
+  for (String option in options) {
+    if (option.startsWith(prefix)) {
+      return option.substring(prefix.length).split(',');
+    }
+  }
+  return const <String>[];
+}
+
+/// Extract list of comma separated values provided for [flag]. Returns an
+/// empty list if [option] contain [flag] without arguments. Returns `null` if
+/// [option] doesn't contain [flag] with or without arguments.
+List<String> _extractOptionalCsvOption(List<String> options, String flag) {
+  String prefix = '$flag=';
+  for (String option in options) {
+    if (option == flag) {
+      return const <String>[];
+    }
+    if (option.startsWith(flag)) {
+      return option.substring(prefix.length).split(',');
+    }
+  }
+  return null;
+}
+
+Uri _resolvePlatformConfigFromOptions(Uri libraryRoot, List<String> options) {
+  return _resolvePlatformConfig(libraryRoot,
+      _extractStringOption(options, "--platform-config=", null),
+      _hasOption(options, '--output-type=dart'),
+      _extractCsvOption(options, '--categories='));
+}
+
+Uri _resolvePlatformConfig(Uri libraryRoot,
+    String platformConfigPath, bool isDart2Dart, Iterable<String> categories) {
+  if (platformConfigPath != null) {
+    return libraryRoot.resolve(platformConfigPath);
+  } else if (isDart2Dart) {
+    return libraryRoot.resolve(_dart2dartPlatform);
+  } else {
+    if (categories.length == 0) {
+      return libraryRoot.resolve(_clientPlatform);
+    }
+    assert(categories.length <= 2);
+    if (categories.contains("Client")) {
+      if (categories.contains("Server")) {
+        return libraryRoot.resolve(_sharedPlatform);
+      }
+      return libraryRoot.resolve(_clientPlatform);
+    }
+    assert(categories.contains("Server"));
+    return libraryRoot.resolve(_serverPlatform);
+  }
+}
+
+bool _hasOption(List<String> options, String option) {
+  return options.indexOf(option) >= 0;
+}
+
+/// Locations of the platform descriptor files relative to the library root.
+const String _clientPlatform = "lib/dart_client.platform";
+const String _serverPlatform = "lib/dart_server.platform";
+const String _sharedPlatform = "lib/dart_shared.platform";
+const String _dart2dartPlatform = "lib/dart2dart.platform";
+
+const String _UNDETERMINED_BUILD_ID = "build number could not be determined";
+const bool _forceIncrementalSupport =
+    const bool.fromEnvironment('DART2JS_EXPERIMENTAL_INCREMENTAL_SUPPORT');
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index 31ce5a8..42eda64 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -30,9 +30,6 @@
 import 'platform_configuration.dart' as platform_configuration;
 import 'script.dart';
 
-const bool forceIncrementalSupport =
-    const bool.fromEnvironment('DART2JS_EXPERIMENTAL_INCREMENTAL_SUPPORT');
-
 /// For every 'dart:' library, a corresponding environment variable is set
 /// to "true". The environment variable's name is the concatenation of
 /// this prefix and the name (without the 'dart:'.
@@ -41,24 +38,13 @@
 /// to "true".
 const String dartLibraryEnvironmentPrefix = 'dart.library.';
 
-/// Locations of the platform descriptor files relative to the library root.
-const String _clientPlatform = "lib/dart_client.platform";
-const String _serverPlatform = "lib/dart_server.platform";
-const String _sharedPlatform = "lib/dart_shared.platform";
-const String _dart2dartPlatform = "lib/dart2dart.platform";
 
 /// Implements the [Compiler] using a [api.CompilerInput] for supplying the
 /// sources.
 class CompilerImpl extends Compiler {
   api.CompilerInput provider;
   api.CompilerDiagnostics handler;
-  final Uri platformConfigUri;
-  final Uri packageConfig;
-  final Uri packageRoot;
-  final api.PackagesDiscoveryProvider packagesDiscoveryProvider;
   Packages packages;
-  List<String> options;
-  Map<String, dynamic> environment;
   bool mockableLibraryUsed = false;
 
   /// A mapping of the dart: library-names to their location.
@@ -70,181 +56,19 @@
   GenericTask userProviderTask;
   GenericTask userPackagesDiscoveryTask;
 
-  Uri get libraryRoot => platformConfigUri.resolve(".");
+  Uri get libraryRoot => options.platformConfigUri.resolve(".");
 
-  CompilerImpl(this.provider,
-           api.CompilerOutput outputProvider,
-           this.handler,
-           Uri libraryRoot,
-           this.packageRoot,
-           List<String> options,
-           this.environment,
-           [this.packageConfig,
-            this.packagesDiscoveryProvider])
-      : this.options = options,
-        this.platformConfigUri = resolvePlatformConfig(libraryRoot, options),
-        super(
-            outputProvider: outputProvider,
-            enableTypeAssertions: hasOption(options, Flags.enableCheckedMode),
-            enableUserAssertions: hasOption(options, Flags.enableCheckedMode),
-            trustTypeAnnotations:
-                hasOption(options, Flags.trustTypeAnnotations),
-            trustPrimitives:
-                hasOption(options, Flags.trustPrimitives),
-            trustJSInteropTypeAnnotations:
-                hasOption(options, Flags.trustJSInteropTypeAnnotations),
-            enableMinification: hasOption(options, Flags.minify),
-            useFrequencyNamer:
-                !hasOption(options, Flags.noFrequencyBasedMinification),
-            preserveUris: hasOption(options, Flags.preserveUris),
-            enableNativeLiveTypeAnalysis:
-                !hasOption(options, Flags.disableNativeLiveTypeAnalysis),
-            emitJavaScript: !(hasOption(options, '--output-type=dart') ||
-                              hasOption(options, '--output-type=dart-multi')),
-            dart2dartMultiFile: hasOption(options, '--output-type=dart-multi'),
-            generateSourceMap: !hasOption(options, Flags.noSourceMaps),
-            analyzeAllFlag: hasOption(options, Flags.analyzeAll),
-            analyzeOnly: hasOption(options, Flags.analyzeOnly),
-            analyzeMain: hasOption(options, Flags.analyzeMain),
-            analyzeSignaturesOnly:
-                hasOption(options, Flags.analyzeSignaturesOnly),
-            strips: extractCsvOption(options, '--force-strip='),
-            disableTypeInferenceFlag:
-                hasOption(options, Flags.disableTypeInference),
-            preserveComments: hasOption(options, Flags.preserveComments),
-            useCpsIr: hasOption(options, Flags.useCpsIr),
-            verbose: hasOption(options, Flags.verbose),
-            sourceMapUri: extractUriOption(options, '--source-map='),
-            outputUri: extractUriOption(options, '--out='),
-            deferredMapUri: extractUriOption(options, '--deferred-map='),
-            dumpInfo: hasOption(options, Flags.dumpInfo),
-            buildId: extractStringOption(
-                options, '--build-id=',
-                "build number could not be determined"),
-            useContentSecurityPolicy:
-              hasOption(options, Flags.useContentSecurityPolicy),
-            useStartupEmitter: hasOption(options, Flags.fastStartup),
-            enableConditionalDirectives:
-                hasOption(options, Flags.conditionalDirectives),
-            useNewSourceInfo: hasOption(options, Flags.useNewSourceInfo),
-            hasIncrementalSupport:
-                forceIncrementalSupport ||
-                hasOption(options, Flags.incrementalSupport),
-            diagnosticOptions: new DiagnosticOptions(
-                suppressWarnings: hasOption(options, Flags.suppressWarnings),
-                fatalWarnings: hasOption(options, Flags.fatalWarnings),
-                suppressHints: hasOption(options, Flags.suppressHints),
-                terseDiagnostics: hasOption(options, Flags.terse),
-                shownPackageWarnings: extractOptionalCsvOption(
-                      options, Flags.showPackageWarnings)),
-            enableExperimentalMirrors:
-                hasOption(options, Flags.enableExperimentalMirrors),
-            enableAssertMessage:
-                hasOption(options, Flags.enableAssertMessage),
-            generateCodeWithCompileTimeErrors:
-                hasOption(options, Flags.generateCodeWithCompileTimeErrors),
-            testMode: hasOption(options, Flags.testMode),
-            allowNativeExtensions:
-                hasOption(options, Flags.allowNativeExtensions)) {
+  CompilerImpl(this.provider, api.CompilerOutput outputProvider,
+      this.handler, api.CompilerOptions options)
+      : super(options: options, outputProvider: outputProvider) {
     tasks.addAll([
         userHandlerTask = new GenericTask('Diagnostic handler', this),
         userProviderTask = new GenericTask('Input provider', this),
         userPackagesDiscoveryTask =
             new GenericTask('Package discovery', this),
     ]);
-    if (libraryRoot == null) {
-      throw new ArgumentError("[libraryRoot] is null.");
-    }
-    if (!libraryRoot.path.endsWith("/")) {
-      throw new ArgumentError("[libraryRoot] must end with a /.");
-    }
-    if (packageRoot != null && packageConfig != null) {
-      throw new ArgumentError("Only one of [packageRoot] or [packageConfig] "
-                              "may be given.");
-    }
-    if (packageRoot != null && !packageRoot.path.endsWith("/")) {
-      throw new ArgumentError("[packageRoot] must end with a /.");
-    }
-    if (!analyzeOnly) {
-      if (allowNativeExtensions) {
-        throw new ArgumentError(
-            "${Flags.allowNativeExtensions} is only supported in combination "
-            "with ${Flags.analyzeOnly}");
-      }
-    }
   }
 
-  static String extractStringOption(List<String> options,
-                                    String prefix,
-                                    String defaultValue) {
-    for (String option in options) {
-      if (option.startsWith(prefix)) {
-        return option.substring(prefix.length);
-      }
-    }
-    return defaultValue;
-  }
-
-  static Uri extractUriOption(List<String> options, String prefix) {
-    var option = extractStringOption(options, prefix, null);
-    return (option == null) ? null : Uri.parse(option);
-  }
-
-  // CSV: Comma separated values.
-  static List<String> extractCsvOption(List<String> options, String prefix) {
-    for (String option in options) {
-      if (option.startsWith(prefix)) {
-        return option.substring(prefix.length).split(',');
-      }
-    }
-    return const <String>[];
-  }
-
-  /// Extract list of comma separated values provided for [flag]. Returns an
-  /// empty list if [option] contain [flag] without arguments. Returns `null` if
-  /// [option] doesn't contain [flag] with or without arguments.
-  static List<String> extractOptionalCsvOption(
-      List<String> options, String flag) {
-    String prefix = '$flag=';
-    for (String option in options) {
-      if (option == flag) {
-        return const <String>[];
-      }
-      if (option.startsWith(flag)) {
-        return option.substring(prefix.length).split(',');
-      }
-    }
-    return null;
-  }
-
-  static Uri resolvePlatformConfig(Uri libraryRoot,
-                                   List<String> options) {
-    String platformConfigPath =
-        extractStringOption(options, "--platform-config=", null);
-    if (platformConfigPath != null) {
-      return libraryRoot.resolve(platformConfigPath);
-    } else if (hasOption(options, '--output-type=dart')) {
-      return libraryRoot.resolve(_dart2dartPlatform);
-    } else {
-      Iterable<String> categories = extractCsvOption(options, '--categories=');
-      if (categories.length == 0) {
-        return libraryRoot.resolve(_clientPlatform);
-      }
-      assert(categories.length <= 2);
-      if (categories.contains("Client")) {
-        if (categories.contains("Server")) {
-          return libraryRoot.resolve(_sharedPlatform);
-        }
-        return libraryRoot.resolve(_clientPlatform);
-      }
-      assert(categories.contains("Server"));
-      return libraryRoot.resolve(_serverPlatform);
-    }
-  }
-
-  static bool hasOption(List<String> options, String option) {
-    return options.indexOf(option) >= 0;
-  }
 
   void log(message) {
     callUserHandler(
@@ -293,7 +117,7 @@
     Uri resourceUri = translateUri(node, readableUri);
     if (resourceUri == null) return synthesizeScript(node, readableUri);
     if (resourceUri.scheme == 'dart-ext') {
-      if (!allowNativeExtensions) {
+      if (!options.allowNativeExtensions) {
         reporter.withCurrentElement(element, () {
           reporter.reportErrorMessage(
               node, MessageKind.DART_EXT_NOT_SUPPORTED);
@@ -350,8 +174,8 @@
   }
 
   /// Translates "resolvedUri" with scheme "dart" to a [uri] resolved relative
-  /// to [platformConfigUri] according to the information in the file at
-  /// [platformConfigUri].
+  /// 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].
@@ -451,33 +275,32 @@
   }
 
   Future setupPackages(Uri uri) {
-    if (packageRoot != null) {
+    if (options.packageRoot != null) {
       // Use "non-file" packages because the file version requires a [Directory]
       // and we can't depend on 'dart:io' classes.
-      packages = new NonFilePackagesDirectoryPackages(packageRoot);
-    } else if (packageConfig != null) {
-      return callUserProvider(packageConfig).then((packageConfigContents) {
-        if (packageConfigContents is String) {
-          packageConfigContents = UTF8.encode(packageConfigContents);
+      packages = new NonFilePackagesDirectoryPackages(options.packageRoot);
+    } else if (options.packageConfig != null) {
+      return callUserProvider(options.packageConfig).then((configContents) {
+        if (configContents is String) {
+          configContents = UTF8.encode(configContents);
         }
         // The input provider may put a trailing 0 byte when it reads a source
         // file, which confuses the package config parser.
-        if (packageConfigContents.length > 0 &&
-            packageConfigContents.last == 0) {
-          packageConfigContents = packageConfigContents.sublist(
-              0, packageConfigContents.length - 1);
+        if (configContents.length > 0 &&
+            configContents.last == 0) {
+          configContents = configContents.sublist(0, configContents.length - 1);
         }
-        packages =
-            new MapPackages(pkgs.parse(packageConfigContents, packageConfig));
+        packages = new MapPackages(
+            pkgs.parse(configContents, options.packageConfig));
       }).catchError((error) {
         reporter.reportErrorMessage(
             NO_LOCATION_SPANNABLE,
             MessageKind.INVALID_PACKAGE_CONFIG,
-            {'uri': packageConfig, 'exception': error});
+            {'uri': options.packageConfig, 'exception': error});
         packages = Packages.noPackages;
       });
     } else {
-      if (packagesDiscoveryProvider == null) {
+      if (options.packagesDiscoveryProvider == null) {
         packages = Packages.noPackages;
       } else {
         return callUserPackagesDiscovery(uri).then((p) {
@@ -490,7 +313,7 @@
 
   Future<Null> setupSdk() {
     if (sdkLibraries == null) {
-      return platform_configuration.load(platformConfigUri, provider)
+      return platform_configuration.load(options.platformConfigUri, provider)
           .then((Map<String, Uri> mapping) {
         sdkLibraries = mapping;
       });
@@ -502,7 +325,7 @@
   }
 
   Future<bool> run(Uri uri) {
-    log('Using platform configuration at ${platformConfigUri}');
+    log('Using platform configuration at ${options.platformConfigUri}');
 
     return Future.wait([setupSdk(), setupPackages(uri)]).then((_) {
       assert(sdkLibraries != null);
@@ -552,10 +375,8 @@
     }
   }
 
-  bool get isMockCompilation {
-    return mockableLibraryUsed
-      && (options.indexOf(Flags.allowMockCompilation) != -1);
-  }
+  bool get isMockCompilation =>
+      mockableLibraryUsed && options.allowMockCompilation;
 
   void callUserHandler(Message message, Uri uri, int begin, int end,
                        String text, api.Diagnostic kind) {
@@ -582,7 +403,7 @@
   Future<Packages> callUserPackagesDiscovery(Uri uri) {
     try {
       return userPackagesDiscoveryTask.measure(
-                 () => packagesDiscoveryProvider(uri));
+                 () => options.packagesDiscoveryProvider(uri));
     } catch (ex, s) {
       diagnoseCrashInUserCode('Uncaught exception in package discovery', ex, s);
       rethrow;
@@ -593,8 +414,8 @@
     assert(invariant(NO_LOCATION_SPANNABLE,
         sdkLibraries != null, message: "setupSdk() has not been run"));
 
-    var result = environment[name];
-    if (result != null || environment.containsKey(name)) return result;
+    var result = options.environment[name];
+    if (result != null || options.environment.containsKey(name)) return result;
     if (!name.startsWith(dartLibraryEnvironmentPrefix)) return null;
 
     String libraryName = name.substring(dartLibraryEnvironmentPrefix.length);
@@ -621,6 +442,6 @@
   }
 
   Uri resolvePatchUri(String libraryName) {
-    return backend.resolvePatchUri(libraryName, platformConfigUri);
+    return backend.resolvePatchUri(libraryName, options.platformConfigUri);
   }
 }
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index d015b7c..bb51679 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -743,7 +743,7 @@
     // TODO(karlklose,johnniwinther): if the type is null, the annotation is
     // from a parameter which has been analyzed before the method has been
     // resolved and the result has been thrown away.
-    if (compiler.enableTypeAssertions && type != null &&
+    if (compiler.options.enableTypeAssertions && type != null &&
         type.containsTypeVariables) {
       if (insideClosure && member.isFactoryConstructor) {
         // This is a closure in a factory constructor.  Since there is no
@@ -813,7 +813,7 @@
     Element element = elements[node];
     if (Elements.isLocal(element)) {
       mutatedVariables.add(element);
-      if (compiler.enableTypeAssertions) {
+      if (compiler.options.enableTypeAssertions) {
         TypedElement typedElement = element;
         analyzeTypeVariables(typedElement.type);
       }
@@ -1065,7 +1065,7 @@
       // escape the potential type variables used in that closure.
       if (element is FunctionElement &&
           (compiler.backend.methodNeedsRti(element) ||
-           compiler.enableTypeAssertions)) {
+           compiler.options.enableTypeAssertions)) {
         analyzeTypeVariables(type);
       }
 
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 6223f3b..1997d1c 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -12,6 +12,7 @@
   static const String analyzeMain = '--analyze-main';
   static const String analyzeOnly = '--analyze-only';
   static const String analyzeSignaturesOnly = '--analyze-signatures-only';
+  static const String disableInlining = '--disable-inlining';
   static const String disableDiagnosticColors = '--disable-diagnostic-colors';
   static const String disableNativeLiveTypeAnalysis =
       '--disable-native-live-type-analysis';
diff --git a/pkg/compiler/lib/src/common/backend_api.dart b/pkg/compiler/lib/src/common/backend_api.dart
index 3063616..d7af0cb 100644
--- a/pkg/compiler/lib/src/common/backend_api.dart
+++ b/pkg/compiler/lib/src/common/backend_api.dart
@@ -55,6 +55,11 @@
     checkNativeAnnotation, checkJsInteropAnnotation;
 import '../resolution/tree_elements.dart' show
     TreeElements;
+import '../serialization/serialization.dart' show
+    DeserializerPlugin,
+    ObjectDecoder,
+    ObjectEncoder,
+    SerializerPlugin;
 import '../tree/tree.dart' show
     Node,
     Send;
@@ -102,6 +107,9 @@
     return const SourceInformationStrategy();
   }
 
+  /// Interface for serialization of backend specific data.
+  BackendSerialization get serialization => const BackendSerialization();
+
   // TODO(johnniwinther): Move this to the JavaScriptBackend.
   String get patchVersion => null;
 
@@ -430,7 +438,8 @@
   /// Creates an impact strategy to use for compilation.
   ImpactStrategy createImpactStrategy(
       {bool supportDeferredLoad: true,
-       bool supportDumpInfo: true}) {
+       bool supportDumpInfo: true,
+       bool supportSerialization: true}) {
     return const ImpactStrategy();
   }
 }
@@ -462,3 +471,11 @@
     return worldImpact;
   }
 }
+
+/// Interface for serialization of backend specific data.
+class BackendSerialization  {
+  const BackendSerialization();
+
+  SerializerPlugin get serializer => const SerializerPlugin();
+  DeserializerPlugin get deserializer => const DeserializerPlugin();
+}
diff --git a/pkg/compiler/lib/src/common/resolution.dart b/pkg/compiler/lib/src/common/resolution.dart
index e422ef8..ce82723 100644
--- a/pkg/compiler/lib/src/common/resolution.dart
+++ b/pkg/compiler/lib/src/common/resolution.dart
@@ -187,6 +187,9 @@
 
   bool hasBeenResolved(Element element);
 
+  ResolutionWorkItem createWorkItem(
+      Element element, ItemCompilationContext compilationContext);
+
   /// Returns the precomputed [WorldImpact] for [element].
   WorldImpact getWorldImpact(Element element);
 
diff --git a/pkg/compiler/lib/src/common/tasks.dart b/pkg/compiler/lib/src/common/tasks.dart
index 737c2a9..1088363 100644
--- a/pkg/compiler/lib/src/common/tasks.dart
+++ b/pkg/compiler/lib/src/common/tasks.dart
@@ -30,7 +30,7 @@
 
   CompilerTask(Compiler compiler)
       : this.compiler = compiler,
-        watch = (compiler.verbose) ? new Stopwatch() : null;
+        watch = (compiler.options.verbose) ? new Stopwatch() : null;
 
   DiagnosticReporter get reporter => compiler.reporter;
 
diff --git a/pkg/compiler/lib/src/compile_time_constants.dart b/pkg/compiler/lib/src/compile_time_constants.dart
index d633e6b..1eabdf3 100644
--- a/pkg/compiler/lib/src/compile_time_constants.dart
+++ b/pkg/compiler/lib/src/compile_time_constants.dart
@@ -243,7 +243,7 @@
     } else {
       expression = compileNodeWithDefinitions(initializer, definitions,
           isConst: isConst);
-      if (compiler.enableTypeAssertions &&
+      if (compiler.options.enableTypeAssertions &&
           checkType &&
           expression != null &&
           element.isField) {
@@ -1079,7 +1079,7 @@
   }
 
   void potentiallyCheckType(TypedElement element, AstConstant constant) {
-    if (compiler.enableTypeAssertions) {
+    if (compiler.options.enableTypeAssertions) {
       DartType elementType = element.type.substByContext(constructedType);
       DartType constantType = constant.value.getType(coreTypes);
       if (!constantSystem.isSubtype(
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 9bfb7eb..3152635 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -34,6 +34,7 @@
     CompilerTask,
     GenericTask;
 import 'common/work.dart' show
+    ItemCompilationContext,
     WorkItem;
 import 'compile_time_constants.dart';
 import 'constants/values.dart';
@@ -184,42 +185,8 @@
   final Registry mirrorDependencies =
       new ResolutionRegistry(null, new TreeElementMapping(null));
 
-  final bool enableMinification;
-
-  final bool useFrequencyNamer;
-
-  /// When `true` emits URIs in the reflection metadata.
-  final bool preserveUris;
-
-  final bool enableTypeAssertions;
-  final bool enableUserAssertions;
-  final bool trustTypeAnnotations;
-  final bool trustPrimitives;
-  final bool trustJSInteropTypeAnnotations;
-  final bool disableTypeInferenceFlag;
-  final Uri deferredMapUri;
-  final bool dumpInfo;
-  final bool useContentSecurityPolicy;
-  final bool enableExperimentalMirrors;
-  final bool enableAssertMessage;
-
-  /**
-   * The maximum size of a concrete type before it widens to dynamic during
-   * concrete type inference.
-   */
-  final int maxConcreteTypeSize;
-  final bool analyzeAllFlag;
-  final bool analyzeOnly;
-
-  /// If true, disable tree-shaking for the main script.
-  final bool analyzeMain;
-
-  /**
-   * If true, skip analysis of method bodies and field initializers. Implies
-   * [analyzeOnly].
-   */
-  final bool analyzeSignaturesOnly;
-  final bool enableNativeLiveTypeAnalysis;
+  /// Options provided from command-line arguments.
+  final api.CompilerOptions options;
 
   /**
    * If true, stop compilation after type inference is complete. Used for
@@ -227,49 +194,9 @@
    */
   bool stopAfterTypeInference = false;
 
-  /**
-   * If [:true:], comment tokens are collected in [commentMap] during scanning.
-   */
-  final bool preserveComments;
-
-  /// Use the new CPS based backend end.  This flag works for both the Dart and
-  /// JavaScript backend.
-  final bool useCpsIr;
-
-  /**
-   * Is the compiler in verbose mode.
-   */
-  final bool verbose;
-
-  /**
-   * URI of the main source map if the compiler is generating source
-   * maps.
-   */
-  final Uri sourceMapUri;
-
-  /**
-   * URI of the main output if the compiler is generating source maps.
-   */
-  final Uri outputUri;
-
-  /// If `true`, some values are cached for reuse in incremental compilation.
-  /// Incremental compilation is basically calling [run] more than once.
-  final bool hasIncrementalSupport;
-
-  /// If `true` native extension syntax is supported by the frontend.
-  final bool allowNativeExtensions;
-
   /// Output provider from user of Compiler API.
   api.CompilerOutput userOutputProvider;
 
-  /// Generate output even when there are compile-time errors.
-  final bool generateCodeWithCompileTimeErrors;
-
-  /// The compiler is run from the build bot.
-  final bool testMode;
-
-  bool disableInlining = false;
-
   List<Uri> librariesToAnalyzeWhenRun;
 
   /// The set of platform libraries reported as unsupported.
@@ -380,7 +307,6 @@
   DeferredLoadTask deferredLoadTask;
   MirrorUsageAnalyzerTask mirrorUsageAnalyzerTask;
   DumpInfoTask dumpInfoTask;
-  String buildId;
 
   /// A customizable filter that is applied to enqueued work items.
   QueueFilter enqueuerFilter = new QueueFilter();
@@ -391,9 +317,6 @@
   static const String CREATE_INVOCATION_MIRROR =
       'createInvocationMirror';
 
-  static const String UNDETERMINED_BUILD_ID =
-      "build number could not be determined";
-
   bool enabledRuntimeType = false;
   bool enabledFunctionApply = false;
   bool enabledInvokeOn = false;
@@ -404,7 +327,7 @@
   Stopwatch progress;
 
   bool get shouldPrintProgress {
-    return verbose && progress.elapsedMilliseconds > 500;
+    return options.verbose && progress.elapsedMilliseconds > 500;
   }
 
   static const int PHASE_SCANNING = 0;
@@ -424,74 +347,25 @@
     compilationFailedInternal = value;
   }
 
-  /// Set by the backend if real reflection is detected in use of dart:mirrors.
-  bool disableTypeInferenceForMirrors = false;
-
-  Compiler({this.enableTypeAssertions: false,
-            this.enableUserAssertions: false,
-            this.trustTypeAnnotations: false,
-            this.trustPrimitives: false,
-            this.trustJSInteropTypeAnnotations: false,
-            bool disableTypeInferenceFlag: false,
-            this.maxConcreteTypeSize: 5,
-            this.enableMinification: false,
-            this.preserveUris: false,
-            this.enableNativeLiveTypeAnalysis: false,
-            bool emitJavaScript: true,
-            bool dart2dartMultiFile: false,
-            bool generateSourceMap: true,
-            bool analyzeAllFlag: false,
-            bool analyzeOnly: false,
-            this.analyzeMain: false,
-            bool analyzeSignaturesOnly: false,
-            this.preserveComments: false,
-            this.useCpsIr: false,
-            this.useFrequencyNamer: false,
-            this.verbose: false,
-            this.sourceMapUri: null,
-            this.outputUri: null,
-            this.buildId: UNDETERMINED_BUILD_ID,
-            this.deferredMapUri: null,
-            this.dumpInfo: false,
-            bool useStartupEmitter: false,
-            bool enableConditionalDirectives: false,
-            bool useNewSourceInfo: false,
-            this.useContentSecurityPolicy: false,
-            bool hasIncrementalSupport: false,
-            this.enableExperimentalMirrors: false,
-            this.enableAssertMessage: false,
-            this.allowNativeExtensions: false,
-            this.generateCodeWithCompileTimeErrors: false,
-            this.testMode: false,
-            DiagnosticOptions diagnosticOptions,
-            api.CompilerOutput outputProvider,
-            List<String> strips: const []})
-      : this.disableTypeInferenceFlag =
-          disableTypeInferenceFlag || !emitJavaScript,
-        this.analyzeOnly =
-            analyzeOnly || analyzeSignaturesOnly || analyzeAllFlag,
-        this.analyzeSignaturesOnly = analyzeSignaturesOnly,
-        this.analyzeAllFlag = analyzeAllFlag,
-        this.hasIncrementalSupport = hasIncrementalSupport,
-        cacheStrategy = new CacheStrategy(hasIncrementalSupport),
+  Compiler({api.CompilerOptions options,
+            api.CompilerOutput outputProvider})
+      : this.options = options,
+        this.cacheStrategy = new CacheStrategy(options.hasIncrementalSupport),
         this.userOutputProvider = outputProvider == null
             ? const NullCompilerOutput() : outputProvider {
-    if (hasIncrementalSupport) {
-      // TODO(ahe): This is too much. Any method from platform and package
-      // libraries can be inlined.
-      disableInlining = true;
-    }
+
     world = new World(this);
     // TODO(johnniwinther): Initialize core types in [initializeCoreClasses] and
     // make its field final.
-    _reporter = new _CompilerDiagnosticReporter(this, diagnosticOptions);
+    _reporter = new _CompilerDiagnosticReporter(
+        this, options.diagnosticOptions);
     _parsing = new _CompilerParsing(this);
     _resolution = new _CompilerResolution(this);
     _coreTypes = new _CompilerCoreTypes(_resolution);
     types = new Types(_resolution);
     tracer = new Tracer(this, this.outputProvider);
 
-    if (verbose) {
+    if (options.verbose) {
       progress = new Stopwatch()..start();
     }
 
@@ -499,17 +373,17 @@
     // for global dependencies.
     globalDependencies = new GlobalDependencyRegistry(this);
 
-    if (emitJavaScript) {
+    if (options.emitJavaScript) {
       js_backend.JavaScriptBackend jsBackend =
           new js_backend.JavaScriptBackend(
-              this, generateSourceMap: generateSourceMap,
-              useStartupEmitter: useStartupEmitter,
-              useNewSourceInfo: useNewSourceInfo);
+              this, generateSourceMap: options.generateSourceMap,
+              useStartupEmitter: options.useStartupEmitter,
+              useNewSourceInfo: options.useNewSourceInfo);
       backend = jsBackend;
     } else {
-      backend = new dart_backend.DartBackend(this, strips,
-                                             multiFile: dart2dartMultiFile);
-      if (dumpInfo) {
+      backend = new dart_backend.DartBackend(this, options.strips,
+          multiFile: options.dart2dartMultiFile);
+      if (options.dumpInfo) {
         throw new ArgumentError('--dump-info is not supported for dart2dart.');
       }
     }
@@ -519,11 +393,11 @@
       serialization = new SerializationTask(this),
       scanner = new ScannerTask(this),
       dietParser = new DietParserTask(
-          this, enableConditionalDirectives: enableConditionalDirectives),
+          this, enableConditionalDirectives: options.enableConditionalDirectives),
       parser = new ParserTask(
-          this, enableConditionalDirectives: enableConditionalDirectives),
+          this, enableConditionalDirectives: options.enableConditionalDirectives),
       patchParser = new PatchParserTask(
-          this, enableConditionalDirectives: enableConditionalDirectives),
+          this, enableConditionalDirectives: options.enableConditionalDirectives),
       resolver = new ResolverTask(this, backend.constantCompilerTask),
       closureToClassMapper = new closureMapping.ClosureTask(this),
       checker = new TypeCheckerTask(this),
@@ -542,15 +416,12 @@
   Universe get resolverWorld => enqueuer.resolution.universe;
   Universe get codegenWorld => enqueuer.codegen.universe;
 
-  bool get hasBuildId => buildId != UNDETERMINED_BUILD_ID;
-
-  bool get analyzeAll => analyzeAllFlag || compileAll;
+  bool get analyzeAll => options.analyzeAll || compileAll;
 
   bool get compileAll => false;
 
-  bool get disableTypeInference {
-    return disableTypeInferenceFlag || compilationFailed;
-  }
+  bool get disableTypeInference =>
+      options.disableTypeInference || compilationFailed;
 
   int getNextFreeClassId() => nextFreeClassId++;
 
@@ -641,7 +512,7 @@
     // The maximum number of full imports chains to process.
     final int chainLimit = 10000;
     // The maximum number of imports chains to show.
-    final int compactChainLimit = verbose ? 20 : 10;
+    final int compactChainLimit = options.verbose ? 20 : 10;
     int chainCount = 0;
     loadedLibraries.forEachImportChain(uri,
         callback: (Link<Uri> importChainReversed) {
@@ -655,7 +526,7 @@
         Uri uri = link.head;
         if (!currentCodeLocation.inSameLocation(uri)) {
           currentCodeLocation =
-              verbose ? new UriLocation(uri) : new CodeLocation(uri);
+              options.verbose ? new UriLocation(uri) : new CodeLocation(uri);
           compactImportChain =
               compactImportChain.prepend(currentCodeLocation);
         }
@@ -728,7 +599,7 @@
             MessageKind.MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND,
             {'importChain': importChains.join(
                 MessageTemplate.MIRRORS_NOT_SUPPORTED_BY_BACKEND_PADDING)});
-      } else if (importsMirrorsLibrary && !enableExperimentalMirrors) {
+      } else if (importsMirrorsLibrary && !options.enableExperimentalMirrors) {
         Set<String> importChains =
             computeImportChainsFor(loadedLibraries, Uris.dart_mirrors);
         reporter.reportWarningMessage(
@@ -742,7 +613,7 @@
       functionApplyMethod =
           coreClasses.functionClass.lookupLocalMember('apply');
 
-      if (preserveComments) {
+      if (options.preserveComments) {
         return libraryLoader.loadLibrary(Uris.dart_mirrors)
             .then((LibraryElement libraryElement) {
           documentClass = libraryElement.find('Comment');
@@ -863,20 +734,20 @@
         .add(selector);
     }
 
-    assert(uri != null || analyzeOnly || hasIncrementalSupport);
+    assert(uri != null || options.analyzeOnly || options.hasIncrementalSupport);
     return new Future.sync(() {
       if (librariesToAnalyzeWhenRun != null) {
         return Future.forEach(librariesToAnalyzeWhenRun, (libraryUri) {
-          reporter.log('Analyzing $libraryUri ($buildId)');
+          reporter.log('Analyzing $libraryUri (${options.buildId})');
           return libraryLoader.loadLibrary(libraryUri);
         });
       }
     }).then((_) {
       if (uri != null) {
-        if (analyzeOnly) {
-          reporter.log('Analyzing $uri ($buildId)');
+        if (options.analyzeOnly) {
+          reporter.log('Analyzing $uri (${options.buildId})');
         } else {
-          reporter.log('Compiling $uri ($buildId)');
+          reporter.log('Compiling $uri (${options.buildId})');
         }
         return libraryLoader.loadLibrary(uri).then((LibraryElement library) {
           mainApp = library;
@@ -893,7 +764,7 @@
     Element main = mainApp.findExported(Identifiers.main);
     ErroneousElement errorElement = null;
     if (main == null) {
-      if (analyzeOnly) {
+      if (options.analyzeOnly) {
         if (!analyzeAll) {
           errorElement = new ErroneousElementX(
               MessageKind.CONSIDER_ANALYZE_ALL, {'main': Identifiers.main},
@@ -937,7 +808,7 @@
       }
     }
     if (mainFunction == null) {
-      if (errorElement == null && !analyzeOnly && !analyzeAll) {
+      if (errorElement == null && !options.analyzeOnly && !analyzeAll) {
         reporter.internalError(mainApp, "Problem with '${Identifiers.main}'.");
       } else {
         mainFunction = errorElement;
@@ -962,8 +833,8 @@
   Future<LibraryElement> analyzeUri(
       Uri libraryUri,
       {bool skipLibraryWithPartOfTag: true}) {
-    assert(analyzeMain);
-    reporter.log('Analyzing $libraryUri ($buildId)');
+    assert(options.analyzeMain);
+    reporter.log('Analyzing $libraryUri (${options.buildId})');
     return libraryLoader.loadLibrary(
         libraryUri, skipFileWithPartOfTag: true).then(
             (LibraryElement library) {
@@ -988,7 +859,8 @@
     deferredLoadTask.beforeResolution(this);
     impactStrategy = backend.createImpactStrategy(
         supportDeferredLoad: deferredLoadTask.isProgramSplit,
-        supportDumpInfo: dumpInfo);
+        supportDumpInfo: options.dumpInfo,
+        supportSerialization: serialization.supportSerialization);
 
     phase = PHASE_RESOLVING;
     if (analyzeAll) {
@@ -996,7 +868,7 @@
       reporter.log('Enqueuing ${library.canonicalUri}');
         fullyEnqueueLibrary(library, enqueuer.resolution);
       });
-    } else if (analyzeMain) {
+    } else if (options.analyzeMain) {
       if (mainApp != null) {
         fullyEnqueueLibrary(mainApp, enqueuer.resolution);
       }
@@ -1018,13 +890,13 @@
     _reporter.reportSuppressedMessagesSummary();
 
     if (compilationFailed){
-      if (!generateCodeWithCompileTimeErrors) return;
+      if (!options.generateCodeWithCompileTimeErrors) return;
       if (!backend.enableCodegenWithErrorsIfSupported(NO_LOCATION_SPANNABLE)) {
         return;
       }
     }
 
-    if (analyzeOnly) {
+    if (options.analyzeOnly) {
       if (!analyzeAll && !compilationFailed) {
         // No point in reporting unused code when [analyzeAll] is true: all
         // code is artificially used.
@@ -1070,7 +942,7 @@
 
     int programSize = backend.assembleProgram();
 
-    if (dumpInfo) {
+    if (options.dumpInfo) {
       dumpInfoTask.reportSize(programSize);
       dumpInfoTask.dumpInfo();
     }
@@ -1141,7 +1013,7 @@
       }
       world.addToWorkList(main);
     }
-    if (verbose) {
+    if (options.verbose) {
       progress.reset();
     }
     emptyQueue(world);
@@ -1261,7 +1133,7 @@
   ];
 
   bool markCompilationAsFailed(DiagnosticMessage message, api.Diagnostic kind) {
-    if (testMode) {
+    if (options.testMode) {
       // When in test mode, i.e. on the build-bot, we always stop compilation.
       return true;
     }
@@ -1470,7 +1342,7 @@
 
   EventSink<String> outputProvider(String name, String extension) {
     if (compilationFailed) {
-      if (!generateCodeWithCompileTimeErrors || testMode) {
+      if (!options.generateCodeWithCompileTimeErrors || options.testMode) {
         // Disable output in test mode: The build bot currently uses the time
         // stamp of the generated file to determine whether the output is
         // up-to-date.
@@ -1978,7 +1850,7 @@
   void pleaseReportCrash() {
     print(
         MessageTemplate.TEMPLATES[MessageKind.PLEASE_REPORT_THE_CRASH]
-            .message({'buildId': compiler.buildId}));
+            .message({'buildId': compiler.options.buildId}));
   }
 
   /// Finds the approximate [Element] for [node]. [currentElement] is used as
@@ -2126,7 +1998,7 @@
       assert(invariant(element, !element.isSynthesized || tree == null));
       ResolutionImpact resolutionImpact =
           compiler.resolver.resolve(element);
-      if (tree != null && !compiler.analyzeSignaturesOnly) {
+      if (tree != null && !compiler.options.analyzeSignaturesOnly) {
         // TODO(het): don't do this if suppressWarnings is on, currently we have
         // to do it because the typechecker also sets types
         // Only analyze nodes with a corresponding [TreeElements].
@@ -2141,6 +2013,7 @@
 
   @override
   void uncacheWorldImpact(Element element) {
+    if (compiler.serialization.isDeserialized(element)) return;
     assert(invariant(element, _worldImpactCache[element] != null,
         message: "WorldImpact not computed for $element."));
     _worldImpactCache[element] = const WorldImpact();
@@ -2157,6 +2030,17 @@
   bool hasBeenResolved(Element element) {
     return _worldImpactCache.containsKey(element);
   }
+
+  @override
+  ResolutionWorkItem createWorkItem(
+      Element element, ItemCompilationContext compilationContext) {
+    if (compiler.serialization.isDeserialized(element)) {
+      return compiler.serialization.createResolutionWorkItem(
+          element, compilationContext);
+    } else {
+      return new ResolutionWorkItem(element, compilationContext);
+    }
+  }
 }
 
 // TODO(johnniwinther): Move [ParserTask], [PatchParserTask], [DietParserTask]
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 6957274..e44b840 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
@@ -1312,7 +1312,7 @@
   /// This is also where we should add type checks in checked mode, but this
   /// is not supported yet.
   ir.Primitive checkType(ir.Primitive value, DartType dartType) {
-    if (!compiler.trustTypeAnnotations) return value;
+    if (!compiler.options.trustTypeAnnotations) return value;
     TypeMask type = typeMaskSystem.subtypesOf(dartType).nullable();
     return irBuilder.addPrimitive(new ir.Refinement(value, type));
   }
@@ -1368,7 +1368,7 @@
         irBuilder.buildNativeFunctionBody(function, javaScriptCode,
             sourceInformationBuilder.buildForeignCode(node));
       } else {
-        String name = backend.getFixedBackendName(function);
+        String name = backend.nativeData.getFixedBackendName(function);
         irBuilder.buildRedirectingNativeFunctionBody(function, name, source);
       }
     } else {
@@ -1869,7 +1869,7 @@
   @override
   ir.Primitive visitAssert(ast.Assert node) {
     assert(irBuilder.isOpen);
-    if (compiler.enableUserAssertions) {
+    if (compiler.options.enableUserAssertions) {
       return giveup(node, 'assert in checked mode not implemented');
     } else {
       // The call to assert and its argument expression must be ignored
@@ -3505,7 +3505,7 @@
             value = backend.mustRetainMetadata;
             break;
           case 'USE_CONTENT_SECURITY_POLICY':
-            value = compiler.useContentSecurityPolicy;
+            value = compiler.options.useContentSecurityPolicy;
             break;
           default:
             internalError(node, 'Unknown internal flag "$name".');
@@ -4247,7 +4247,7 @@
   }
 
   bool get trustJSInteropTypeAnnotations =>
-      _compiler.trustJSInteropTypeAnnotations;
+      _compiler.options.trustJSInteropTypeAnnotations;
 
   bool isNative(ClassElement element) => _backend.isNative(element);
 
@@ -4258,7 +4258,7 @@
 
   String getJsInteropTargetPath(FunctionElement element) {
     return '${_backend.namer.fixedBackendPath(element)}.'
-      '${_backend.getFixedBackendName(element)}';
+      '${_backend.nativeData.getFixedBackendName(element)}';
   }
 
   DartType get jsJavascriptObjectType =>
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index 41d33f9..3f982d1 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -1163,7 +1163,7 @@
       return null;
     }
 
-    bool trustPrimitives = compiler.trustPrimitives;
+    bool trustPrimitives = compiler.options.trustPrimitives;
 
     /// Check that the receiver and argument satisfy the given type checks, and
     /// throw a [NoSuchMethodError] or [ArgumentError] if the check fails.
@@ -1486,7 +1486,7 @@
         Primitive list,
         Primitive index,
         [int checkKind = BoundsCheck.BOTH_BOUNDS | BoundsCheck.INTEGER]) {
-    if (compiler.trustPrimitives) {
+    if (compiler.options.trustPrimitives) {
       return cps.letPrim(new BoundsCheck.noCheck(list, cps.sourceInformation));
     } else {
       GetLength length = cps.letPrim(new GetLength(list));
@@ -1547,7 +1547,7 @@
           if (!typeSystem.isDefinitelyUint(newLength.type)) {
             // TODO(asgerf): We could let the SetLength instruction throw for
             // negative right-hand sides (see length setter in js_array.dart).
-            if (compiler.trustPrimitives) {
+            if (compiler.options.trustPrimitives) {
               newLength = cps.refine(newLength, typeSystem.uint32Type);
               newLength.type = typeSystem.uint32Type;
             } else {
diff --git a/pkg/compiler/lib/src/dart_backend/backend.dart b/pkg/compiler/lib/src/dart_backend/backend.dart
index 7d99b21..bb925f9 100644
--- a/pkg/compiler/lib/src/dart_backend/backend.dart
+++ b/pkg/compiler/lib/src/dart_backend/backend.dart
@@ -111,7 +111,7 @@
             compiler.reporter, compiler.outputProvider,
             forceStripTypes: strips.indexOf('types') != -1,
             multiFile: multiFile,
-            enableMinification: compiler.enableMinification),
+            enableMinification: compiler.options.enableMinification),
         super(compiler) {
     impactTransformer = new DartImpactTransformer(this);
   }
@@ -194,7 +194,7 @@
         sortElements: Elements.sortedByPosition,
         mirrorRenamer: mirrorRenamer,
         mainFunction: compiler.mainFunction,
-        outputUri: compiler.outputUri);
+        outputUri: compiler.options.outputUri);
 
     // Output verbose info about size ratio of resulting bundle to all
     // referenced non-platform sources.
diff --git a/pkg/compiler/lib/src/dart_backend/outputter.dart b/pkg/compiler/lib/src/dart_backend/outputter.dart
index 3e6f564..484bda2 100644
--- a/pkg/compiler/lib/src/dart_backend/outputter.dart
+++ b/pkg/compiler/lib/src/dart_backend/outputter.dart
@@ -511,7 +511,7 @@
           ? mainName.substring(0, mainName.length - 5)
           : mainName;
       // Map each library to a path based on the uri of the original
-      // library and [compiler.outputUri].
+      // library and [compiler.options.outputUri].
       Set<String> usedLibraryPaths = new Set<String>();
       for (LibraryElement library in libraryInfo.userLibraries) {
         if (library == mainFunction.library) {
@@ -602,4 +602,4 @@
 
     return totalSize;
   }
-}
\ No newline at end of file
+}
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index c24ecbf..81ffd69 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -346,7 +346,7 @@
                       collectTypeDependencies(type);
                       break;
                     case TypeUseKind.CHECKED_MODE_CHECK:
-                      if (compiler.enableTypeAssertions) {
+                      if (compiler.options.enableTypeAssertions) {
                         collectTypeDependencies(type);
                       }
                       break;
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index d909a47..109cd312 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -431,7 +431,7 @@
   }
 
   void registerImpact(Element element, WorldImpact impact) {
-    if (compiler.dumpInfo) {
+    if (compiler.options.dumpInfo) {
       impacts[element] = impact;
     }
   }
@@ -470,7 +470,7 @@
   // Returns true if we care about tracking the size of
   // this node.
   bool isTracking(jsAst.Node code) {
-    if (compiler.dumpInfo) {
+    if (compiler.options.dumpInfo) {
       return _tracking.contains(code);
     } else {
       return false;
@@ -480,7 +480,7 @@
   // Registers that a javascript AST node `code` was produced by the
   // dart Element `element`.
   void registerElementAst(Element element, jsAst.Node code) {
-    if (compiler.dumpInfo) {
+    if (compiler.options.dumpInfo) {
       _elementToNodes
           .putIfAbsent(element, () => new List<jsAst.Node>())
           .add(code);
@@ -489,7 +489,7 @@
   }
 
   void registerConstantAst(ConstantValue constant, jsAst.Node code) {
-    if (compiler.dumpInfo) {
+    if (compiler.options.dumpInfo) {
       assert(_constantToNode[constant] == null ||
           _constantToNode[constant] == code);
       _constantToNode[constant] = code;
@@ -594,13 +594,14 @@
     result.program = new ProgramInfo(
         entrypoint: infoCollector._elementToInfo[compiler.mainFunction],
         size: _programSize,
-        dart2jsVersion: compiler.hasBuildId ? compiler.buildId : null,
+        dart2jsVersion:
+            compiler.options.hasBuildId ? compiler.options.buildId : null,
         compilationMoment: new DateTime.now(),
         compilationDuration: compiler.totalCompileTime.elapsed,
         toJsonDuration: stopwatch.elapsedMilliseconds,
         dumpInfoDuration: this.timing,
         noSuchMethodEnabled: compiler.backend.enabledNoSuchMethod,
-        minified: compiler.enableMinification);
+        minified: compiler.options.enableMinification);
 
     ChunkedConversionSink<Object> sink = encoder.startChunkedConversion(
         new StringConversionSink.fromStringSink(buffer));
diff --git a/pkg/compiler/lib/src/elements/common.dart b/pkg/compiler/lib/src/elements/common.dart
index 1e24ff0..5d5f9e6 100644
--- a/pkg/compiler/lib/src/elements/common.dart
+++ b/pkg/compiler/lib/src/elements/common.dart
@@ -123,6 +123,19 @@
   Element get origin {
     throw new UnsupportedError('origin is not supported on $this');
   }
+
+  @override
+  ClassElement get contextClass {
+    ClassElement cls;
+    for (Element e = this; e != null; e = e.enclosingElement) {
+      if (e.isClass) {
+        // Record [e] instead of returning it directly. We need the last class
+        // in the chain since the first classes might be closure classes.
+        cls = e.declaration;
+      }
+    }
+    return cls;
+  }
 }
 
 abstract class LibraryElementCommon implements LibraryElement {
@@ -331,7 +344,7 @@
         classElement.forEachBackendMember((e) => f(classElement, e));
       }
       if (includeInjectedMembers) {
-        if (classElement.patch != null) {
+        if (classElement.isPatched) {
           classElement.patch.forEachLocalMember((e) {
             if (!e.isPatch) f(classElement, e);
           });
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index 121a882..cfc0dcb 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -208,18 +208,6 @@
     return null;
   }
 
-  ClassElement get contextClass {
-    ClassElement cls;
-    for (Element e = this; e != null; e = e.enclosingElement) {
-      if (e.isClass) {
-        // Record [e] instead of returning it directly. We need the last class
-        // in the chain since the first classes might be closure classes.
-        cls = e.declaration;
-      }
-    }
-    return cls;
-  }
-
   /**
    * Creates the scope for this element.
    */
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 2c7403f..38c02bf 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -76,7 +76,7 @@
   EnqueueTask(Compiler compiler)
     : resolution = new ResolutionEnqueuer(
           compiler, compiler.backend.createItemCompilationContext,
-          compiler.analyzeOnly && compiler.analyzeMain
+          compiler.options.analyzeOnly && compiler.options.analyzeMain
               ? const EnqueuerStrategy() : const TreeShakingEnqueuerStrategy()),
       codegen = new CodegenEnqueuer(
           compiler, compiler.backend.createItemCompilationContext,
@@ -157,7 +157,7 @@
    */
   void addToWorkList(Element element) {
     assert(invariant(element, element.isDeclaration));
-    if (internalAddToWorkList(element) && compiler.dumpInfo) {
+    if (internalAddToWorkList(element) && compiler.options.dumpInfo) {
       // TODO(sigmund): add other missing dependencies (internals, selectors
       // enqueued after allocations), also enable only for the codegen enqueuer.
       compiler.dumpInfoTask.registerDependency(
@@ -663,7 +663,7 @@
         _registerIsCheck(type);
         break;
       case TypeUseKind.CHECKED_MODE_CHECK:
-        if (compiler.enableTypeAssertions) {
+        if (compiler.options.enableTypeAssertions) {
           _registerIsCheck(type);
         }
         break;
@@ -803,14 +803,8 @@
 
     compiler.world.registerUsedElement(element);
 
-    ResolutionWorkItem workItem;
-    if (compiler.serialization.isDeserialized(element)) {
-      workItem = compiler.serialization.createResolutionWorkItem(
-          element, itemCompilationContextCreator());
-    } else {
-      workItem = new ResolutionWorkItem(
-          element, itemCompilationContextCreator());
-    }
+    ResolutionWorkItem workItem = compiler.resolution.createWorkItem(
+        element, itemCompilationContextCreator());
     queue.add(workItem);
 
     // Enable isolate support if we start using something from the isolate
@@ -942,13 +936,13 @@
     // Codegen inlines field initializers. It only needs to generate
     // code for checked setters.
     if (element.isField && element.isInstanceMember) {
-      if (!compiler.enableTypeAssertions
+      if (!compiler.options.enableTypeAssertions
           || element.enclosingElement.isClosure) {
         return false;
       }
     }
 
-    if (compiler.hasIncrementalSupport && !isProcessed(element)) {
+    if (compiler.options.hasIncrementalSupport && !isProcessed(element)) {
       newlyEnqueuedElements.add(element);
     }
 
@@ -986,7 +980,7 @@
   }
 
   void handleUnseenSelector(DynamicUse dynamicUse) {
-    if (compiler.hasIncrementalSupport) {
+    if (compiler.options.hasIncrementalSupport) {
       newlySeenSelectors.add(dynamicUse);
     }
     super.handleUnseenSelector(dynamicUse);
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
index fbb7880..85a81bc 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
@@ -466,7 +466,8 @@
 
   void update(LocalElement local, T type, Node node) {
     assert(type != null);
-    if (compiler.trustTypeAnnotations || compiler.enableTypeAssertions) {
+    if (compiler.options.trustTypeAnnotations ||
+        compiler.options.enableTypeAssertions) {
       type = types.narrowType(type, local.type);
     }
     updateLocal() {
@@ -779,7 +780,7 @@
 
   T visitAssert(Assert node) {
     // Avoid pollution from assert statement unless enabled.
-    if (compiler.enableUserAssertions) {
+    if (compiler.options.enableUserAssertions) {
       super.visitAssert(node);
     }
     return null;
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index 14d904a..f12a8b4 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -709,7 +709,7 @@
 
   void runOverAllElements() {
     if (compiler.disableTypeInference) return;
-    if (compiler.verbose) {
+    if (compiler.options.verbose) {
       compiler.progress.reset();
     }
     sortResolvedElements().forEach((Element element) {
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index e549d68..0ed437c 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -515,8 +515,8 @@
   TypeMask potentiallyNarrowType(TypeMask mask,
                                  TypeGraphInferrerEngine inferrer) {
     Compiler compiler = inferrer.compiler;
-    if (!compiler.trustTypeAnnotations &&
-        !compiler.enableTypeAssertions &&
+    if (!compiler.options.trustTypeAnnotations &&
+        !compiler.options.enableTypeAssertions &&
         !inferrer.annotations.trustTypeAnnotations(element)) {
       return mask;
     }
@@ -664,14 +664,14 @@
   TypeMask potentiallyNarrowType(TypeMask mask,
                                  TypeGraphInferrerEngine inferrer) {
     Compiler compiler = inferrer.compiler;
-    if (!compiler.trustTypeAnnotations &&
+    if (!compiler.options.trustTypeAnnotations &&
         !inferrer.annotations.trustTypeAnnotations(declaration)) {
       return mask;
     }
     // When type assertions are enabled (aka checked mode), we have to always
     // ignore type annotations to ensure that the checks are actually inserted
     // into the function body and retained until runtime.
-    assert(!compiler.enableTypeAssertions);
+    assert(!compiler.options.enableTypeAssertions);
     return _narrowType(compiler, mask, element.type);
   }
 
diff --git a/pkg/compiler/lib/src/js/js.dart b/pkg/compiler/lib/src/js/js.dart
index df510a8..837b9fe 100644
--- a/pkg/compiler/lib/src/js/js.dart
+++ b/pkg/compiler/lib/src/js/js.dart
@@ -27,7 +27,7 @@
      Renamer renamerForNames: JavaScriptPrintingOptions.identityRenamer}) {
   // TODO(johnniwinther): Do we need all the options here?
   JavaScriptPrintingOptions options = new JavaScriptPrintingOptions(
-      shouldCompressOutput: compiler.enableMinification,
+      shouldCompressOutput: compiler.options.enableMinification,
       minifyLocalVariables: allowVariableMinification,
       preferSemicolonToNewlineInMinifiedOutput: USE_LAZY_EMITTER,
       renamerForNames: renamerForNames);
@@ -47,7 +47,7 @@
   JavaScriptSourceInformationStrategy sourceInformationFactory =
       compiler.backend.sourceInformationStrategy;
   JavaScriptPrintingOptions options = new JavaScriptPrintingOptions(
-      shouldCompressOutput: compiler.enableMinification,
+      shouldCompressOutput: compiler.options.enableMinification,
       minifyLocalVariables: allowVariableMinification,
       preferSemicolonToNewlineInMinifiedOutput: USE_LAZY_EMITTER,
       renamerForNames: renamerForNames);
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 1d8a35a..f8afee0 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -504,6 +504,10 @@
 
   SourceInformationStrategy sourceInformationStrategy;
 
+  JavaScriptBackendSerialization serialization;
+
+  final NativeData nativeData = new NativeData();
+
   final BackendHelpers helpers;
   final BackendImpacts impacts;
 
@@ -538,10 +542,11 @@
     constantCompilerTask = new JavaScriptConstantTask(compiler);
     impactTransformer = new JavaScriptImpactTransformer(this);
     patchResolverTask = new PatchResolverTask(compiler);
-    functionCompiler = compiler.useCpsIr
+    functionCompiler = compiler.options.useCpsIr
          ? new CpsFunctionCompiler(
              compiler, this, sourceInformationStrategy)
          : new SsaFunctionCompiler(this, sourceInformationStrategy);
+    serialization = new JavaScriptBackendSerialization(this);
   }
 
   ConstantSystem get constantSystem => constants.constantSystem;
@@ -585,8 +590,8 @@
   }
 
   static Namer determineNamer(Compiler compiler) {
-    return compiler.enableMinification ?
-        compiler.useFrequencyNamer ?
+    return compiler.options.enableMinification ?
+        compiler.options.useFrequencyNamer ?
             new FrequencyBasedNamer(compiler) :
             new MinifyNamer(compiler) :
         new Namer(compiler);
@@ -600,44 +605,50 @@
   // TODO(johnniwinther): Replace this with a more precise modelling; type
   // inference of these elements is disabled.
   Element registerBackendUse(Element element) {
-    if (element != null) {
-      bool registerUse = false;
-      if (element == helpers.streamIteratorConstructor ||
-          element == helpers.compiler.symbolConstructor ||
-          element == helpers.compiler.symbolValidatedConstructor ||
-          element == helpers.syncCompleterConstructor ||
-          element == coreClasses.symbolClass ||
-          element == helpers.objectNoSuchMethod) {
-        // TODO(johnniwinther): These are valid but we could be more precise.
-        registerUse = true;
-      } else if (element.implementationLibrary.isPatch ||
-                 element.library == helpers.jsHelperLibrary ||
-                 element.library == helpers.interceptorsLibrary ||
-                 element.library == helpers.isolateHelperLibrary) {
-        // TODO(johnniwinther): We should be more precise about these.
-        registerUse = true;
-      } else if (element == coreClasses.listClass ||
-                 element == helpers.mapLiteralClass ||
-                 element == coreClasses.functionClass ||
-                 element == coreClasses.stringClass) {
-        // TODO(johnniwinther): Avoid these.
-        registerUse = true;
-      }
-      if (!registerUse) {
-        assert(invariant(element, false,
-            message: "Backend use of $element is not allowed."));
-        return element;
-      }
-      helpersUsed.add(element.declaration);
-      if (element.isClass && element.isPatched) {
-        // Both declaration and implementation may declare fields, so we
-        // add both to the list of helpers.
-        helpersUsed.add(element.implementation);
-      }
+    if (element == null) return null;
+    assert(invariant(element, _isValidBackendUse(element),
+        message: "Backend use of $element is not allowed."));
+    helpersUsed.add(element.declaration);
+    if (element.isClass && element.isPatched) {
+      // Both declaration and implementation may declare fields, so we
+      // add both to the list of helpers.
+      helpersUsed.add(element.implementation);
     }
     return element;
   }
 
+  bool _isValidBackendUse(Element element) {
+    assert(invariant(element, element.isDeclaration,
+        message: ""));
+    if (element == helpers.streamIteratorConstructor ||
+        element == helpers.compiler.symbolConstructor ||
+        element == helpers.compiler.symbolValidatedConstructor ||
+        element == helpers.syncCompleterConstructor ||
+        element == coreClasses.symbolClass ||
+        element == helpers.objectNoSuchMethod) {
+      // TODO(johnniwinther): These are valid but we could be more precise.
+      return true;
+    } else if (element.implementationLibrary.isPatch ||
+               // Needed to detect deserialized injected elements, that is
+               // element declared in patch files.
+               (element.library.isPlatformLibrary &&
+                element.sourcePosition.uri.path.contains(
+                    '_internal/js_runtime/lib/')) ||
+               element.library == helpers.jsHelperLibrary ||
+               element.library == helpers.interceptorsLibrary ||
+               element.library == helpers.isolateHelperLibrary) {
+      // TODO(johnniwinther): We should be more precise about these.
+      return true;
+    } else if (element == coreClasses.listClass ||
+               element == helpers.mapLiteralClass ||
+               element == coreClasses.functionClass ||
+               element == coreClasses.stringClass) {
+      // TODO(johnniwinther): Avoid these.
+      return true;
+    }
+    return false;
+  }
+
   bool usedByBackend(Element element) {
     if (element.isParameter
         || element.isInitializingFormal
@@ -702,7 +713,7 @@
   }
 
   bool canUseAliasedSuperMember(Element member, Selector selector) {
-    return !selector.isGetter && !compiler.hasIncrementalSupport;
+    return !selector.isGetter && !compiler.options.hasIncrementalSupport;
   }
 
   /**
@@ -712,161 +723,16 @@
     return aliasedSuperMembers.contains(member);
   }
 
-  /// The JavaScript names for elements implemented via typed JavaScript
-  /// interop.
-  Map<Element, String> jsInteropNames = <Element, String>{};
-
-  /// The JavaScript names for native JavaScript elements implemented.
-  Map<Element, String> nativeMemberName = <Element, String>{};
-
-  /// Tag info for native JavaScript classes names. See
-  /// [setNativeClassTagInfo].
-  Map<ClassElement, String> nativeClassTagInfo = <ClassElement, String>{};
-
-  /// Returns `true` if [element] is explicitly marked as part of JsInterop.
-  bool _isJsInterop(Element element) {
-    return jsInteropNames.containsKey(element.declaration);
-  }
-
-  /// Returns [element] as an explicit part of JsInterop. The js interop name is
-  /// expected to be computed later.
-  void markAsJsInterop(Element element) {
-    jsInteropNames[element.declaration] = null;
-  }
-
-  /// Sets the explicit js interop [name] for [element].
-  void setJsInteropName(Element element, String name) {
-    assert(invariant(element,
-        isJsInterop(element),
-        message:
-          'Element $element is not js interop but given a js interop name.'));
-    jsInteropNames[element.declaration] = name;
-  }
-
-  /// Returns the explicit js interop name for [element].
-  String getJsInteropName(Element element) {
-    return jsInteropNames[element.declaration];
-  }
-
   /// Returns `true` if [element] is part of JsInterop.
   @override
-  bool isJsInterop(Element element) {
-    // An function is part of JsInterop in the following cases:
-    // * It has a jsInteropName annotation
-    // * It is external member of a class or library tagged as JsInterop.
-    if (element.isFunction || element.isConstructor || element.isAccessor) {
-      FunctionElement function = element;
-      if (!function.isExternal) return false;
-
-      if (_isJsInterop(function)) return true;
-      if (function.isClassMember) return isJsInterop(function.contextClass);
-      if (function.isTopLevel) return isJsInterop(function.library);
-      return false;
-    } else {
-      return _isJsInterop(element);
-    }
-  }
-
-  /// Returns `true` if the name of [element] is fixed for the generated
-  /// JavaScript.
-  bool hasFixedBackendName(Element element) {
-    return isJsInterop(element) ||
-        nativeMemberName.containsKey(element.declaration);
-  }
-
-  String _jsNameHelper(Element element) {
-    String jsInteropName = jsInteropNames[element.declaration];
-    assert(invariant(element,
-        !(_isJsInterop(element) && jsInteropName == null),
-        message:
-            'Element $element is js interop but js interop name has not yet '
-            'been computed.'));
-    if (jsInteropName != null && jsInteropName.isNotEmpty) {
-      return jsInteropName;
-    }
-    return element.isLibrary ? 'self' : element.name;
-  }
-
-  /// Computes the name for [element] to use in the generated JavaScript. This
-  /// is either given through a native annotation or a js interop annotation.
-  String getFixedBackendName(Element element) {
-    String name = nativeMemberName[element.declaration];
-    if (name == null && isJsInterop(element)) {
-      // If an element isJsInterop but _isJsInterop is false that means it is
-      // considered interop as the parent class is interop.
-      name = _jsNameHelper(
-          element.isConstructor ? element.enclosingClass : element);
-      nativeMemberName[element.declaration] = name;
-    }
-    return name;
-  }
+  bool isJsInterop(Element element) => nativeData.isJsInterop(element);
 
   /// Whether [element] corresponds to a native JavaScript construct either
   /// through the native mechanism (`@Native(...)` or the `native` pseudo
   /// keyword) which is only allowed for internal libraries or via the typed
   /// JavaScriptInterop mechanism which is allowed for user libraries.
   @override
-  bool isNative(Element element) {
-    if (isJsInterop(element)) return true;
-    if (element.isClass) {
-      return nativeClassTagInfo.containsKey(element.declaration);
-    } else {
-      return nativeMemberName.containsKey(element.declaration);
-    }
-  }
-
-  /// Sets the native [name] for the member [element]. This name is used for
-  /// [element] in the generated JavaScript.
-  void setNativeMemberName(MemberElement element, String name) {
-    // TODO(johnniwinther): Avoid setting this more than once. The enqueuer
-    // might enqueue [element] several times (before processing it) and computes
-    // name on each call to `internalAddToWorkList`.
-    assert(invariant(element,
-        nativeMemberName[element.declaration] == null ||
-        nativeMemberName[element.declaration] == name,
-        message:
-          "Native member name set inconsistently on $element: "
-          "Existing name '${nativeMemberName[element.declaration]}', "
-          "new name '$name'."));
-    nativeMemberName[element.declaration] = name;
-  }
-
-  /// Sets the native tag info for [cls].
-  ///
-  /// The tag info string contains comma-separated 'words' which are either
-  /// dispatch tags (having JavaScript identifier syntax) and directives that
-  /// begin with `!`.
-  void setNativeClassTagInfo(ClassElement cls, String tagInfo) {
-    // TODO(johnniwinther): Assert that this is only called once. The memory
-    // compiler copies pre-processed elements into a new compiler through
-    // [Compiler.onLibraryScanned] and thereby causes multiple calls to this
-    // method.
-    assert(invariant(cls,
-        nativeClassTagInfo[cls.declaration] == null ||
-        nativeClassTagInfo[cls.declaration] == tagInfo,
-        message:
-          "Native tag info set inconsistently on $cls: "
-          "Existing tag info '${nativeClassTagInfo[cls.declaration]}', "
-          "new tag info '$tagInfo'."));
-    nativeClassTagInfo[cls.declaration] = tagInfo;
-  }
-
-  /// Returns the list of native tag words for [cls].
-  List<String> getNativeTagsOfClassRaw(ClassElement cls) {
-    String quotedName = nativeClassTagInfo[cls.declaration];
-    return quotedName.substring(1, quotedName.length - 1).split(',');
-  }
-
-  /// Returns the list of non-directive native tag words for [cls].
-  List<String> getNativeTagsOfClass(ClassElement cls) {
-    return getNativeTagsOfClassRaw(cls).where(
-        (s) => !s.startsWith('!')).toList();
-  }
-
-  /// Returns `true` if [cls] has a `!nonleaf` tag word.
-  bool hasNativeTagsForcedNonLeaf(ClassElement cls) {
-    return getNativeTagsOfClassRaw(cls).contains('!nonleaf');
-  }
+  bool isNative(Element element) => nativeData.isNative(element);
 
   bool isNativeOrExtendsNative(ClassElement element) {
     if (element == null) return false;
@@ -1009,7 +875,13 @@
       Element interceptorMember = interceptorClass.lookupMember(member.name);
       // Interceptors must override all Object methods due to calling convention
       // differences.
-      assert(interceptorMember.enclosingClass == interceptorClass);
+      assert(invariant(
+          interceptorMember,
+          interceptorMember.enclosingClass == interceptorClass,
+          message:
+            "Member ${member.name} not overridden in ${interceptorClass}. "
+            "Found $interceptorMember from "
+            "${interceptorMember.enclosingClass}."));
     });
   }
 
@@ -1209,7 +1081,7 @@
         Element getFactory(String name, int arity) {
           // The constructor is on the patch class, but dart2js unit tests don't
           // have a patch class.
-          ClassElement implementation = cls.patch != null ? cls.patch : cls;
+          ClassElement implementation = cls.implementation;
           ConstructorElement ctor = implementation.lookupConstructor(name);
           if (ctor == null ||
               (Name.isPrivateName(name) &&
@@ -1225,7 +1097,7 @@
         Element getMember(String name) {
           // The constructor is on the patch class, but dart2js unit tests don't
           // have a patch class.
-          ClassElement implementation = cls.patch != null ? cls.patch : cls;
+          ClassElement implementation = cls.implementation;
           Element element = implementation.lookupLocalMember(name);
           if (element == null || !element.isFunction || !element.isStatic) {
             reporter.internalError(helpers.mapLiteralClass,
@@ -1345,7 +1217,7 @@
     // will instantiate those two classes.
     addInterceptors(helpers.jsBoolClass, world, registry);
     addInterceptors(helpers.jsNullClass, world, registry);
-    if (compiler.enableTypeAssertions) {
+    if (compiler.options.enableTypeAssertions) {
       // Unconditionally register the helper that checks if the
       // expression in an if/while/for is a boolean.
       // TODO(ngeoffray): Should we have the resolver register those instead?
@@ -1944,14 +1816,13 @@
 
   void registerStaticUse(Element element, Enqueuer enqueuer) {
     if (element == helpers.disableTreeShakingMarker) {
-      compiler.disableTypeInferenceForMirrors = true;
       isTreeShakingDisabled = true;
     } else if (element == helpers.preserveNamesMarker) {
       mustPreserveNames = true;
     } else if (element == helpers.preserveMetadataMarker) {
       mustRetainMetadata = true;
     } else if (element == helpers.preserveUrisMarker) {
-      if (compiler.preserveUris) mustPreserveUris = true;
+      if (compiler.options.preserveUris) mustPreserveUris = true;
     } else if (element == helpers.preserveLibraryNamesMarker) {
       mustRetainLibraryNames = true;
     } else if (element == helpers.getIsolateAffinityTagMarker) {
@@ -2394,7 +2265,7 @@
       enabledNoSuchMethod = true;
     }
 
-    if (compiler.hasIncrementalSupport) {
+    if (compiler.options.hasIncrementalSupport) {
       // Always enable tear-off closures during incremental compilation.
       Element e = helpers.closureFromTearOff;
       if (e != null && !enqueuer.isProcessed(e)) {
@@ -2561,8 +2432,8 @@
   /// If [addExtension] is false, the ".part.js" suffix is left out.
   String deferredPartFileName(String name, {bool addExtension: true}) {
     assert(name != "");
-    String outPath = compiler.outputUri != null
-        ? compiler.outputUri.path
+    String outPath = compiler.options.outputUri != null
+        ? compiler.options.outputUri.path
         : "out";
     String outName = outPath.substring(outPath.lastIndexOf('/') + 1);
     String extension = addExtension ? ".part.js" : "";
@@ -2577,7 +2448,7 @@
 
   @override
   bool enableCodegenWithErrorsIfSupported(Spannable node) {
-    if (compiler.useCpsIr) {
+    if (compiler.options.useCpsIr) {
       // TODO(25747): Support code generation with compile-time errors.
       reporter.reportHintMessage(
           node,
@@ -2673,12 +2544,14 @@
   @override
   ImpactStrategy createImpactStrategy(
       {bool supportDeferredLoad: true,
-       bool supportDumpInfo: true}) {
+       bool supportDumpInfo: true,
+       bool supportSerialization: true}) {
     return new JavaScriptImpactStrategy(
         resolution,
         compiler.dumpInfoTask,
         supportDeferredLoad: supportDeferredLoad,
-        supportDumpInfo: supportDumpInfo);
+        supportDumpInfo: supportDumpInfo,
+        supportSerialization: supportSerialization);
   }
 }
 
@@ -2792,7 +2665,7 @@
           registerBackendImpact(transformed, impacts.catchStatement);
           break;
         case Feature.COMPILE_TIME_ERROR:
-          if (backend.compiler.generateCodeWithCompileTimeErrors) {
+          if (backend.compiler.options.generateCodeWithCompileTimeErrors) {
             // TODO(johnniwinther): This should have its own uncatchable error.
             registerBackendImpact(transformed, impacts.throwRuntimeError);
           }
@@ -2858,7 +2731,7 @@
           hasAsCast = true;
           break;
         case TypeUseKind.CHECKED_MODE_CHECK:
-          if (backend.compiler.enableTypeAssertions) {
+          if (backend.compiler.options.enableTypeAssertions) {
             onIsCheck(type, transformed);
           }
           break;
@@ -3000,7 +2873,7 @@
     type = type.unaliased;
     registerBackendImpact(transformed, impacts.typeCheck);
 
-    bool inCheckedMode = backend.compiler.enableTypeAssertions;
+    bool inCheckedMode = backend.compiler.options.enableTypeAssertions;
     if (inCheckedMode) {
       registerBackendImpact(transformed, impacts.checkedModeTypeCheck);
     }
@@ -3032,7 +2905,7 @@
     type = type.unaliased;
     registerBackendImpact(transformed, impacts.typeCheck);
 
-    bool inCheckedMode = backend.compiler.enableTypeAssertions;
+    bool inCheckedMode = backend.compiler.options.enableTypeAssertions;
     // [registerIsCheck] is also called for checked mode checks, so we
     // need to register checked mode helpers.
     if (inCheckedMode) {
@@ -3154,11 +3027,13 @@
   final DumpInfoTask dumpInfoTask;
   final bool supportDeferredLoad;
   final bool supportDumpInfo;
+  final bool supportSerialization;
 
   JavaScriptImpactStrategy(this.resolution,
                            this.dumpInfoTask,
                            {this.supportDeferredLoad,
-                            this.supportDumpInfo});
+                            this.supportDumpInfo,
+                            this.supportSerialization});
 
   @override
   void visitImpact(Element element,
@@ -3167,7 +3042,7 @@
                    ImpactUseCase impactUse) {
     // TODO(johnniwinther): Compute the application strategy once for each use.
     if (impactUse == ResolutionEnqueuer.IMPACT_USE) {
-      if (supportDeferredLoad) {
+      if (supportDeferredLoad || supportSerialization) {
         impact.apply(visitor);
       } else {
         impact.apply(visitor);
@@ -3186,7 +3061,10 @@
 
   @override
   void onImpactUsed(ImpactUseCase impactUse) {
-    if (impactUse == DeferredLoadTask.IMPACT_USE) {
+    if (impactUse == DeferredLoadTask.IMPACT_USE &&
+        !supportSerialization) {
+      // TODO(johnniwinther): Allow emptying when serialization has been
+      // performed.
       resolution.emptyCache();
     }
   }
diff --git a/pkg/compiler/lib/src/js_backend/backend_serialization.dart b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
new file mode 100644
index 0000000..8a4923f
--- /dev/null
+++ b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
@@ -0,0 +1,60 @@
+// 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 js_backend.serialization;
+
+import '../common/backend_api.dart' show
+    BackendSerialization;
+import '../elements/elements.dart';
+import '../serialization/serialization.dart' show
+    DeserializerPlugin,
+    ObjectDecoder,
+    ObjectEncoder,
+    SerializerPlugin;
+import '../serialization/keys.dart';
+import 'js_backend.dart';
+
+const String _BACKEND_DATA_TAG = 'jsBackendData';
+
+class JavaScriptBackendSerialization implements BackendSerialization {
+  final JavaScriptBackendSerializer serializer;
+  final JavaScriptBackendDeserializer deserializer;
+
+  JavaScriptBackendSerialization(JavaScriptBackend backend)
+      : serializer = new JavaScriptBackendSerializer(backend),
+        deserializer = new JavaScriptBackendDeserializer(backend);
+}
+
+class JavaScriptBackendSerializer implements SerializerPlugin {
+  final JavaScriptBackend backend;
+
+  JavaScriptBackendSerializer(this.backend);
+
+  @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);
+    }
+  }
+}
+
+class JavaScriptBackendDeserializer implements DeserializerPlugin {
+  final JavaScriptBackend backend;
+
+  JavaScriptBackendDeserializer(this.backend);
+
+  @override
+  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;
+    }
+  }
+}
+
diff --git a/pkg/compiler/lib/src/js_backend/codegen/task.dart b/pkg/compiler/lib/src/js_backend/codegen/task.dart
index 89b9aab..853554f 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/task.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/task.dart
@@ -322,7 +322,8 @@
 
     treeOptimizationTask.measure(() {
       applyTreePass(new StatementRewriter());
-      applyTreePass(new VariableMerger(minifying: compiler.enableMinification));
+      applyTreePass(new VariableMerger(minifying:
+          compiler.options.enableMinification));
       applyTreePass(new LoopRewriter());
       applyTreePass(new LogicalRewriter());
       applyTreePass(new PullIntoInitializers());
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index 0550d8d..9bb1417 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -105,7 +105,7 @@
     // digits are lost anyway.
     String representation = primitiveValue.toString();
     String alternative = null;
-    int cutoff = compiler.enableMinification ? 10000 : 1e10.toInt();
+    int cutoff = compiler.options.enableMinification ? 10000 : 1e10.toInt();
     if (primitiveValue.abs() >= cutoff) {
       alternative = _shortenExponentialRepresentation(
           primitiveValue.toStringAsExponential());
@@ -133,7 +133,7 @@
 
   @override
   jsAst.Expression visitBool(BoolConstantValue constant, [_]) {
-    if (compiler.enableMinification) {
+    if (compiler.options.enableMinification) {
       if (constant.isTrue) {
         // Use !0 for true.
         return js("!0");
diff --git a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
index 0a89b42..c821aea 100644
--- a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
+++ b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
@@ -14,8 +14,9 @@
   // this could be because the field belongs to a mixin. In such a case this
   // will return `null` and a normal field name has to be used.
   jsAst.Name _minifiedInstanceFieldPropertyName(Element element) {
-    if (backend.hasFixedBackendName(element)) {
-      return new StringBackedName(backend.getFixedBackendName(element));
+    if (backend.nativeData.hasFixedBackendName(element)) {
+      return new StringBackedName(
+          backend.nativeData.getFixedBackendName(element));
     }
 
     _FieldNamingScope names;
diff --git a/pkg/compiler/lib/src/js_backend/js_backend.dart b/pkg/compiler/lib/src/js_backend/js_backend.dart
index 9a482f0..2704c0a 100644
--- a/pkg/compiler/lib/src/js_backend/js_backend.dart
+++ b/pkg/compiler/lib/src/js_backend/js_backend.dart
@@ -14,6 +14,7 @@
 import '../common.dart';
 import '../common/backend_api.dart' show
     Backend,
+    BackendSerialization,
     ImpactTransformer,
     ForeignResolver;
 import '../common/codegen.dart' show
@@ -116,11 +117,15 @@
 
 import 'backend_helpers.dart';
 import 'backend_impact.dart';
+import 'backend_serialization.dart' show
+    JavaScriptBackendSerialization;
 import 'codegen/task.dart';
 import 'constant_system_javascript.dart';
-import 'patch_resolver.dart';
+import 'native_data.dart' show
+    NativeData;
 import 'js_interop_analysis.dart' show JsInteropAnalysis;
 import 'lookup_map_analysis.dart' show LookupMapAnalysis;
+import 'patch_resolver.dart';
 
 part 'backend.dart';
 part 'checked_mode_helpers.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 fc96572..1ba5398 100644
--- a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
@@ -70,11 +70,11 @@
         ConstantValue value = constructedConstant.fields[nameField];
         if (value.isString) {
           StringConstantValue stringValue = value;
-          backend.setJsInteropName(
+          backend.nativeData.setJsInteropName(
               e, stringValue.primitiveValue.slowToString());
         } else {
           // TODO(jacobr): report a warning if the value is not a String.
-          backend.setJsInteropName(e, '');
+          backend.nativeData.setJsInteropName(e, '');
         }
         enabledJsInterop = true;
         return;
@@ -179,7 +179,7 @@
           if (selector.namedArgumentCount > 0) return;
           int argumentCount = selector.argumentCount;
           var candidateParameterNames =
-              'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMOPQRSTUVWXYZ';
+              'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
           var parameters = new List<String>.generate(
               argumentCount, (i) => candidateParameterNames[i]);
 
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 111eb22..ca97a3a 100644
--- a/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
@@ -307,7 +307,7 @@
     // When --verbose is passed, we show the total number and set of keys that
     // were tree-shaken from lookup maps.
     Compiler compiler = backend.compiler;
-    if (compiler.verbose) {
+    if (compiler.options.verbose) {
       var sb = new StringBuffer();
       int count = 0;
       for (var info in _lookupMaps.values) {
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index bd55710..7ffe502 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -624,7 +624,7 @@
   }
 
   String _jsNameHelper(Element e) {
-    String jsInteropName = backend.getJsInteropName(e);
+    String jsInteropName = backend.nativeData.getJsInteropName(e);
     if (jsInteropName != null && jsInteropName.isNotEmpty)
       return jsInteropName;
     return e.isLibrary ? 'self' : e.name;
@@ -779,8 +779,9 @@
   jsAst.Name instanceFieldPropertyName(FieldElement element) {
     ClassElement enclosingClass = element.enclosingClass;
 
-    if (backend.hasFixedBackendName(element)) {
-      return new StringBackedName(backend.getFixedBackendName(element));
+    if (backend.nativeData.hasFixedBackendName(element)) {
+      return new StringBackedName(
+          backend.nativeData.getFixedBackendName(element));
     }
 
     // Some elements, like e.g. instances of BoxFieldElement are special.
diff --git a/pkg/compiler/lib/src/js_backend/native_data.dart b/pkg/compiler/lib/src/js_backend/native_data.dart
new file mode 100644
index 0000000..1929548
--- /dev/null
+++ b/pkg/compiler/lib/src/js_backend/native_data.dart
@@ -0,0 +1,170 @@
+// 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 js_backend.native_data;
+
+import '../common.dart';
+import '../elements/elements.dart' show
+    ClassElement,
+    Element,
+    FunctionElement,
+    MemberElement;
+
+/// Additional element information for native classes and methods and js-interop
+/// methods.
+class NativeData {
+  /// The JavaScript names for elements implemented via typed JavaScript
+  /// interop.
+  Map<Element, String> jsInteropNames = <Element, String>{};
+
+  /// The JavaScript names for native JavaScript elements implemented.
+  Map<Element, String> nativeMemberName = <Element, String>{};
+
+  /// Tag info for native JavaScript classes names. See
+  /// [setNativeClassTagInfo].
+  Map<ClassElement, String> nativeClassTagInfo = <ClassElement, String>{};
+
+  /// Returns `true` if [element] is explicitly marked as part of JsInterop.
+  bool _isJsInterop(Element element) {
+    return jsInteropNames.containsKey(element.declaration);
+  }
+
+  /// Returns [element] as an explicit part of JsInterop. The js interop name is
+  /// expected to be computed later.
+  void markAsJsInterop(Element element) {
+    jsInteropNames[element.declaration] = null;
+  }
+
+  /// Sets the explicit js interop [name] for [element].
+  void setJsInteropName(Element element, String name) {
+    assert(invariant(element,
+        isJsInterop(element),
+        message:
+          'Element $element is not js interop but given a js interop name.'));
+    jsInteropNames[element.declaration] = name;
+  }
+
+  /// Returns the explicit js interop name for [element].
+  String getJsInteropName(Element element) {
+    return jsInteropNames[element.declaration];
+  }
+
+  /// Returns `true` if [element] is part of JsInterop.
+  bool isJsInterop(Element element) {
+    // An function is part of JsInterop in the following cases:
+    // * It has a jsInteropName annotation
+    // * It is external member of a class or library tagged as JsInterop.
+    if (element.isFunction || element.isConstructor || element.isAccessor) {
+      FunctionElement function = element;
+      if (!function.isExternal) return false;
+
+      if (_isJsInterop(function)) return true;
+      if (function.isClassMember) return isJsInterop(function.contextClass);
+      if (function.isTopLevel) return isJsInterop(function.library);
+      return false;
+    } else {
+      return _isJsInterop(element);
+    }
+  }
+
+  /// Returns `true` if the name of [element] is fixed for the generated
+  /// JavaScript.
+  bool hasFixedBackendName(Element element) {
+    return isJsInterop(element) ||
+        nativeMemberName.containsKey(element.declaration);
+  }
+
+  String _jsNameHelper(Element element) {
+    String jsInteropName = jsInteropNames[element.declaration];
+    assert(invariant(element,
+        !(_isJsInterop(element) && jsInteropName == null),
+        message:
+            'Element $element is js interop but js interop name has not yet '
+            'been computed.'));
+    if (jsInteropName != null && jsInteropName.isNotEmpty) {
+      return jsInteropName;
+    }
+    return element.isLibrary ? 'self' : element.name;
+  }
+
+  /// Computes the name for [element] to use in the generated JavaScript. This
+  /// is either given through a native annotation or a js interop annotation.
+  String getFixedBackendName(Element element) {
+    String name = nativeMemberName[element.declaration];
+    if (name == null && isJsInterop(element)) {
+      // If an element isJsInterop but _isJsInterop is false that means it is
+      // considered interop as the parent class is interop.
+      name = _jsNameHelper(
+          element.isConstructor ? element.enclosingClass : element);
+      nativeMemberName[element.declaration] = name;
+    }
+    return name;
+  }
+
+  /// Whether [element] corresponds to a native JavaScript construct either
+  /// through the native mechanism (`@Native(...)` or the `native` pseudo
+  /// keyword) which is only allowed for internal libraries or via the typed
+  /// JavaScriptInterop mechanism which is allowed for user libraries.
+  bool isNative(Element element) {
+    if (isJsInterop(element)) return true;
+    if (element.isClass) {
+      return nativeClassTagInfo.containsKey(element.declaration);
+    } else {
+      return nativeMemberName.containsKey(element.declaration);
+    }
+  }
+
+  /// Sets the native [name] for the member [element]. This name is used for
+  /// [element] in the generated JavaScript.
+  void setNativeMemberName(MemberElement element, String name) {
+    // TODO(johnniwinther): Avoid setting this more than once. The enqueuer
+    // might enqueue [element] several times (before processing it) and computes
+    // name on each call to `internalAddToWorkList`.
+    assert(invariant(element,
+        nativeMemberName[element.declaration] == null ||
+        nativeMemberName[element.declaration] == name,
+        message:
+          "Native member name set inconsistently on $element: "
+          "Existing name '${nativeMemberName[element.declaration]}', "
+          "new name '$name'."));
+    nativeMemberName[element.declaration] = name;
+  }
+
+  /// Sets the native tag info for [cls].
+  ///
+  /// The tag info string contains comma-separated 'words' which are either
+  /// dispatch tags (having JavaScript identifier syntax) and directives that
+  /// begin with `!`.
+  void setNativeClassTagInfo(ClassElement cls, String tagInfo) {
+    // TODO(johnniwinther): Assert that this is only called once. The memory
+    // compiler copies pre-processed elements into a new compiler through
+    // [Compiler.onLibraryScanned] and thereby causes multiple calls to this
+    // method.
+    assert(invariant(cls,
+        nativeClassTagInfo[cls.declaration] == null ||
+        nativeClassTagInfo[cls.declaration] == tagInfo,
+        message:
+          "Native tag info set inconsistently on $cls: "
+          "Existing tag info '${nativeClassTagInfo[cls.declaration]}', "
+          "new tag info '$tagInfo'."));
+    nativeClassTagInfo[cls.declaration] = tagInfo;
+  }
+
+  /// Returns the list of native tag words for [cls].
+  List<String> getNativeTagsOfClassRaw(ClassElement cls) {
+    String quotedName = nativeClassTagInfo[cls.declaration];
+    return quotedName.substring(1, quotedName.length - 1).split(',');
+  }
+
+  /// Returns the list of non-directive native tag words for [cls].
+  List<String> getNativeTagsOfClass(ClassElement cls) {
+    return getNativeTagsOfClassRaw(cls).where(
+        (s) => !s.startsWith('!')).toList();
+  }
+
+  /// Returns `true` if [cls] has a `!nonleaf` tag word.
+  bool hasNativeTagsForcedNonLeaf(ClassElement cls) {
+    return getNativeTagsOfClassRaw(cls).contains('!nonleaf');
+  }
+}
\ No newline at end of file
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index bcede45..29aade6 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -300,7 +300,7 @@
         }
       }
     });
-    if (compiler.enableTypeAssertions) {
+    if (compiler.options.enableTypeAssertions) {
       void analyzeMethod(TypedElement method) {
         DartType memberType = method.type;
         ClassElement contextClass = Types.getClassContext(memberType);
diff --git a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
index 87f9d41..c727d56 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -169,7 +169,7 @@
                 backend.emitter.staticFunctionAccess(
                     backend.helpers.createInvocationMirror),
             'methodName':
-                js.quoteName(compiler.enableMinification
+                js.quoteName(compiler.options.enableMinification
                     ? internalName : methodName),
             'internalName': js.quoteName(internalName),
             'type': js.number(type),
@@ -227,7 +227,7 @@
   }
 
   jsAst.Statement tearOffGetter;
-  if (!compiler.useContentSecurityPolicy) {
+  if (!compiler.options.useContentSecurityPolicy) {
     jsAst.Expression tearOffAccessText =
         new jsAst.UnparsedNode(tearOffAccessExpression, compiler, false);
     tearOffGetter = js.statement('''
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
index 06aa189..77f606a 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
@@ -62,7 +62,7 @@
   void emitConstructorsForCSP(Class cls) {
     List<jsAst.Name> fieldNames = <jsAst.Name>[];
 
-    if (!compiler.useContentSecurityPolicy) return;
+    if (!compiler.options.useContentSecurityPolicy) return;
 
     if (!cls.onlyForRti && !cls.isNative) {
       fieldNames = cls.fields.map((Field field) => field.name).toList();
@@ -208,7 +208,7 @@
   /// Emits getters/setters for fields if compiling in CSP mode.
   void emitClassGettersSettersForCSP(Class cls, ClassBuilder builder) {
 
-    if (!compiler.useContentSecurityPolicy || cls.onlyForRti) return;
+    if (!compiler.options.useContentSecurityPolicy || cls.onlyForRti) return;
 
     for (Field field in cls.fields) {
       Element member = field.element;
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 30114a7..7c9b6d8 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
@@ -152,9 +152,9 @@
   TypeVariableHandler get typeVariableHandler => backend.typeVariableHandler;
 
   String get _ => space;
-  String get space => compiler.enableMinification ? "" : " ";
-  String get n => compiler.enableMinification ? "" : "\n";
-  String get N => compiler.enableMinification ? "\n" : ";\n";
+  String get space => compiler.options.enableMinification ? "" : " ";
+  String get n => compiler.options.enableMinification ? "" : "\n";
+  String get N => compiler.options.enableMinification ? "\n" : ";\n";
 
   /**
    * List of expressions and statements that will be included in the
@@ -571,7 +571,7 @@
 
   jsAst.Statement buildCspPrecompiledFunctionFor(
       OutputUnit outputUnit) {
-    if (compiler.useContentSecurityPolicy) {
+    if (compiler.options.useContentSecurityPolicy) {
       // TODO(ahe): Compute a hash code.
       // TODO(sigurdm): Avoid this precompiled function. Generated
       // constructor-functions and getter/setter functions can be stored in the
@@ -598,7 +598,7 @@
                      Fragment fragment) {
     ClassElement classElement = cls.element;
     reporter.withCurrentElement(classElement, () {
-      if (compiler.hasIncrementalSupport) {
+      if (compiler.options.hasIncrementalSupport) {
         ClassBuilder cachedBuilder =
             cachedClassBuilders.putIfAbsent(classElement, () {
               ClassBuilder builder =
@@ -711,7 +711,7 @@
           }
         }
       })(#laziesInfo)
-      ''', {'notMinified': !compiler.enableMinification,
+      ''', {'notMinified': !compiler.options.enableMinification,
             'laziesInfo': new jsAst.ArrayInitializer(laziesInfo),
             'lazy': js(lazyInitializerName),
             'isMainFragment': isMainFragment,
@@ -728,7 +728,7 @@
       laziesInfo.add(js.quoteName(field.name));
       laziesInfo.add(js.quoteName(namer.deriveLazyInitializerName(field.name)));
       laziesInfo.add(field.code);
-      if (!compiler.enableMinification) {
+      if (!compiler.options.enableMinification) {
         laziesInfo.add(js.quoteName(field.name));
       }
       if (!isMainFragment) {
@@ -763,7 +763,7 @@
            isolateProperties]);
     }
 
-    if (compiler.enableMinification) {
+    if (compiler.options.enableMinification) {
       return js('#(#,#,#)',
           [js(lazyInitializerName),
            js.quoteName(namer.globalPropertyName(element)),
@@ -805,12 +805,12 @@
 
     if (constants.isEmpty) return js.comment("No constants in program.");
     List<jsAst.Statement> parts = <jsAst.Statement>[];
-    if (compiler.hasIncrementalSupport && isMainFragment) {
+    if (compiler.options.hasIncrementalSupport && isMainFragment) {
       parts = cachedEmittedConstantsAst;
     }
     for (Constant constant in constants) {
       ConstantValue constantValue = constant.value;
-      if (compiler.hasIncrementalSupport && isMainFragment) {
+      if (compiler.options.hasIncrementalSupport && isMainFragment) {
         if (cachedEmittedConstants.contains(constantValue)) continue;
         cachedEmittedConstants.add(constantValue);
       }
@@ -1027,7 +1027,7 @@
             'makeConstListProperty': makeConstListProperty,
             'functionThatReturnsNullProperty':
                 backend.rtiEncoder.getFunctionThatReturnsNullName,
-            'hasIncrementalSupport': compiler.hasIncrementalSupport,
+            'hasIncrementalSupport': compiler.options.hasIncrementalSupport,
             'lazyInitializerProperty': lazyInitializerProperty,});
   }
 
@@ -1073,7 +1073,7 @@
   jsAst.Statement buildSupportsDirectProtoAccess() {
     jsAst.Statement supportsDirectProtoAccess;
 
-    if (compiler.hasIncrementalSupport) {
+    if (compiler.options.hasIncrementalSupport) {
       supportsDirectProtoAccess = js.statement(r'''
         var supportsDirectProtoAccess = false;
       ''');
@@ -1095,17 +1095,16 @@
   jsAst.Expression generateLibraryDescriptor(LibraryElement library,
                                              Fragment fragment) {
     var uri = "";
-    if (!compiler.enableMinification || backend.mustPreserveUris) {
+    if (!compiler.options.enableMinification || backend.mustPreserveUris) {
       uri = library.canonicalUri;
-      if (uri.scheme == 'file' && compiler.outputUri != null) {
-        uri = relativize(compiler.outputUri, library.canonicalUri, false);
+      if (uri.scheme == 'file' && compiler.options.outputUri != null) {
+        uri = relativize(
+        compiler.options.outputUri, library.canonicalUri, false);
       }
     }
 
-    String libraryName =
-        (!compiler.enableMinification || backend.mustRetainLibraryNames) ?
-        library.libraryName :
-        "";
+    String libraryName = (!compiler.options.enableMinification ||
+        backend.mustRetainLibraryNames) ? library.libraryName : "";
 
     jsAst.Fun metadata = task.metadataCollector.buildMetadataFunction(library);
 
@@ -1342,7 +1341,7 @@
 
   void checkEverythingEmitted(Iterable<Element> elements) {
     List<Element> pendingStatics;
-    if (!compiler.hasIncrementalSupport) {
+    if (!compiler.options.hasIncrementalSupport) {
       pendingStatics =
           Elements.sortedByPosition(elements.where((e) => !e.isLibrary));
 
@@ -1429,7 +1428,8 @@
       // The program builder does not collect libraries that only
       // contain typedefs that are used for reflection.
       for (LibraryElement element in remainingLibraries) {
-        assert(element is LibraryElement || compiler.hasIncrementalSupport);
+        assert(element is LibraryElement ||
+            compiler.options.hasIncrementalSupport);
         if (element is LibraryElement) {
           parts.add(generateLibraryDescriptor(element, mainFragment));
           descriptors.remove(element);
@@ -1552,7 +1552,7 @@
     })();
     """, {
       "disableVariableRenaming": js.comment("/* ::norenaming:: */"),
-      "hasIncrementalSupport": compiler.hasIncrementalSupport,
+      "hasIncrementalSupport": compiler.options.hasIncrementalSupport,
       "helper": js('this.#', [namer.incrementalHelperName]),
       "schemaChange": buildSchemaChangeFunction(),
       "addMethod": buildIncrementalAddMethod(),
@@ -1612,27 +1612,27 @@
     mainOutput.addBuffer(jsAst.createCodeBuffer(
         program, compiler, monitor: compiler.dumpInfoTask));
 
-    if (compiler.deferredMapUri != null) {
+    if (compiler.options.deferredMapUri != null) {
       outputDeferredMap();
     }
 
     if (generateSourceMap) {
-      mainOutput.add(
-          generateSourceMapTag(compiler.sourceMapUri, compiler.outputUri));
+      mainOutput.add(generateSourceMapTag(
+          compiler.options.sourceMapUri, compiler.options.outputUri));
     }
 
     mainOutput.close();
 
     if (generateSourceMap) {
       outputSourceMap(mainOutput, lineColumnCollector, '',
-          compiler.sourceMapUri, compiler.outputUri);
+          compiler.options.sourceMapUri, compiler.options.outputUri);
     }
   }
 
   /// Used by incremental compilation to patch up the prototype of
   /// [oldConstructor] for use as prototype of [newConstructor].
   jsAst.Fun buildSchemaChangeFunction() {
-    if (!compiler.hasIncrementalSupport) return null;
+    if (!compiler.options.hasIncrementalSupport) return null;
     return js('''
 function(newConstructor, oldConstructor, superclass) {
   // Invariant: newConstructor.prototype has no interesting properties besides
@@ -1665,7 +1665,7 @@
   /// top-level). [globalFunctionsAccess] is a reference to
   /// [embeddedNames.GLOBAL_FUNCTIONS].
   jsAst.Fun buildIncrementalAddMethod() {
-    if (!compiler.hasIncrementalSupport) return null;
+    if (!compiler.options.hasIncrementalSupport) return null;
     return js(r"""
 function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
   var arrayOrFunction = originalDescriptor[name];
@@ -1992,7 +1992,7 @@
         // in stack traces and profile entries.
         body.add(js.statement('var dart = #', libraryDescriptor));
 
-        if (compiler.useContentSecurityPolicy) {
+        if (compiler.options.useContentSecurityPolicy) {
           body.add(buildCspPrecompiledFunctionFor(outputUnit));
         }
         body.add(
@@ -2067,8 +2067,8 @@
 
       if (generateSourceMap) {
         Uri mapUri, partUri;
-        Uri sourceMapUri = compiler.sourceMapUri;
-        Uri outputUri = compiler.outputUri;
+        Uri sourceMapUri = compiler.options.sourceMapUri;
+        Uri outputUri = compiler.options.outputUri;
 
         String partName = "$partPrefix.part";
 
@@ -2076,14 +2076,16 @@
           String mapFileName = partName + ".js.map";
           List<String> mapSegments = sourceMapUri.pathSegments.toList();
           mapSegments[mapSegments.length - 1] = mapFileName;
-          mapUri = compiler.sourceMapUri.replace(pathSegments: mapSegments);
+          mapUri = compiler.options.sourceMapUri
+              .replace(pathSegments: mapSegments);
         }
 
         if (outputUri != null) {
           String partFileName = partName + ".js";
           List<String> partSegments = outputUri.pathSegments.toList();
           partSegments[partSegments.length - 1] = partFileName;
-          partUri = compiler.outputUri.replace(pathSegments: partSegments);
+          partUri = compiler.options.outputUri.replace(
+              pathSegments: partSegments);
         }
 
         output.add(generateSourceMapTag(mapUri, partUri));
@@ -2102,7 +2104,7 @@
   jsAst.Comment buildGeneratedBy() {
     List<String> options = [];
     if (compiler.mirrorsLibrary != null) options.add('mirrors');
-    if (compiler.useContentSecurityPolicy) options.add("CSP");
+    if (compiler.options.useContentSecurityPolicy) options.add("CSP");
     return new jsAst.Comment(generatedBy(compiler, flavor: options.join(", ")));
   }
 
@@ -2130,13 +2132,14 @@
     mapping["_comment"] = "This mapping shows which compiled `.js` files are "
         "needed for a given deferred library import.";
     mapping.addAll(compiler.deferredLoadTask.computeDeferredMap());
-    compiler.outputProvider(compiler.deferredMapUri.path, 'deferred_map')
+    compiler.outputProvider(
+            compiler.options.deferredMapUri.path, 'deferred_map')
         ..add(const JsonEncoder.withIndent("  ").convert(mapping))
         ..close();
   }
 
   void invalidateCaches() {
-    if (!compiler.hasIncrementalSupport) return;
+    if (!compiler.options.hasIncrementalSupport) return;
     if (cachedElements.isEmpty) return;
     for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) {
       if (element.isInstanceMember) {
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
index f8911bd..d342642 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
@@ -122,7 +122,7 @@
     List<jsAst.Statement> statements = <jsAst.Statement>[];
     if (trivialNsmHandlers.length == 0) return statements;
 
-    bool minify = compiler.enableMinification;
+    bool minify = compiler.options.enableMinification;
     bool useDiffEncoding = minify && trivialNsmHandlers.length > 30;
 
     // Find out how many selectors there are with the special calling
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
index ecd8a4b..2481d12 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
@@ -81,9 +81,10 @@
   String unmangledNameIndex = backend.mustRetainMetadata
       ? ' 3 * optionalParameterCount + 2 * requiredParameterCount + 3'
       : ' 2 * optionalParameterCount + requiredParameterCount + 3';
-  String receiverParamName = compiler.enableMinification ? "r" : "receiver";
-  String valueParamName = compiler.enableMinification ? "v" : "value";
-  String space = compiler.enableMinification ? "" : " ";
+  String receiverParamName = compiler.options.enableMinification
+      ? "r" : "receiver";
+  String valueParamName = compiler.options.enableMinification ? "v" : "value";
+  String space = compiler.options.enableMinification ? "" : " ";
   String _ = space;
 
   String specProperty = '"${namer.nativeSpecProperty}"';  // "%"
@@ -109,12 +110,12 @@
      'enabledInvokeOn': compiler.enabledInvokeOn,
      'interceptedNames': interceptedNamesAccess,
      'interceptedNamesSet': emitter.generateInterceptedNamesSet(),
-     'notInCspMode': !compiler.useContentSecurityPolicy,
-     'inCspMode': compiler.useContentSecurityPolicy,
+     'notInCspMode': !compiler.options.useContentSecurityPolicy,
+     'inCspMode': compiler.options.useContentSecurityPolicy,
      'deferredAction': namer.deferredAction,
      'hasIsolateSupport': program.hasIsolateSupport,
      'fieldNamesProperty': js.string(Emitter.FIELD_NAMES_PROPERTY_NAME),
-     'hasIncrementalSupport': compiler.hasIncrementalSupport,
+     'hasIncrementalSupport': compiler.options.hasIncrementalSupport,
      'incrementalHelper': namer.accessIncrementalHelper,
      'createNewIsolateFunction': createNewIsolateFunctionAccess,
      'isolateName': namer.isolateName,
diff --git a/pkg/compiler/lib/src/js_emitter/headers.dart b/pkg/compiler/lib/src/js_emitter/headers.dart
index 67fd4a2..2d15d11 100644
--- a/pkg/compiler/lib/src/js_emitter/headers.dart
+++ b/pkg/compiler/lib/src/js_emitter/headers.dart
@@ -7,7 +7,9 @@
 
 String generatedBy(Compiler compiler, {String flavor: ""}) {
   String suffix = '';
-  if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}';
+  if (compiler.options.hasBuildId) {
+    suffix = ' version: ${compiler.options.buildId}';
+  }
   if (flavor != "") flavor = " ($flavor)";
   return '// Generated by dart2js$flavor, '
       'the Dart to JavaScript compiler$suffix.';
diff --git a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
index 3d3270c..73eeeb74 100644
--- a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
@@ -246,7 +246,7 @@
       // checked mode, so we don't optimize the interceptor if the
       // compiler has type assertions enabled.
       if (selector.isIndexSet
-          && (compiler.enableTypeAssertions || !containsArray)) {
+          && (compiler.options.enableTypeAssertions || !containsArray)) {
         return null;
       }
       if (!containsArray && !containsString) {
diff --git a/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
index a0b9b48..d2dd9fd 100644
--- a/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
@@ -193,7 +193,9 @@
 
   String buildGeneratedBy(compiler) {
     var suffix = '';
-    if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}';
+    if (compiler.options.hasBuildId) {
+      suffix = ' version: ${compiler.options.buildId}';
+    }
     return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n';
   }
 
diff --git a/pkg/compiler/lib/src/js_emitter/main_call_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/main_call_stub_generator.dart
index d3204e9..2efc6e4 100644
--- a/pkg/compiler/lib/src/js_emitter/main_call_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/main_call_stub_generator.dart
@@ -32,7 +32,7 @@
       Element isolateMain =
         helpers.isolateHelperLibrary.find(BackendHelpers.START_ROOT_ISOLATE);
       mainCallClosure = _buildIsolateSetupClosure(main, isolateMain);
-    } else if (compiler.hasIncrementalSupport) {
+    } else if (compiler.options.hasIncrementalSupport) {
       mainCallClosure = js(
           'function() { return #(); }',
           emitterTask.staticFunctionAccess(main));
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index fdea7ff..b51c470 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -297,7 +297,7 @@
         node, _compiler, renamerForNames: nameToKey);
     return _globalMetadataMap.putIfAbsent(printed, () {
       _BoundMetadataEntry result = new _BoundMetadataEntry(node);
-      if (_compiler.hasIncrementalSupport) {
+      if (_compiler.options.hasIncrementalSupport) {
         result.finalize(_globalMetadataCounter++);
       }
       return result;
@@ -337,7 +337,7 @@
       _BoundMetadataEntry result = new _BoundMetadataEntry(
           _computeTypeRepresentation(type,
                                      ignoreTypeVariables: ignoreTypeVariables));
-      if (_compiler.hasIncrementalSupport) {
+      if (_compiler.options.hasIncrementalSupport) {
         result.finalize(_globalTypesCounter++);
       }
       return result;
@@ -376,7 +376,7 @@
 
     jsAst.ArrayInitializer finalizeMap(Map<dynamic, _BoundMetadataEntry> map) {
       // When in incremental mode, we allocate entries eagerly.
-      if (_compiler.hasIncrementalSupport) {
+      if (_compiler.options.hasIncrementalSupport) {
         return new jsAst.ArrayInitializer(map.values.toList());
       }
 
diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
index 378b4a53..dab8fe0 100644
--- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
@@ -139,7 +139,7 @@
       if (backend.isJsInterop(classElement)) {
         needed = true;  // TODO(jacobr): we don't need all interop classes.
       } else if (cls.isNative &&
-                 backend.hasNativeTagsForcedNonLeaf(classElement)) {
+                 backend.nativeData.hasNativeTagsForcedNonLeaf(classElement)) {
         needed = true;
         nonLeafClasses.add(cls);
       }
@@ -159,7 +159,8 @@
     for (Class cls in classes) {
       if (!cls.isNative) continue;
       if (backend.isJsInterop(cls.element)) continue;
-      List<String> nativeTags = backend.getNativeTagsOfClass(cls.element);
+      List<String> nativeTags =
+          backend.nativeData.getNativeTagsOfClass(cls.element);
 
       if (nonLeafClasses.contains(cls) ||
           extensionPoints.containsKey(cls)) {
@@ -315,7 +316,7 @@
     assert(invariant(member, nativeMethods.contains(member)));
     // When calling a JS method, we call it with the native name, and only the
     // arguments up until the last one provided.
-    target = backend.getFixedBackendName(member);
+    target = backend.nativeData.getFixedBackendName(member);
 
     if (isInterceptedMethod) {
       receiver = argumentsBuffer[0];
diff --git a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
index c006e05..8325fe1 100644
--- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -118,7 +118,7 @@
     });
 
     var body;  // List or jsAst.Statement.
-    if (backend.hasFixedBackendName(member)) {
+    if (backend.nativeData.hasFixedBackendName(member)) {
       body = emitterTask.nativeEmitter.generateParameterStubStatements(
           member, isInterceptedMethod, namer.invocationName(selector),
           parametersBuffer, argumentsBuffer,
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
index 268d671..2f5d257 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
@@ -148,7 +148,8 @@
 
     JavaScriptConstantCompiler handler = backend.constants;
     List<ConstantValue> constants = handler.getConstantsForEmission(
-        compiler.hasIncrementalSupport ? null : emitter.compareConstants);
+        compiler.options.hasIncrementalSupport ? null
+            : emitter.compareConstants);
     for (ConstantValue constant in constants) {
       if (emitter.isConstantInlinedOrAlreadyEmitted(constant)) continue;
 
@@ -314,4 +315,4 @@
     computeNeededStaticNonFinalFields();
     computeNeededLibraries();
   }
-}
\ No newline at end of file
+}
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart b/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
index 894bd92..09eabaf 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
@@ -99,7 +99,7 @@
         js.Name accessorName = namer.fieldAccessorName(field);
         js.Name fieldName = namer.fieldPropertyName(field);
         bool needsCheckedSetter = false;
-        if (compiler.enableTypeAssertions
+        if (compiler.options.enableTypeAssertions
             && needsSetter
             && !canAvoidGeneratedCheckedSetter(field)) {
           needsCheckedSetter = true;
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 42f7138..7aef3a3 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
@@ -416,7 +416,7 @@
               FunctionElement fn = member;
               functionType = fn.type;
             } else if (member.isGetter) {
-              if (_compiler.trustTypeAnnotations) {
+              if (_compiler.options.trustTypeAnnotations) {
                 GetterElement getter = member;
                 DartType returnType = getter.type.returnType;
                 if (returnType.isFunctionType) {
@@ -522,7 +522,7 @@
   ///
   /// Returns a class that contains the fields of a class.
   Class buildFieldsHackForIncrementalCompilation(ClassElement element) {
-    assert(_compiler.hasIncrementalSupport);
+    assert(_compiler.options.hasIncrementalSupport);
 
     List<Field> instanceFields = _buildFields(element, false);
     js.Name name = namer.className(element);
@@ -694,7 +694,7 @@
     return backend.isAccessibleByReflection(method) ||
         // During incremental compilation, we have to assume that reflection
         // *might* get enabled.
-        _compiler.hasIncrementalSupport;
+        _compiler.options.hasIncrementalSupport;
   }
 
   bool _methodCanBeApplied(FunctionElement method) {
@@ -704,7 +704,7 @@
 
   // TODO(herhut): Refactor incremental compilation and remove method.
   Method buildMethodHackForIncrementalCompilation(FunctionElement element) {
-    assert(_compiler.hasIncrementalSupport);
+    assert(_compiler.options.hasIncrementalSupport);
     if (element.isInstanceMember) {
       return _buildMethod(element);
     } else {
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index 11826c3..056345b 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -218,7 +218,7 @@
           NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE);
     }
 
-    if (compiler.deferredMapUri != null) {
+    if (compiler.options.deferredMapUri != null) {
       writeDeferredMap();
     }
 
@@ -228,7 +228,7 @@
 
   /// Generates a simple header that provides the compiler's build id.
   js.Comment buildGeneratedBy() {
-    String flavor = compiler.useContentSecurityPolicy
+    String flavor = compiler.options.useContentSecurityPolicy
         ? 'fast startup, CSP'
         : 'fast startup';
     return new js.Comment(generatedBy(compiler, flavor: flavor));
@@ -284,15 +284,15 @@
         monitor: compiler.dumpInfoTask));
 
     if (shouldGenerateSourceMap) {
-      mainOutput.add(
-          generateSourceMapTag(compiler.sourceMapUri, compiler.outputUri));
+      mainOutput.add(generateSourceMapTag(
+          compiler.options.sourceMapUri, compiler.options.outputUri));
     }
 
     mainOutput.close();
 
     if (shouldGenerateSourceMap) {
       outputSourceMap(mainOutput, lineColumnCollector, '',
-          compiler.sourceMapUri, compiler.outputUri);
+          compiler.options.sourceMapUri, compiler.options.outputUri);
     }
   }
 
@@ -348,8 +348,8 @@
 
     if (shouldGenerateSourceMap) {
       Uri mapUri, partUri;
-      Uri sourceMapUri = compiler.sourceMapUri;
-      Uri outputUri = compiler.outputUri;
+      Uri sourceMapUri = compiler.options.sourceMapUri;
+      Uri outputUri = compiler.options.outputUri;
       String partName = "$hunkPrefix.$partExtension";
       String hunkFileName = "$hunkPrefix.$deferredExtension";
 
@@ -357,13 +357,15 @@
         String mapFileName = hunkFileName + ".map";
         List<String> mapSegments = sourceMapUri.pathSegments.toList();
         mapSegments[mapSegments.length - 1] = mapFileName;
-        mapUri = compiler.sourceMapUri.replace(pathSegments: mapSegments);
+        mapUri = compiler.options.sourceMapUri
+            .replace(pathSegments: mapSegments);
       }
 
       if (outputUri != null) {
         List<String> partSegments = outputUri.pathSegments.toList();
         partSegments[partSegments.length - 1] = hunkFileName;
-        partUri = compiler.outputUri.replace(pathSegments: partSegments);
+        partUri = compiler.options.outputUri
+            .replace(pathSegments: partSegments);
       }
 
       output.add(generateSourceMapTag(mapUri, partUri));
@@ -416,7 +418,8 @@
     mapping["_comment"] = "This mapping shows which compiled `.js` files are "
         "needed for a given deferred library import.";
     mapping.addAll(compiler.deferredLoadTask.computeDeferredMap());
-    compiler.outputProvider(compiler.deferredMapUri.path, 'deferred_map')
+    compiler.outputProvider(
+          compiler.options.deferredMapUri.path, 'deferred_map')
       ..add(const JsonEncoder.withIndent("  ").convert(mapping))
       ..close();
   }
diff --git a/pkg/compiler/lib/src/library_loader.dart b/pkg/compiler/lib/src/library_loader.dart
index 238d393..68f6008 100644
--- a/pkg/compiler/lib/src/library_loader.dart
+++ b/pkg/compiler/lib/src/library_loader.dart
@@ -369,8 +369,11 @@
         return reporter.withCurrentElement(library, () {
           return measure(() {
             currentHandler.computeExports();
-            LoadedLibraries loadedLibraries =
-                new _LoadedLibraries(library, currentHandler.nodeMap, this);
+            LoadedLibraries loadedLibraries = new _LoadedLibraries(
+                library,
+                currentHandler.newLibraries,
+                currentHandler.nodeMap,
+                this);
             currentHandler = null;
             return compiler.onLibrariesLoaded(loadedLibraries)
                 .then((_) => library);
@@ -596,8 +599,8 @@
   Future<LibraryElement> loadDeserializedLibrary(
       LibraryDependencyHandler handler,
       LibraryElement library) {
-    compiler.onLibraryCreated(library);
     libraryCanonicalUriMap[library.canonicalUri] = library;
+    handler.registerNewLibrary(library);
     return compiler.onLibraryScanned(library, handler).then((_) {
       return Future.forEach(library.imports, (ImportElement import) {
         return createLibrary(handler, library, import.uri);
@@ -1158,6 +1161,7 @@
  */
 class LibraryDependencyHandler implements LibraryLoader {
   final _LibraryLoaderTask task;
+  final List<LibraryElement> _newLibraries = <LibraryElement>[];
 
   /**
    * Newly loaded libraries and their corresponding node in the library
@@ -1174,8 +1178,8 @@
 
   DiagnosticReporter get reporter => task.reporter;
 
-  /// The libraries loaded with this handler.
-  Iterable<LibraryElement> get loadedLibraries => nodeMap.keys;
+  /// The libraries created with this handler.
+  Iterable<LibraryElement> get newLibraries => _newLibraries;
 
   /**
    * Performs a fixed-point computation on the export scopes of all registered
@@ -1264,8 +1268,11 @@
    * Registers [library] for the processing of its import/export scope.
    */
   void registerNewLibrary(LibraryElement library) {
-    nodeMap[library] = new LibraryDependencyNode(library);
     compiler.onLibraryCreated(library);
+    _newLibraries.add(library);
+    if (!library.exportsHandled) {
+      nodeMap[library] = new LibraryDependencyNode(library);
+    }
   }
 
   /**
@@ -1314,8 +1321,12 @@
   final Map<Uri, LibraryElement> loadedLibraries = <Uri, LibraryElement>{};
   final Map<LibraryElement, LibraryDependencyNode> nodeMap;
 
-  _LoadedLibraries(this.rootLibrary, this.nodeMap, this.task) {
-    nodeMap.keys.forEach((LibraryElement loadedLibrary) {
+  _LoadedLibraries(
+      this.rootLibrary,
+      Iterable<LibraryElement> libraries,
+      this.nodeMap,
+      this.task) {
+    libraries.forEach((LibraryElement loadedLibrary) {
       loadedLibraries[loadedLibrary.canonicalUri] = loadedLibrary;
     });
   }
@@ -1406,4 +1417,6 @@
 
     computeSuffixes(rootLibrary, const Link<Uri>());
   }
+
+  String toString() => 'root=$rootLibrary,libraries=${loadedLibraries.keys}';
 }
diff --git a/pkg/compiler/lib/src/mirrors/analyze.dart b/pkg/compiler/lib/src/mirrors/analyze.dart
index ad3c0ea..313cc92 100644
--- a/pkg/compiler/lib/src/mirrors/analyze.dart
+++ b/pkg/compiler/lib/src/mirrors/analyze.dart
@@ -9,6 +9,7 @@
 import 'source_mirrors.dart';
 import 'dart2js_mirrors.dart' show Dart2JsMirrorSystem;
 import '../../compiler.dart' as api;
+import '../../compiler_new.dart' as new_api;
 import '../apiimpl.dart' as apiimpl;
 import '../compiler.dart' show Compiler;
 import '../old_to_new_api.dart';
@@ -58,12 +59,13 @@
       new LegacyCompilerInput(inputProvider),
       new LegacyCompilerOutput(),
       new LegacyCompilerDiagnostics(internalDiagnosticHandler),
-      libraryRoot,
-      packageRoot,
-      options,
-      const {},
-      packageConfig,
-      findPackages);
+      new new_api.CompilerOptions.parse(
+          libraryRoot: libraryRoot,
+          packageRoot: packageRoot,
+          options: options,
+          environment: const {},
+          packageConfig: packageConfig,
+          packagesDiscoveryProvider: findPackages));
   compiler.librariesToAnalyzeWhenRun = libraries;
   return compiler.run(null).then((bool success) {
     if (success && !compilationFailed) {
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 3921b8e..d0fd80f 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -706,8 +706,8 @@
     // but otherwise we would include a lot of code by default).
     // TODO(sigmund,sra): consider doing something better for numeric types.
     behavior.typesReturned.add(
-        !isInterop || compiler.trustJSInteropTypeAnnotations ? returnType
-        : const DynamicType());
+        !isInterop || compiler.options.trustJSInteropTypeAnnotations
+            ? returnType : const DynamicType());
     if (!type.returnType.isVoid) {
       // Declared types are nullable.
       behavior.typesReturned.add(compiler.coreTypes.nullType);
@@ -734,8 +734,8 @@
     bool isInterop = compiler.backend.isJsInterop(field);
     // TODO(sigmund,sra): consider doing something better for numeric types.
     behavior.typesReturned.add(
-        !isInterop || compiler.trustJSInteropTypeAnnotations ? type
-        : const DynamicType());
+        !isInterop || compiler.options.trustJSInteropTypeAnnotations
+            ? type : const DynamicType());
     // Declared types are nullable.
     behavior.typesReturned.add(resolution.coreTypes.nullType);
     behavior._capture(type, resolution,
@@ -859,7 +859,7 @@
           typesInstantiated.add(type);
         }
 
-        if (!compiler.trustJSInteropTypeAnnotations ||
+        if (!compiler.options.trustJSInteropTypeAnnotations ||
           type.isDynamic || type.isObject) {
           // By saying that only JS-interop types can be created, we prevent
           // pulling in every other native type (e.g. all of dart:html) when a
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index 738a304..0f5b985 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -141,7 +141,7 @@
   CoreTypes get coreTypes => compiler.coreTypes;
 
   void processNativeClasses(Iterable<LibraryElement> libraries) {
-    if (compiler.hasIncrementalSupport) {
+    if (compiler.options.hasIncrementalSupport) {
       // Since [Set.add] returns bool if an element was added, this restricts
       // [libraries] to ones that haven't already been processed. This saves
       // time during incremental compiles.
@@ -236,7 +236,18 @@
    * Returns the source string of the class named in the extends clause, or
    * `null` if there is no extends clause.
    */
-  String findExtendsNameOfClass(BaseClassElementX classElement) {
+  String findExtendsNameOfClass(ClassElement classElement) {
+    if (classElement.isResolved) {
+      ClassElement superClass = classElement.superclass;
+      while (superClass != null) {
+        if (!superClass.isUnnamedMixinApplication) {
+          return superClass.name;
+        }
+        superClass = superClass.superclass;
+      }
+      return null;
+    }
+
     //  "class B extends A ... {}"  --> "A"
     //  "class B extends foo.A ... {}"  --> "A"
     //  "class B<T> extends foo.A<T,T> with M1, M2 ... {}"  --> "A"
@@ -368,9 +379,9 @@
     flushing = false;
   }
 
-  processClass(BaseClassElementX classElement, cause) {
+  processClass(ClassElement classElement, cause) {
     // TODO(ahe): Fix this assertion to work in incremental compilation.
-    assert(compiler.hasIncrementalSupport ||
+    assert(compiler.options.hasIncrementalSupport ||
            !registeredClasses.contains(classElement));
 
     bool firstTime = registeredClasses.isEmpty;
@@ -407,34 +418,40 @@
     });
   }
 
-  handleFieldAnnotations(Element element) {
+  void handleFieldAnnotations(Element element) {
+    if (compiler.serialization.isDeserialized(element)) {
+      return;
+    }
     if (backend.isNative(element.enclosingElement)) {
       // Exclude non-instance (static) fields - they not really native and are
       // compiled as isolate globals.  Access of a property of a constructor
       // function or a non-method property in the prototype chain, must be coded
       // using a JS-call.
       if (element.isInstanceMember) {
-        setNativeName(element);
+        _setNativeName(element);
       }
     }
   }
 
-  handleMethodAnnotations(Element method) {
+  void handleMethodAnnotations(Element method) {
+    if (compiler.serialization.isDeserialized(method)) {
+      return;
+    }
     if (isNativeMethod(method)) {
       if (method.isStatic) {
-        setNativeNameForStaticMethod(method);
+        _setNativeNameForStaticMethod(method);
       } else {
-        setNativeName(method);
+        _setNativeName(method);
       }
     }
   }
 
   /// Sets the native name of [element], either from an annotation, or
   /// defaulting to the Dart name.
-  void setNativeName(MemberElement element) {
+  void _setNativeName(MemberElement element) {
     String name = findJsNameFromAnnotation(element);
     if (name == null) name = element.name;
-    backend.setNativeMemberName(element, name);
+    backend.nativeData.setNativeMemberName(element, name);
   }
 
   /// Sets the native name of the static native method [element], using the
@@ -445,20 +462,21 @@
   ///    use the declared @JSName as the expression
   /// 3. If [element] does not have a @JSName annotation, qualify the name of
   ///    the method with the @Native name of the enclosing class.
-  void setNativeNameForStaticMethod(MethodElement element) {
+  void _setNativeNameForStaticMethod(MethodElement element) {
     String name = findJsNameFromAnnotation(element);
     if (name == null) name = element.name;
     if (isIdentifier(name)) {
       List<String> nativeNames =
-          backend.getNativeTagsOfClassRaw(element.enclosingClass);
+          backend.nativeData.getNativeTagsOfClassRaw(element.enclosingClass);
       if (nativeNames.length != 1) {
         reporter.internalError(element,
             'Unable to determine a native name for the enclosing class, '
             'options: $nativeNames');
       }
-      backend.setNativeMemberName(element, '${nativeNames[0]}.$name');
+      backend.nativeData.setNativeMemberName(
+          element, '${nativeNames[0]}.$name');
     } else {
-      backend.setNativeMemberName(element, name);
+      backend.nativeData.setNativeMemberName(element, name);
     }
   }
 
@@ -584,7 +602,7 @@
   Map<String, ClassElement> tagOwner = new Map<String, ClassElement>();
 
   NativeResolutionEnqueuer(Enqueuer world, Compiler compiler)
-    : super(world, compiler, compiler.enableNativeLiveTypeAnalysis);
+    : super(world, compiler, compiler.options.enableNativeLiveTypeAnalysis);
 
   void processNativeClass(ClassElement classElement) {
     super.processNativeClass(classElement);
@@ -593,7 +611,7 @@
     if (backend.isJsInterop(classElement)) return;
     // Since we map from dispatch tags to classes, a dispatch tag must be used
     // on only one native class.
-    for (String tag in backend.getNativeTagsOfClass(classElement)) {
+    for (String tag in backend.nativeData.getNativeTagsOfClass(classElement)) {
       ClassElement owner = tagOwner[tag];
       if (owner != null) {
         if (owner != classElement) {
@@ -670,7 +688,7 @@
   final Set<ClassElement> doneAddSubtypes = new Set<ClassElement>();
 
   NativeCodegenEnqueuer(Enqueuer world, Compiler compiler, this.emitter)
-    : super(world, compiler, compiler.enableNativeLiveTypeAnalysis);
+    : super(world, compiler, compiler.options.enableNativeLiveTypeAnalysis);
 
   void processNativeClasses(Iterable<LibraryElement> libraries) {
     super.processNativeClasses(libraries);
diff --git a/pkg/compiler/lib/src/native/native.dart b/pkg/compiler/lib/src/native/native.dart
index 4a1a641..5a1af7c 100644
--- a/pkg/compiler/lib/src/native/native.dart
+++ b/pkg/compiler/lib/src/native/native.dart
@@ -30,7 +30,7 @@
       || libraryName == 'dart:web_audio'
       || libraryName == 'dart:web_gl'
       || libraryName == 'dart:web_sql'
-      || compiler.allowNativeExtensions) {
+      || compiler.options.allowNativeExtensions) {
     return true;
   }
   return false;
diff --git a/pkg/compiler/lib/src/native/ssa.dart b/pkg/compiler/lib/src/native/ssa.dart
index 7555590..a14f7ad 100644
--- a/pkg/compiler/lib/src/native/ssa.dart
+++ b/pkg/compiler/lib/src/native/ssa.dart
@@ -54,7 +54,7 @@
   //      hasBody = true
   bool hasBody = false;
   assert(backend.isNative(element));
-  String nativeMethodName = backend.getFixedBackendName(element);
+  String nativeMethodName = backend.nativeData.getFixedBackendName(element);
   if (nativeBody != null) {
     LiteralString jsCode = nativeBody.asLiteralString();
     String str = jsCode.dartString.slowToString();
diff --git a/pkg/compiler/lib/src/patch_parser.dart b/pkg/compiler/lib/src/patch_parser.dart
index 593b08f..fd747e9 100644
--- a/pkg/compiler/lib/src/patch_parser.dart
+++ b/pkg/compiler/lib/src/patch_parser.dart
@@ -463,7 +463,7 @@
       String native = getNativeAnnotation(annotation);
       if (native != null) {
         JavaScriptBackend backend = compiler.backend;
-        backend.setNativeClassTagInfo(element, native);
+        backend.nativeData.setNativeClassTagInfo(element, native);
         return native;
       }
     }
@@ -496,7 +496,7 @@
     bool hasJsInterop = hasJsNameAnnotation(annotation);
     if (hasJsInterop) {
       JavaScriptBackend backend = compiler.backend;
-      backend.markAsJsInterop(element);
+      backend.nativeData.markAsJsInterop(element);
     }
     // Due to semantics of apply in the baseclass we have to return null to
     // indicate that no match was found.
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index 5821afa..69f9786 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -180,7 +180,7 @@
           ? Scope.buildEnclosingScope(element) : element.buildScope(),
       // The type annotations on a typedef do not imply type checks.
       // TODO(karlklose): clean this up (dartbug.com/8870).
-      inCheckContext = compiler.enableTypeAssertions &&
+      inCheckContext = compiler.options.enableTypeAssertions &&
           !element.isLibrary &&
           !element.isTypedef &&
           !element.enclosingElement.isTypedef,
@@ -496,7 +496,7 @@
   }
 
   ResolutionResult visitAssert(Assert node) {
-    if (!compiler.enableAssertMessage) {
+    if (!compiler.options.enableAssertMessage) {
       if (node.hasMessage) {
         reporter.reportErrorMessage(
             node, MessageKind.EXPERIMENTAL_ASSERT_MESSAGE);
diff --git a/pkg/compiler/lib/src/resolution/resolution.dart b/pkg/compiler/lib/src/resolution/resolution.dart
index b0fc586..f628e83 100644
--- a/pkg/compiler/lib/src/resolution/resolution.dart
+++ b/pkg/compiler/lib/src/resolution/resolution.dart
@@ -266,7 +266,8 @@
             tree, MessageKind.FUNCTION_WITH_INITIALIZER);
       }
 
-      if (!compiler.analyzeSignaturesOnly || tree.isRedirectingFactory) {
+      if (!compiler.options.analyzeSignaturesOnly ||
+          tree.isRedirectingFactory) {
         // We need to analyze the redirecting factory bodies to ensure that
         // we can analyze compile-time constants.
         visitor.visit(tree.body);
diff --git a/pkg/compiler/lib/src/resolution/signatures.dart b/pkg/compiler/lib/src/resolution/signatures.dart
index df165a6..0fc9aac 100644
--- a/pkg/compiler/lib/src/resolution/signatures.dart
+++ b/pkg/compiler/lib/src/resolution/signatures.dart
@@ -342,7 +342,7 @@
       returnType = element.enclosingClass.thisType;
       // Because there is no type annotation for the return type of
       // this element, we explicitly add one.
-      if (compiler.enableTypeAssertions) {
+      if (compiler.options.enableTypeAssertions) {
         registry.registerTypeUse(new TypeUse.checkedModeCheck(returnType));
       }
     } else {
diff --git a/pkg/compiler/lib/src/scanner/scanner_task.dart b/pkg/compiler/lib/src/scanner/scanner_task.dart
index 17b3dbc..98be820 100644
--- a/pkg/compiler/lib/src/scanner/scanner_task.dart
+++ b/pkg/compiler/lib/src/scanner/scanner_task.dart
@@ -46,8 +46,8 @@
   void scanElements(CompilationUnitElement compilationUnit) {
     Script script = compilationUnit.script;
     Token tokens = new Scanner(script.file,
-        includeComments: compiler.preserveComments).tokenize();
-    if (compiler.preserveComments) {
+        includeComments: compiler.options.preserveComments).tokenize();
+    if (compiler.options.preserveComments) {
       tokens = compiler.processAndStripComments(tokens);
     }
     compiler.dietParser.dietParse(compilationUnit, tokens);
diff --git a/pkg/compiler/lib/src/serialization/element_serialization.dart b/pkg/compiler/lib/src/serialization/element_serialization.dart
index 173dd1e..9cea9d2 100644
--- a/pkg/compiler/lib/src/serialization/element_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/element_serialization.dart
@@ -19,6 +19,7 @@
   LIBRARY,
   COMPILATION_UNIT,
   CLASS,
+  ENUM,
   GENERATIVE_CONSTRUCTOR,
   FACTORY_CONSTRUCTOR,
   TOPLEVEL_FIELD,
@@ -33,6 +34,7 @@
   INSTANCE_FUNCTION,
   INSTANCE_GETTER,
   INSTANCE_SETTER,
+  LOCAL_FUNCTION,
   TYPEDEF,
   TYPEVARIABLE,
   PARAMETER,
@@ -79,16 +81,16 @@
 
 class SerializerUtil {
   /// Serialize the declared members of [element] into [encoder].
-  static void serializeMembers(ScopeContainerElement element,
+  static void serializeMembers(Iterable<Element> members,
                                ObjectEncoder encoder) {
     MapEncoder mapEncoder = encoder.createMap(Key.MEMBERS);
-    element.forEachLocalMember((Element member) {
+    for (Element member in members) {
       String name = member.name;
       if (member.isSetter) {
         name = '$name,=';
       }
       mapEncoder.setElement(name, member);
-    });
+    }
   }
 
   /// Serialize the source position of [element] into [encoder].
@@ -116,24 +118,25 @@
   }
 
   /// Returns a function that adds the underlying declared elements for a
-  /// particular element into [list].
+  /// particular element into [set].
   ///
   /// For instance, for an [AbstractFieldElement] the getter and setter elements
   /// are added, if available.
-  static flattenElements(List<Element> list) {
+  static flattenElements(Set<Element> set) {
     return (Element element) {
+      if (element.isPatch) return;
       // TODO(johnniwinther): Handle ambiguous elements.
       if (element.isAmbiguous) return;
       if (element.isAbstractField) {
         AbstractFieldElement abstractField = element;
         if (abstractField.getter != null) {
-          list.add(abstractField.getter);
+          set.add(abstractField.getter);
         }
         if (abstractField.setter != null) {
-          list.add(abstractField.setter);
+          set.add(abstractField.setter);
         }
       } else {
-        list.add(element);
+        set.add(element);
       }
     };
   }
@@ -149,26 +152,68 @@
     return null;
   }
 
+  static List<Element> getMembers(LibraryElement element) {
+    List<Element> members = <Element>[];
+    element.implementation.forEachLocalMember((Element member) {
+      if (!member.isPatch) {
+        members.add(member);
+      }
+    });
+    return members;
+  }
+
+  static List<CompilationUnitElement> getCompilationUnits(
+      LibraryElement element) {
+    List<CompilationUnitElement> compilationUnits = <CompilationUnitElement>[];
+    compilationUnits.addAll(element.compilationUnits.toList());
+    if (element.isPatched) {
+      compilationUnits.addAll(element.implementation.compilationUnits.toList());
+    }
+    return compilationUnits;
+  }
+
+  static List<ImportElement> getImports(LibraryElement element) {
+    List<ImportElement> imports = <ImportElement>[];
+    imports.addAll(element.imports);
+    if (element.isPatched) {
+      imports.addAll(element.implementation.imports);
+    }
+    return imports;
+  }
+
+  static List<Element> getImportedElements(
+      LibraryElement element) {
+    Set<Element> importedElements = new Set<Element>();
+    element.forEachImport(SerializerUtil.flattenElements(importedElements));
+    if (element.isPatched) {
+      element.implementation.forEachImport(
+          SerializerUtil.flattenElements(importedElements));
+    }
+    return importedElements.toList();
+  }
+
+  static List<Element> getExportedElements(
+      LibraryElement element) {
+    Set<Element> exportedElements = new Set<Element>();
+    element.forEachExport(SerializerUtil.flattenElements(exportedElements));
+    return exportedElements.toList();
+  }
+
   void serialize(LibraryElement element,
                  ObjectEncoder encoder,
                  SerializedElementKind kind) {
     encoder.setUri(
         Key.CANONICAL_URI, element.canonicalUri, element.canonicalUri);
     encoder.setString(Key.LIBRARY_NAME, element.libraryName);
-    SerializerUtil.serializeMembers(element, encoder);
+    SerializerUtil.serializeMembers(getMembers(element), encoder);
     encoder.setElement(Key.COMPILATION_UNIT, element.entryCompilationUnit);
-    encoder.setElements(
-        Key.COMPILATION_UNITS, element.compilationUnits.toList());
-    encoder.setElements(Key.IMPORTS, element.imports);
+    encoder.setElements(Key.COMPILATION_UNITS, getCompilationUnits(element));
+    encoder.setElements(Key.IMPORTS, getImports(element));
     encoder.setElements(Key.EXPORTS, element.exports);
 
-    List<Element> importedElements = <Element>[];
-    element.forEachImport(SerializerUtil.flattenElements(importedElements));
-    encoder.setElements(Key.IMPORT_SCOPE, importedElements);
+    encoder.setElements(Key.IMPORT_SCOPE, getImportedElements(element));
 
-    List<Element> exportedElements = <Element>[];
-    element.forEachExport(SerializerUtil.flattenElements(exportedElements));
-    encoder.setElements(Key.EXPORT_SCOPE, exportedElements);
+    encoder.setElements(Key.EXPORT_SCOPE, getExportedElements(element));
 
   }
 }
@@ -190,7 +235,11 @@
     encoder.setUri(
         Key.URI, element.library.canonicalUri, element.script.resourceUri);
     List<Element> elements = <Element>[];
-    element.forEachLocalMember((e) => elements.add(e));
+    element.forEachLocalMember((e) {
+      if (!element.isPatch) {
+        elements.add(e);
+      }
+    });
     encoder.setElements(Key.ELEMENTS, elements);
   }
 }
@@ -200,11 +249,28 @@
 
   SerializedElementKind getSerializedKind(Element element) {
     if (element.isClass) {
+      ClassElement cls = element;
+      if (cls.isEnumClass) {
+        return SerializedElementKind.ENUM;
+      }
       return SerializedElementKind.CLASS;
     }
     return null;
   }
 
+  static List<Element> getMembers(ClassElement element) {
+    List<Element> members = <Element>[];
+    element.forEachLocalMember(members.add);
+    if (element.isPatched) {
+      element.implementation.forEachLocalMember((Element member) {
+        if (!member.isPatch) {
+          members.add(member);
+        }
+      });
+    }
+    return members;
+  }
+
   void serialize(ClassElement element,
                  ObjectEncoder encoder,
                  SerializedElementKind kind) {
@@ -214,6 +280,9 @@
     SerializerUtil.serializePosition(element, encoder);
     encoder.setTypes(Key.TYPE_VARIABLES, element.typeVariables);
     encoder.setBool(Key.IS_ABSTRACT, element.isAbstract);
+    if (element.isUnnamedMixinApplication) {
+      encoder.setBool(Key.IS_UNNAMED_MIXIN_APPLICATION, true);
+    }
     if (element.supertype != null) {
       encoder.setType(Key.SUPERTYPE, element.supertype);
     }
@@ -225,7 +294,12 @@
         element.allSupertypesAndSelf.supertypes.toList());
     supertypes.setInts(Key.OFFSETS, element.allSupertypesAndSelf.levelOffsets);
     encoder.setTypes(Key.INTERFACES, element.interfaces.toList());
-    SerializerUtil.serializeMembers(element, encoder);
+    SerializerUtil.serializeMembers(getMembers(element), encoder);
+    encoder.setBool(Key.IS_PROXY, element.isProxy);
+    if (kind == SerializedElementKind.ENUM) {
+      EnumClassElement enumClass = element;
+      encoder.setElements(Key.FIELDS, enumClass.enumValues);
+    }
   }
 }
 
@@ -306,6 +380,9 @@
       if (element.isInstanceMember) {
         return SerializedElementKind.INSTANCE_FUNCTION;
       }
+      if (element.isLocal) {
+        return SerializedElementKind.LOCAL_FUNCTION;
+      }
     }
     if (element.isGetter) {
       if (element.isTopLevel) return SerializedElementKind.TOPLEVEL_GETTER;
@@ -340,6 +417,12 @@
       encoder.setElement(Key.LIBRARY, element.library);
       encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
     }
+    encoder.setBool(Key.IS_EXTERNAL, element.isExternal);
+    if (element.isLocal) {
+      LocalFunctionElement localFunction = element;
+      encoder.setElement(
+          Key.EXECUTABLE_CONTEXT, localFunction.executableContext);
+    }
   }
 }
 
@@ -508,6 +591,8 @@
         return new CompilationUnitElementZ(decoder);
       case SerializedElementKind.CLASS:
         return new ClassElementZ(decoder);
+      case SerializedElementKind.ENUM:
+        return new EnumClassElementZ(decoder);
       case SerializedElementKind.TOPLEVEL_FIELD:
         return new TopLevelFieldElementZ(decoder);
       case SerializedElementKind.STATIC_FIELD:
@@ -524,6 +609,8 @@
         return new StaticFunctionElementZ(decoder);
       case SerializedElementKind.INSTANCE_FUNCTION:
         return new InstanceFunctionElementZ(decoder);
+      case SerializedElementKind.LOCAL_FUNCTION:
+        return new LocalFunctionElementZ(decoder);
       case SerializedElementKind.TOPLEVEL_GETTER:
         return new TopLevelGetterElementZ(decoder);
       case SerializedElementKind.STATIC_GETTER:
diff --git a/pkg/compiler/lib/src/serialization/impact_serialization.dart b/pkg/compiler/lib/src/serialization/impact_serialization.dart
new file mode 100644
index 0000000..92e68c5
--- /dev/null
+++ b/pkg/compiler/lib/src/serialization/impact_serialization.dart
@@ -0,0 +1,104 @@
+// 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 dart2js.serialization.impact;
+
+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 'keys.dart';
+import 'serialization.dart';
+
+/// Visitor that serializes a [WorldImpact] object using an [ObjectEncoder].
+class ImpactSerializer implements WorldImpactVisitor {
+  final ListEncoder staticUses;
+  final ListEncoder dynamicUses;
+  final ListEncoder typeUses;
+
+  ImpactSerializer(ObjectEncoder objectEncoder)
+      : staticUses = objectEncoder.createList(Key.STATIC_USES),
+        dynamicUses = objectEncoder.createList(Key.DYNAMIC_USES),
+        typeUses = objectEncoder.createList(Key.TYPE_USES);
+
+  @override
+  void visitDynamicUse(DynamicUse dynamicUse) {
+    ObjectEncoder object = dynamicUses.createObject();
+    object.setEnum(Key.KIND, dynamicUse.selector.kind);
+
+    object.setInt(Key.ARGUMENTS,
+        dynamicUse.selector.callStructure.argumentCount);
+    object.setStrings(Key.NAMED_ARGUMENTS,
+        dynamicUse.selector.callStructure.namedArguments);
+
+    object.setString(Key.NAME,
+        dynamicUse.selector.memberName.text);
+    object.setBool(Key.IS_SETTER,
+        dynamicUse.selector.memberName.isSetter);
+    if (dynamicUse.selector.memberName.library != null) {
+      object.setElement(Key.LIBRARY,
+        dynamicUse.selector.memberName.library);
+    }
+  }
+
+  @override
+  void visitStaticUse(StaticUse staticUse) {
+    ObjectEncoder object = staticUses.createObject();
+    object.setEnum(Key.KIND, staticUse.kind);
+    object.setElement(Key.ELEMENT, staticUse.element);
+  }
+
+  @override
+  void visitTypeUse(TypeUse typeUse) {
+    ObjectEncoder object = typeUses.createObject();
+    object.setEnum(Key.KIND, typeUse.kind);
+    object.setType(Key.TYPE, typeUse.type);
+  }
+}
+
+/// A deserialized [WorldImpact] object.
+class DeserializedWorldImpact extends WorldImpact with WorldImpactBuilder {}
+
+class ImpactDeserializer {
+  /// Deserializes a [WorldImpact] from [objectDecoder].
+  static WorldImpact deserializeImpact(ObjectDecoder objectDecoder) {
+    DeserializedWorldImpact worldImpact = new DeserializedWorldImpact();
+    ListDecoder staticUses = objectDecoder.getList(Key.STATIC_USES);
+    for (int index = 0; index < staticUses.length; index++) {
+      ObjectDecoder object = staticUses.getObject(index);
+      StaticUseKind kind = object.getEnum(Key.KIND, StaticUseKind.values);
+      Element element = object.getElement(Key.ELEMENT);
+      worldImpact.registerStaticUse(new StaticUse.internal(element, kind));
+    }
+    ListDecoder dynamicUses = objectDecoder.getList(Key.DYNAMIC_USES);
+    for (int index = 0; index < dynamicUses.length; index++) {
+      ObjectDecoder object = dynamicUses.getObject(index);
+      SelectorKind kind = object.getEnum(Key.KIND, SelectorKind.values);
+      int argumentCount = object.getInt(Key.ARGUMENTS);
+      List<String> namedArguments =
+          object.getStrings(Key.NAMED_ARGUMENTS, isOptional: true);
+      String name = object.getString(Key.NAME);
+      bool isSetter = object.getBool(Key.IS_SETTER);
+      LibraryElement library = object.getElement(Key.LIBRARY, isOptional: true);
+      worldImpact.registerDynamicUse(
+          new DynamicUse(
+              new Selector(
+                  kind,
+                  new Name(name, library, isSetter: isSetter),
+                  new CallStructure(argumentCount, namedArguments)),
+              null));
+    }
+    ListDecoder typeUses = objectDecoder.getList(Key.TYPE_USES);
+    for (int index = 0; index < typeUses.length; index++) {
+      ObjectDecoder object = typeUses.getObject(index);
+      TypeUseKind kind = object.getEnum(Key.KIND, TypeUseKind.values);
+      DartType type = object.getType(Key.TYPE);
+      worldImpact.registerTypeUse(new TypeUse.internal(type, kind));
+    }
+    return worldImpact;
+  }
+}
diff --git a/pkg/compiler/lib/src/serialization/keys.dart b/pkg/compiler/lib/src/serialization/keys.dart
index de1af42..c3b0bf8 100644
--- a/pkg/compiler/lib/src/serialization/keys.dart
+++ b/pkg/compiler/lib/src/serialization/keys.dart
@@ -18,10 +18,13 @@
   static const Key CONSTANT = const Key('constant');
   static const Key CONSTANTS = const Key('constants');
   static const Key CONSTRUCTOR = const Key('constructor');
+  static const Key DATA = const Key('data');
   static const Key DEFAULT = const Key('default');
   static const Key DEFAULTS = const Key('defaults');
+  static const Key DYNAMIC_USES = const Key('dynamic-uses');
   static const Key ELEMENT = const Key('element');
   static const Key ELEMENTS = const Key('elements');
+  static const Key EXECUTABLE_CONTEXT = const Key('executable-context');
   static const Key EXPORTS = const Key('exports');
   static const Key EXPORT_SCOPE = const Key('export-scope');
   static const Key EXPRESSION = const Key('expression');
@@ -30,6 +33,7 @@
   static const Key FIELDS = const Key('fields');
   static const Key FUNCTION = const Key('function');
   static const Key ID = const Key('id');
+  static const Key IMPACTS = const Key('impacts');
   static const Key IMPORT = const Key('import');
   static const Key IMPORTS = const Key('imports');
   static const Key IMPORT_SCOPE = const Key('import-scope');
@@ -43,6 +47,10 @@
   static const Key IS_NAMED = const Key('isNamed');
   static const Key IS_OPERATOR = const Key('isOperator');
   static const Key IS_OPTIONAL = const Key('isOptional');
+  static const Key IS_PROXY = const Key('isProxy');
+  static const Key IS_SETTER = const Key('isSetter');
+  static const Key IS_UNNAMED_MIXIN_APPLICATION =
+      const Key('isUnnamedMixinApplication');
   static const Key KEYS = const Key('keys');
   static const Key KIND = const Key('kind');
   static const Key LEFT = const Key('left');
@@ -53,6 +61,7 @@
   static const Key MEMBERS = const Key('members');
   static const Key NAME = const Key('name');
   static const Key NAMES = const Key('names');
+  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 OFFSET = const Key('offset');
@@ -65,6 +74,7 @@
   static const Key PREFIX = const Key('prefix');
   static const Key RETURN_TYPE = const Key('return-type');
   static const Key RIGHT = const Key('right');
+  static const Key STATIC_USES = const Key('static-uses');
   static const Key SUPERTYPE = const Key('supertype');
   static const Key SUPERTYPES = const Key('supertypes');
   static const Key TAGS = const Key('tags');
@@ -73,6 +83,7 @@
   static const Key TYPES = const Key('types');
   static const Key TYPE_ARGUMENTS = const Key('type-arguments');
   static const Key TYPE_DECLARATION = const Key('type-declaration');
+  static const Key TYPE_USES = const Key('type-uses');
   static const Key TYPE_VARIABLES = const Key('type-variables');
   static const Key URI = const Key('uri');
   static const Key VALUE = const Key('value');
diff --git a/pkg/compiler/lib/src/serialization/modelz.dart b/pkg/compiler/lib/src/serialization/modelz.dart
index 23153bf..9b825ce 100644
--- a/pkg/compiler/lib/src/serialization/modelz.dart
+++ b/pkg/compiler/lib/src/serialization/modelz.dart
@@ -80,9 +80,6 @@
   }
 
   @override
-  ClassElement get contextClass => _unsupported('contextClass');
-
-  @override
   ClassElement get enclosingClass => null;
 
   @override
@@ -91,9 +88,6 @@
   }
 
   @override
-  String get fixedBackendName => _unsupported('fixedBackendName');
-
-  @override
   LibraryElement get implementationLibrary => library;
 
   @override
@@ -325,6 +319,8 @@
 
   AbstractFieldElementZ(this.name, this.getter, this.setter);
 
+  FunctionElement get _canonicalElement => getter != null ? getter : setter;
+
   @override
   ElementKind get kind => ElementKind.ABSTRACT_FIELD;
 
@@ -334,19 +330,16 @@
   }
 
   @override
-  LibraryElement get library {
-    return getter != null ? getter.library : setter.library;
-  }
+  LibraryElement get library => _canonicalElement.library;
 
   @override
-  Element get enclosingElement {
-    return getter != null ? getter.enclosingElement : setter.enclosingElement;
-  }
+  Element get enclosingElement => _canonicalElement.enclosingElement;
 
   @override
-  SourceSpan get sourcePosition {
-    return getter != null ? getter.sourcePosition : setter.sourcePosition;
-  }
+  SourceSpan get sourcePosition => _canonicalElement.sourcePosition;
+
+  @override
+  ClassElement get enclosingClass => _canonicalElement.enclosingClass;
 }
 
 class LibraryElementZ extends DeserializedElementZ
@@ -533,6 +526,9 @@
   CompilationUnitElement get compilationUnit => this;
 
   @override
+  Element get enclosingElement => library;
+
+  @override
   accept(ElementVisitor visitor, arg) {
     return visitor.visitCompilationUnitElement(this, arg);
   }
@@ -726,13 +722,16 @@
 abstract class FunctionTypedElementMixin
     implements FunctionElement, DeserializedElementZ {
   @override
-  AsyncMarker get asyncMarker => _unsupported('');
-
-  @override
-  bool get isExternal => _unsupported('');
+  AsyncMarker get asyncMarker => _unsupported('asyncMarker');
 
   @override
   FunctionElement asFunctionElement() => this;
+
+  @override
+  bool get isExternal {
+    return _decoder.getBool(
+        Key.IS_EXTERNAL, isOptional: true, defaultValue: false);
+  }
 }
 
 class ClassElementZ extends DeserializedElementZ
@@ -853,11 +852,12 @@
   bool get isEnumClass => false;
 
   @override
-  bool get isProxy => _unsupported('isProxy');
+  bool get isProxy => _decoder.getBool(Key.IS_PROXY);
 
   @override
   bool get isUnnamedMixinApplication {
-    return _unsupported('isUnnamedMixinApplication');
+    return _decoder.getBool(Key.IS_UNNAMED_MIXIN_APPLICATION,
+        isOptional: true, defaultValue: false);
   }
 
   @override
@@ -886,6 +886,25 @@
   }
 }
 
+
+class EnumClassElementZ extends ClassElementZ implements EnumClassElement {
+  List<FieldElement> _enumValues;
+
+  EnumClassElementZ(ObjectDecoder decoder)
+      : super(decoder);
+
+  @override
+  bool get isEnumClass => true;
+
+  @override
+  List<FieldElement> get enumValues {
+    if (_enumValues == null) {
+      _enumValues = _decoder.getElements(Key.FIELDS);
+    }
+    return _enumValues;
+  }
+}
+
 abstract class ConstructorElementZ extends DeserializedElementZ
     with AnalyzableElementMixin,
          AstElementMixin,
@@ -955,6 +974,11 @@
   }
 
   @override
+  bool get isEffectiveTargetMalformed {
+    return _unsupported('isEffectiveTargetMalformed');
+  }
+
+  @override
   bool get isRedirectingFactory => _unsupported('isRedirectingFactory');
 
   @override
@@ -975,6 +999,10 @@
 
   @override
   ElementKind get kind => ElementKind.GENERATIVE_CONSTRUCTOR;
+
+  @override
+  bool get isEffectiveTargetMalformed =>
+      _unsupported('isEffectiveTargetMalformed');
 }
 
 class FactoryConstructorElementZ extends ConstructorElementZ {
@@ -984,6 +1012,10 @@
 
   @override
   ElementKind get kind => ElementKind.FACTORY_CONSTRUCTOR;
+
+  @override
+  bool get isEffectiveTargetMalformed =>
+      _unsupported('isEffectiveTargetMalformed');
 }
 
 abstract class MemberElementMixin
@@ -1096,6 +1128,61 @@
       : super(decoder);
 }
 
+abstract class LocalExecutableMixin
+    implements DeserializedElementZ, ExecutableElement, LocalElement {
+  ExecutableElement _executableContext;
+
+  @override
+  Element get enclosingElement => executableContext;
+
+  @override
+  ExecutableElement get executableContext {
+    if (_executableContext == null) {
+      _executableContext = _decoder.getElement(Key.EXECUTABLE_CONTEXT);
+    }
+    return _executableContext;
+  }
+
+  @override
+  MemberElement get memberContext => executableContext.memberContext;
+
+  @override
+  bool get isLocal => true;
+
+  @override
+  LibraryElement get library => memberContext.library;
+
+  @override
+  CompilationUnitElement get compilationUnit {
+    return memberContext.compilationUnit;
+  }
+
+  @override
+  bool get hasTreeElements => memberContext.hasTreeElements;
+
+  @override
+  TreeElements get treeElements => memberContext.treeElements;
+}
+
+class LocalFunctionElementZ extends DeserializedElementZ
+    with LocalExecutableMixin,
+         AstElementMixin,
+         ParametersMixin,
+         FunctionTypedElementMixin,
+         TypedElementMixin
+    implements LocalFunctionElement {
+  LocalFunctionElementZ(ObjectDecoder decoder)
+      : super(decoder);
+
+  @override
+  accept(ElementVisitor visitor, arg) {
+    return visitor.visitFunctionElement(this, arg);
+  }
+
+  @override
+  ElementKind get kind => ElementKind.FUNCTION;
+}
+
 abstract class GetterElementZ extends DeserializedElementZ
     with AnalyzableElementMixin,
          AstElementMixin,
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index 5a818ce..0379b6a 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -4,15 +4,18 @@
 
 library dart2js.serialization;
 
+import '../common/backend_api.dart';
 import '../elements/elements.dart';
 import '../constants/expressions.dart';
 import '../dart_types.dart';
+import '../universe/world_impact.dart';
 
-import 'element_serialization.dart';
 import 'constant_serialization.dart';
-import 'type_serialization.dart';
-import 'keys.dart';
+import 'element_serialization.dart';
+import 'impact_serialization.dart';
 import 'json_serializer.dart';
+import 'keys.dart';
+import 'type_serialization.dart';
 import 'values.dart';
 
 /// An object that supports the encoding an [ObjectValue] for serialization.
@@ -608,6 +611,7 @@
 // between serialized subcomponent.
 class Serializer {
   final SerializationEncoder _encoder;
+  List<SerializerPlugin> plugins = <SerializerPlugin>[];
 
   Map<Element, DataObject> _elementMap = <Element, DataObject>{};
   Map<ConstantExpression, DataObject> _constantMap =
@@ -623,7 +627,6 @@
     // [DataObject] for [library]. If not already created, this will
     // put the serialization of [library] in the work queue.
     _getElementDataObject(library);
-    _emptyWorklist();
   }
 
   void _emptyWorklist() {
@@ -641,26 +644,40 @@
     if (element == null) {
       throw new ArgumentError('Serializer._getElementDataObject(null)');
     }
-    return _elementMap.putIfAbsent(element, () {
+    DataObject dataObject = _elementMap[element];
+    if (dataObject == null) {
       // Run through [ELEMENT_SERIALIZERS] sequentially to find the one that
       // deals with [element].
       for (ElementSerializer serializer in ELEMENT_SERIALIZERS) {
         SerializedElementKind kind = serializer.getSerializedKind(element);
         if (kind != null) {
-          DataObject dataObject = new DataObject(
+          dataObject = new DataObject(
               new IntValue(_elementMap.length), new EnumValue(kind));
+          _elementMap[element] = dataObject;
           // Delay the serialization of the element itself to avoid loops, and
           // to keep the call stack small.
           _pendingList.add(() {
-            serializer.serialize(
-                element, new ObjectEncoder(this, dataObject.map), kind);
+            ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map);
+            serializer.serialize(element, encoder, kind);
+
+            MapEncoder pluginData;
+            for (SerializerPlugin plugin in plugins) {
+              plugin.onElement(element, (String tag) {
+                if (pluginData == null) {
+                  pluginData = encoder.createMap(Key.DATA);
+                }
+                return pluginData.createObject(tag);
+              });
+            }
           });
-          return dataObject;
         }
       }
+    }
+    if (dataObject == null) {
       throw new UnsupportedError(
           'Unsupported element: $element (${element.kind})');
-    });
+    }
+    return dataObject;
   }
 
   /// Creates the [ElementValue] for [element].
@@ -731,6 +748,8 @@
   }
 
   ObjectValue get objectValue {
+    _emptyWorklist();
+
     Map<Key, Value> map = <Key, Value>{};
     map[Key.ELEMENTS] =
         new ListValue(_elementMap.values.map((l) => l.objectValue).toList());
@@ -755,11 +774,34 @@
   }
 }
 
+/// Plugin for serializing additional data for an [Element].
+class SerializerPlugin {
+  const SerializerPlugin();
+
+  /// Called upon the serialization of [element].
+  ///
+  /// Use [creatorEncoder] to create a data object with id [tag] for storing
+  /// additional data for [element].
+  void onElement(Element element, ObjectEncoder createEncoder(String tag)) {}
+}
+
+/// Plugin for deserializing additional data for an [Element].
+class DeserializerPlugin {
+  const DeserializerPlugin();
+
+  /// Called upon the deserialization of [element].
+  ///
+  /// 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)) {}
+}
+
 /// Deserializer for a closed collection of libraries.
 // TODO(johnniwinther): Support per-library deserialization and dependencies
 // between deserialized subcomponent.
 class Deserializer {
   final SerializationDecoder decoder;
+  List<DeserializerPlugin> plugins = <DeserializerPlugin>[];
   ObjectDecoder _headerObject;
   ListDecoder _elementList;
   ListDecoder _typeList;
@@ -818,9 +860,21 @@
   /// Returns the deserialized [Element] for [id].
   Element deserializeElement(int id) {
     if (id == null) throw new ArgumentError('Deserializer.getElement(null)');
-    return _elementMap.putIfAbsent(id, () {
-      return ElementDeserializer.deserialize(elements.getObject(id));
-    });
+    Element element = _elementMap[id];
+    if (element == null) {
+      ObjectDecoder decoder = elements.getObject(id);
+      element = ElementDeserializer.deserialize(decoder);
+      _elementMap[id] = element;
+
+      MapDecoder pluginData = decoder.getMap(Key.DATA, isOptional: true);
+      // Call plugins even when there is no data, so they can take action in
+      // this case.
+      for (DeserializerPlugin plugin in plugins) {
+        plugin.onElement(element,
+          (String tag) => pluginData?.getObject(tag, isOptional: true));
+      }
+    }
+    return element;
   }
 
   /// Returns the deserialized [DartType] for [id].
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index 551ba49..fc1dfae 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -26,6 +26,11 @@
 
   String get name => 'Serialization';
 
+  /// If `true`, data must be retained to support serialization.
+  // TODO(johnniwinther): Make this more precise in terms of what needs to be
+  // retained, for instance impacts, resolution data etc.
+  bool supportSerialization = false;
+
   /// Returns the [LibraryElement] for [resolvedUri] if available from
   /// serialization.
   LibraryElement readLibrary(Uri resolvedUri) {
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 8796e23..8c8f78c 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -1205,8 +1205,8 @@
   // implementation/declaration distinction.
   Element get sourceElement => sourceElementStack.last;
 
-  bool get _checkOrTrustTypes =>
-      compiler.enableTypeAssertions || compiler.trustTypeAnnotations;
+  bool get _checkOrTrustTypes => compiler.options.enableTypeAssertions ||
+      compiler.options.trustTypeAnnotations;
 
   /// Build the graph for [target].
   HGraph build() {
@@ -1225,7 +1225,7 @@
       result = buildMethod(target);
     } else if (target.isField) {
       if (target.isInstanceMember) {
-        assert(compiler.enableTypeAssertions);
+        assert(compiler.options.enableTypeAssertions);
         result = buildCheckedSetter(target);
       } else {
         result = buildLazyInitializer(target);
@@ -1426,7 +1426,7 @@
     if (cachedCanBeInlined == false) return false;
 
     bool meetsHardConstraints() {
-      if (compiler.disableInlining) return false;
+      if (compiler.options.disableInlining) return false;
 
       assert(invariant(
           currentNode != null ? currentNode : element,
@@ -1477,7 +1477,7 @@
     bool doesNotContainCode() {
       // A function with size 1 does not contain any code.
       return InlineWeeder.canBeInlined(function, 1, true,
-          enableUserAssertions: compiler.enableUserAssertions);
+          enableUserAssertions: compiler.options.enableUserAssertions);
     }
 
     bool reductiveHeuristic() {
@@ -1485,7 +1485,7 @@
       // does not make the program larger.
       if (isCalledOnce(element)) {
         return InlineWeeder.canBeInlined(function, -1, false,
-            enableUserAssertions: compiler.enableUserAssertions);
+            enableUserAssertions: compiler.options.enableUserAssertions);
       }
       // TODO(sra): Measure if inlining would 'reduce' the size.  One desirable
       // case we miss by doing nothing is inlining very simple constructors
@@ -1524,7 +1524,7 @@
         // if we can inline this method regardless of size.
         assert(InlineWeeder.canBeInlined(function, -1, false,
                 allowLoops: true,
-                enableUserAssertions: compiler.enableUserAssertions));
+                enableUserAssertions: compiler.options.enableUserAssertions));
         return true;
       }
 
@@ -1548,7 +1548,7 @@
       bool canInline;
       canInline = InlineWeeder.canBeInlined(
           function, maxInliningNodes, useMaxInliningNodes,
-          enableUserAssertions: compiler.enableUserAssertions);
+          enableUserAssertions: compiler.options.enableUserAssertions);
       if (canInline) {
         backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop);
       } else {
@@ -2642,7 +2642,7 @@
   }
 
   HInstruction _trustType(HInstruction original, DartType type) {
-    assert(compiler.trustTypeAnnotations);
+    assert(compiler.options.trustTypeAnnotations);
     assert(type != null);
     type = localsHandler.substInContext(type);
     type = type.unaliased;
@@ -2656,7 +2656,7 @@
   }
 
   HInstruction _checkType(HInstruction original, DartType type, int kind) {
-    assert(compiler.enableTypeAssertions);
+    assert(compiler.options.enableTypeAssertions);
     assert(type != null);
     type = localsHandler.substInContext(type);
     HInstruction other = buildTypeConversion(original, type, kind);
@@ -2668,9 +2668,9 @@
       { int kind: HTypeConversion.CHECKED_MODE_CHECK }) {
     if (type == null) return original;
     HInstruction checkedOrTrusted = original;
-    if (compiler.trustTypeAnnotations) {
+    if (compiler.options.trustTypeAnnotations) {
       checkedOrTrusted = _trustType(original, type);
-    } else if (compiler.enableTypeAssertions) {
+    } else if (compiler.options.enableTypeAssertions) {
       checkedOrTrusted = _checkType(original, type, kind);
     }
     if (checkedOrTrusted == original) return original;
@@ -2750,7 +2750,7 @@
   }
 
   visitAssert(ast.Assert node) {
-    if (!compiler.enableUserAssertions) return;
+    if (!compiler.options.enableUserAssertions) return;
 
     if (!node.hasMessage) {
       // Generate:
@@ -4320,7 +4320,7 @@
          value = backend.mustRetainMetadata;
          break;
        case 'USE_CONTENT_SECURITY_POLICY':
-         value = compiler.useContentSecurityPolicy;
+         value = compiler.options.useContentSecurityPolicy;
          break;
        default:
          reporter.reportErrorMessage(
@@ -5353,7 +5353,7 @@
   /// In checked mode checks the [type] of [node] to be well-bounded. The method
   /// returns [:true:] if an error can be statically determined.
   bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) {
-    if (!compiler.enableTypeAssertions) return false;
+    if (!compiler.options.enableTypeAssertions) return false;
 
     Map<DartType, Set<DartType>> seenChecksMap =
         new Map<DartType, Set<DartType>>();
@@ -5993,7 +5993,7 @@
 
       var nativeBehavior = new native.NativeBehavior()
         ..codeTemplate = codeTemplate;
-      if (compiler.trustJSInteropTypeAnnotations) {
+      if (compiler.options.trustJSInteropTypeAnnotations) {
         nativeBehavior.typesReturned.add(constructor.enclosingClass.thisType);
       }
       return new HForeignCode(
@@ -6004,7 +6004,7 @@
     }
     var target = new HForeignCode(js.js.parseForeignJS(
             "${backend.namer.fixedBackendPath(element)}."
-            "${backend.getFixedBackendName(element)}"),
+            "${backend.nativeData.getFixedBackendName(element)}"),
         backend.dynamicType,
         <HInstruction>[]);
     add(target);
@@ -6024,7 +6024,8 @@
     // The return type is dynamic if we don't trust js-interop type
     // declarations.
     nativeBehavior.typesReturned.add(
-        compiler.trustJSInteropTypeAnnotations ? type : const DynamicType());
+        compiler.options.trustJSInteropTypeAnnotations
+            ? type : const DynamicType());
 
     // The allocation effects include the declared type if it is native (which
     // includes js interop types).
@@ -6034,7 +6035,7 @@
 
     // It also includes any other JS interop type if we don't trust the
     // annotation or if is declared too broad.
-    if (!compiler.trustJSInteropTypeAnnotations || type.isObject ||
+    if (!compiler.options.trustJSInteropTypeAnnotations || type.isObject ||
         type.isDynamic) {
       nativeBehavior.typesInstantiated.add(
           backend.helpers.jsJavaScriptObjectClass.thisType);
@@ -7333,7 +7334,7 @@
       visit(node.expression);
       value = pop();
       if (isBuildingAsyncFunction) {
-        if (compiler.enableTypeAssertions &&
+        if (compiler.options.enableTypeAssertions &&
             !isValidAsyncReturnType(returnType)) {
           String message =
                 "Async function returned a Future, "
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 4032c0a..410532c 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -1598,7 +1598,7 @@
         // A direct (i.e. non-interceptor) native call is the result of
         // optimization.  The optimization ensures any type checks or
         // conversions have been satisified.
-        methodName = backend.getFixedBackendName(target);
+        methodName = backend.nativeData.getFixedBackendName(target);
       }
     }
 
@@ -1960,7 +1960,7 @@
 
   js.Expression newLiteralBool(bool value,
                                SourceInformation sourceInformation) {
-    if (compiler.enableMinification) {
+    if (compiler.options.enableMinification) {
       // Use !0 for true, !1 for false.
       return new js.Prefix("!", new js.LiteralNumber(value ? "0" : "1"))
           .withSourceInformation(sourceInformation);
@@ -2787,7 +2787,7 @@
       ClassWorld classWorld = compiler.world;
       // An int check if the input is not int or null, is not
       // sufficient for doing an argument or receiver check.
-      assert(compiler.trustTypeAnnotations ||
+      assert(compiler.options.trustTypeAnnotations ||
              !node.checkedType.containsOnlyInt(classWorld) ||
              node.checkedInput.isIntegerOrNull(compiler));
       js.Expression test = generateReceiverOrArgumentTypeTest(
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index a68f70b..beb4f42 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -291,7 +291,7 @@
   SsaTrustedCheckRemover(this.compiler);
 
   void visitGraph(HGraph graph) {
-    if (!compiler.trustPrimitives) return;
+    if (!compiler.options.trustPrimitives) return;
     visitDominatorTree(graph);
   }
 
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index c445190..3281111 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
@@ -324,7 +324,7 @@
     }
 
     // Try creating a one-shot interceptor or optimized is-check
-    if (compiler.hasIncrementalSupport) return false;
+    if (compiler.options.hasIncrementalSupport) return false;
     if (node.usedBy.length != 1) return false;
     HInstruction user = node.usedBy.single;
 
diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
index 8852d1f..9e03bb9 100644
--- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
+++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
@@ -98,7 +98,7 @@
                                    Compiler compiler) {
     if (instruction.inputs[1].isMutableIndexable(compiler)) {
       if (!instruction.inputs[2].isInteger(compiler)
-          && compiler.enableTypeAssertions) {
+          && compiler.options.enableTypeAssertions) {
         // We want the right checked mode error.
         return null;
       }
@@ -118,7 +118,7 @@
                                    Compiler compiler) {
     if (!instruction.inputs[1].isIndexablePrimitive(compiler)) return null;
     if (!instruction.inputs[2].isInteger(compiler)
-        && compiler.enableTypeAssertions) {
+        && compiler.options.enableTypeAssertions) {
       // We want the right checked mode error.
       return null;
     }
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 484a784..78d5391 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -61,7 +61,7 @@
 
     ConstantSystem constantSystem = compiler.backend.constantSystem;
     JavaScriptItemCompilationContext context = work.compilationContext;
-    bool trustPrimitives = compiler.trustPrimitives;
+    bool trustPrimitives = compiler.options.trustPrimitives;
     measure(() {
       List<OptimizationPhase> phases = <OptimizationPhase>[
           // Run trivial instruction simplification first to optimize
@@ -393,7 +393,7 @@
         } else if (applies(helpers.jsArrayAdd)) {
           // The codegen special cases array calls, but does not
           // inline argument type checks.
-          if (!compiler.enableTypeAssertions) {
+          if (!compiler.options.enableTypeAssertions) {
             target = helpers.jsArrayAdd;
           }
         }
@@ -513,7 +513,7 @@
         if (type is FunctionType) {
           canInline = false;
         }
-        if (compiler.enableTypeAssertions) {
+        if (compiler.options.enableTypeAssertions) {
           // TODO(sra): Check if [input] is guaranteed to pass the parameter
           // type check.  Consider using a strengthened type check to avoid
           // passing `null` to primitive types since the native methods usually
@@ -918,7 +918,7 @@
     // interceptor calling convention, but is not a call on an
     // interceptor.
     HInstruction value = node.inputs.last;
-    if (compiler.enableTypeAssertions) {
+    if (compiler.options.enableTypeAssertions) {
       DartType type = field.type;
       if (!type.treatAsRaw || type.isTypeVariable) {
         // We cannot generate the correct type representation here, so don't
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index 4758afd..0b35432 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -160,29 +160,29 @@
     return "Boolify: ${temporaryId(node.inputs[0])}";
   }
 
-  String handleInvokeBinary(HInvokeBinary node, String op) {
+  String handleInvokeBinary(HInvokeBinary node, String opcode) {
     String left = temporaryId(node.left);
     String right= temporaryId(node.right);
-    return '$left $op $right';
+    return '$opcode: $left $right';
   }
 
-  String visitAdd(HAdd node) => handleInvokeBinary(node, '+');
+  String visitAdd(HAdd node) => handleInvokeBinary(node, 'Add');
 
-  String visitBitAnd(HBitAnd node) => handleInvokeBinary(node, '&');
+  String visitBitAnd(HBitAnd node) => handleInvokeBinary(node, 'BitAnd');
 
   String visitBitNot(HBitNot node) {
     String operand = temporaryId(node.operand);
-    return "~$operand";
+    return "BitNot: $operand";
   }
 
-  String visitBitOr(HBitOr node) => handleInvokeBinary(node, '|');
+  String visitBitOr(HBitOr node) => handleInvokeBinary(node, 'BitOr');
 
-  String visitBitXor(HBitXor node) => handleInvokeBinary(node, '^');
+  String visitBitXor(HBitXor node) => handleInvokeBinary(node, 'BitXor');
 
   String visitBoundsCheck(HBoundsCheck node) {
     String lengthId = temporaryId(node.length);
     String indexId = temporaryId(node.index);
-    return "Bounds check: length = $lengthId, index = $indexId";
+    return "BoundsCheck: length = $lengthId, index = $indexId";
   }
 
   String visitBreak(HBreak node) {
@@ -193,7 +193,7 @@
     return "Break: (B${target.id})";
   }
 
-  String visitConstant(HConstant constant) => "Constant ${constant.constant}";
+  String visitConstant(HConstant constant) => "Constant: ${constant.constant}";
 
   String visitContinue(HContinue node) {
     HBasicBlock target = currentBlock.successors[0];
@@ -203,22 +203,22 @@
     return "Continue: (B${target.id})";
   }
 
-  String visitDivide(HDivide node) => handleInvokeBinary(node, '/');
+  String visitDivide(HDivide node) => handleInvokeBinary(node, 'Divide');
 
-  String visitExit(HExit node) => "exit";
+  String visitExit(HExit node) => "Exit";
 
   String visitFieldGet(HFieldGet node) {
     if (node.isNullCheck) {
-      return 'null check on ${temporaryId(node.receiver)}';
+      return 'FieldGet: NullCheck ${temporaryId(node.receiver)}';
     }
     String fieldName = node.element.name;
-    return 'field get ${temporaryId(node.receiver)}.$fieldName';
+    return 'FieldGet: ${temporaryId(node.receiver)}.$fieldName';
   }
 
   String visitFieldSet(HFieldSet node) {
     String valueId = temporaryId(node.value);
     String fieldName = node.element.name;
-    return 'field set ${temporaryId(node.receiver)}.$fieldName to $valueId';
+    return 'FieldSet: ${temporaryId(node.receiver)}.$fieldName to $valueId';
   }
 
   String visitReadModifyWrite(HReadModifyWrite node) {
@@ -227,23 +227,23 @@
     String op = node.jsOp;
     if (node.isAssignOp) {
       String valueId = temporaryId(node.value);
-      return 'field-update $receiverId.$fieldName $op= $valueId';
+      return 'ReadModifyWrite: $receiverId.$fieldName $op= $valueId';
     } else if (node.isPreOp) {
-      return 'field-update $op$receiverId.$fieldName';
+      return 'ReadModifyWrite: $op$receiverId.$fieldName';
     } else {
-      return 'field-update $receiverId.$fieldName$op';
+      return 'ReadModifyWrite: $receiverId.$fieldName$op';
     }
   }
 
   String visitLocalGet(HLocalGet node) {
     String localName = node.variable.name;
-    return 'local get ${temporaryId(node.local)}.$localName';
+    return 'LocalGet: ${temporaryId(node.local)}.$localName';
   }
 
   String visitLocalSet(HLocalSet node) {
     String valueId = temporaryId(node.value);
     String localName = node.variable.name;
-    return 'local set ${temporaryId(node.local)}.$localName to $valueId';
+    return 'LocalSet: ${temporaryId(node.local)}.$localName to $valueId';
   }
 
   String visitGoto(HGoto node) {
@@ -251,11 +251,11 @@
     return "Goto: (B${target.id})";
   }
 
-  String visitGreater(HGreater node) => handleInvokeBinary(node, '>');
+  String visitGreater(HGreater node) => handleInvokeBinary(node, 'Greater');
   String visitGreaterEqual(HGreaterEqual node) {
-    return handleInvokeBinary(node, '>=');
+    return handleInvokeBinary(node, 'GreaterEqual');
   }
-  String visitIdentity(HIdentity node) => handleInvokeBinary(node, '===');
+  String visitIdentity(HIdentity node) => handleInvokeBinary(node, 'Identity');
 
   String visitIf(HIf node) {
     HBasicBlock thenBlock = currentBlock.successors[0];
@@ -264,8 +264,8 @@
     return "If ($conditionId): (B${thenBlock.id}) else (B${elseBlock.id})";
   }
 
-  String visitGenericInvoke(String invokeType, String functionName,
-                            List<HInstruction> arguments) {
+  String handleGenericInvoke(String invokeType, String functionName,
+                             List<HInstruction> arguments) {
     StringBuffer argumentsString = new StringBuffer();
     for (int i = 0; i < arguments.length; i++) {
       if (i != 0) argumentsString.write(", ");
@@ -293,59 +293,60 @@
       JavaScriptBackend backend = compiler.backend;
       String cls =
           backend.namer.suffixForGetInterceptor(node.interceptedClasses);
-      return "Intercept ($cls): $value";
+      return "Interceptor ($cls): $value";
     }
-    return "Intercept: $value";
+    return "Interceptor: $value";
   }
 
   String visitInvokeClosure(HInvokeClosure node)
-      => visitInvokeDynamic(node, "closure");
+      => handleInvokeDynamic(node, "InvokeClosure");
 
-  String visitInvokeDynamic(HInvokeDynamic invoke, String kind) {
+  String handleInvokeDynamic(HInvokeDynamic invoke, String kind) {
     String receiver = temporaryId(invoke.receiver);
     String name = invoke.selector.name;
-    String target = "($kind) $receiver.$name";
+    String target = "$receiver.$name";
     int offset = HInvoke.ARGUMENTS_OFFSET;
     List arguments = invoke.inputs.sublist(offset);
-    return visitGenericInvoke("Invoke", target, arguments) +
+    return handleGenericInvoke(kind, target, arguments) +
         "(${invoke.mask})";
   }
 
   String visitInvokeDynamicMethod(HInvokeDynamicMethod node)
-      => visitInvokeDynamic(node, "method");
+      => handleInvokeDynamic(node, "InvokeDynamicMethod");
   String visitInvokeDynamicGetter(HInvokeDynamicGetter node)
-      => visitInvokeDynamic(node, "get");
+      => handleInvokeDynamic(node, "InvokeDynamicGetter");
   String visitInvokeDynamicSetter(HInvokeDynamicSetter node)
-      => visitInvokeDynamic(node, "set");
+      => handleInvokeDynamic(node, "InvokeDynamicSetter");
 
   String visitInvokeStatic(HInvokeStatic invoke) {
     String target = invoke.element.name;
-    return visitGenericInvoke("Invoke", target, invoke.inputs);
+    return handleGenericInvoke("InvokeStatic", target, invoke.inputs);
   }
 
   String visitInvokeSuper(HInvokeSuper invoke) {
     String target = invoke.element.name;
-    return visitGenericInvoke("Invoke super", target, invoke.inputs);
+    return handleGenericInvoke("InvokeSuper", target, invoke.inputs);
   }
 
   String visitInvokeConstructorBody(HInvokeConstructorBody invoke) {
     String target = invoke.element.name;
-    return visitGenericInvoke("Invoke constructor body", target, invoke.inputs);
+    return handleGenericInvoke("InvokeConstructorBody", target, invoke.inputs);
   }
 
   String visitForeignCode(HForeignCode foreign) {
-    return visitGenericInvoke("Foreign", "${foreign.codeTemplate.ast}",
+    return handleGenericInvoke("ForeignCode", "${foreign.codeTemplate.ast}",
                               foreign.inputs);
   }
 
   String visitForeignNew(HForeignNew node) {
-    return visitGenericInvoke("New",
+    return handleGenericInvoke("ForeignNew",
                               "${node.element.name}",
                               node.inputs);
   }
 
-  String visitLess(HLess node) => handleInvokeBinary(node, '<');
-  String visitLessEqual(HLessEqual node) => handleInvokeBinary(node, '<=');
+  String visitLess(HLess node) => handleInvokeBinary(node, 'Less');
+  String visitLessEqual(HLessEqual node) =>
+      handleInvokeBinary(node, 'LessEqual');
 
   String visitLiteralList(HLiteralList node) {
     StringBuffer elementsString = new StringBuffer();
@@ -353,65 +354,67 @@
       if (i != 0) elementsString.write(", ");
       elementsString.write(temporaryId(node.inputs[i]));
     }
-    return "Literal list: [$elementsString]";
+    return "LiteralList: [$elementsString]";
   }
 
   String visitLoopBranch(HLoopBranch branch) {
     HBasicBlock bodyBlock = currentBlock.successors[0];
     HBasicBlock exitBlock = currentBlock.successors[1];
     String conditionId = temporaryId(branch.inputs[0]);
-    return "While ($conditionId): (B${bodyBlock.id}) then (B${exitBlock.id})";
+    return
+      "LoopBranch ($conditionId): (B${bodyBlock.id}) then (B${exitBlock.id})";
   }
 
-  String visitMultiply(HMultiply node) => handleInvokeBinary(node, '*');
+  String visitMultiply(HMultiply node) => handleInvokeBinary(node, 'Multiply');
 
   String visitNegate(HNegate node) {
     String operand = temporaryId(node.operand);
-    return "-$operand";
+    return "Negate: $operand";
   }
 
   String visitNot(HNot node) => "Not: ${temporaryId(node.inputs[0])}";
 
   String visitParameterValue(HParameterValue node) {
-    return "p${node.sourceElement.name}";
+    return "ParameterValue: ${node.sourceElement.name}";
   }
 
   String visitLocalValue(HLocalValue node) {
-    return "l${node.sourceElement.name}";
+    return "LocalValue: ${node.sourceElement.name}";
   }
 
   String visitPhi(HPhi phi) {
     StringBuffer buffer = new StringBuffer();
-    buffer.write("Phi(");
+    buffer.write("Phi: ");
     for (int i = 0; i < phi.inputs.length; i++) {
       if (i > 0) buffer.write(", ");
       buffer.write(temporaryId(phi.inputs[i]));
     }
-    buffer.write(")");
     return buffer.toString();
   }
 
   String visitRef(HRef node) {
-    return 'Ref ${temporaryId(node.value)}';
+    return 'Ref: ${temporaryId(node.value)}';
   }
 
-  String visitReturn(HReturn node) => "Return ${temporaryId(node.inputs[0])}";
+  String visitReturn(HReturn node) => "Return: ${temporaryId(node.inputs[0])}";
 
-  String visitShiftLeft(HShiftLeft node) => handleInvokeBinary(node, '<<');
-  String visitShiftRight(HShiftRight node) => handleInvokeBinary(node, '>>');
+  String visitShiftLeft(HShiftLeft node) =>
+      handleInvokeBinary(node, 'ShiftLeft');
+  String visitShiftRight(HShiftRight node) =>
+      handleInvokeBinary(node, 'ShiftRight');
 
   String visitStatic(HStatic node)
-      => "Static ${node.element.name}";
+      => "Static: ${node.element.name}";
 
   String visitLazyStatic(HLazyStatic node)
-      => "LazyStatic ${node.element.name}";
+      => "LazyStatic: ${node.element.name}";
 
   String visitOneShotInterceptor(HOneShotInterceptor node)
-      => visitInvokeDynamic(node, "one shot interceptor");
+      => handleInvokeDynamic(node, "OneShotInterceptor");
 
   String visitStaticStore(HStaticStore node) {
     String lhs = node.element.name;
-    return "Static $lhs = ${temporaryId(node.inputs[0])}";
+    return "StaticStore: $lhs = ${temporaryId(node.inputs[0])}";
   }
 
   String visitStringConcat(HStringConcat node) {
@@ -421,10 +424,10 @@
   }
 
   String visitStringify(HStringify node) {
-    return "Stringify ${temporaryId(node.inputs[0])}";
+    return "Stringify: ${temporaryId(node.inputs[0])}";
   }
 
-  String visitSubtract(HSubtract node) => handleInvokeBinary(node, '-');
+  String visitSubtract(HSubtract node) => handleInvokeBinary(node, 'Subtract');
 
   String visitSwitch(HSwitch node) {
     StringBuffer buf = new StringBuffer();
@@ -442,20 +445,20 @@
     return buf.toString();
   }
 
-  String visitThis(HThis node) => "this";
+  String visitThis(HThis node) => "This";
 
-  String visitThrow(HThrow node) => "Throw ${temporaryId(node.inputs[0])}";
+  String visitThrow(HThrow node) => "Throw: ${temporaryId(node.inputs[0])}";
 
   String visitThrowExpression(HThrowExpression node) {
-    return "ThrowExpression ${temporaryId(node.inputs[0])}";
+    return "ThrowExpression: ${temporaryId(node.inputs[0])}";
   }
 
   String visitTruncatingDivide(HTruncatingDivide node) {
-    return handleInvokeBinary(node, '~/');
+    return handleInvokeBinary(node, 'TruncatingDivide');
   }
 
   String visitExitTry(HExitTry node) {
-    return "Exit try";
+    return "ExitTry";
   }
 
   String visitTry(HTry node) {
@@ -477,12 +480,12 @@
 
   String visitIs(HIs node) {
     String type = node.typeExpression.toString();
-    return "TypeTest: ${temporaryId(node.expression)} is $type";
+    return "Is: ${temporaryId(node.expression)} is $type";
   }
 
   String visitIsViaInterceptor(HIsViaInterceptor node) {
     String type = node.typeExpression.toString();
-    return "TypeTest: ${temporaryId(node.inputs[0])} is $type";
+    return "IsViaInterceptor: ${temporaryId(node.inputs[0])} is $type";
   }
 
   String visitTypeConversion(HTypeConversion node) {
@@ -529,10 +532,10 @@
   }
 
   String visitAwait(HAwait node) {
-    return "await ${temporaryId(node.inputs[0])}";
+    return "Await: ${temporaryId(node.inputs[0])}";
   }
 
   String visitYield(HYield node) {
-    return "yield${node.hasStar ? "*" : ""} ${temporaryId(node.inputs[0])}";
+    return "Yield${node.hasStar ? "*" : ""}: ${temporaryId(node.inputs[0])}";
   }
 }
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index 6355c6a..49373dc 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -292,7 +292,7 @@
   // Return true if the argument type check was added.
   bool checkArgument(HInvokeDynamic instruction) {
     // We want the right error in checked mode.
-    if (compiler.enableTypeAssertions) return false;
+    if (compiler.options.enableTypeAssertions) return false;
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
 
diff --git a/pkg/compiler/lib/src/tokens/token.dart b/pkg/compiler/lib/src/tokens/token.dart
index 1b05a5f..d390eb7 100644
--- a/pkg/compiler/lib/src/tokens/token.dart
+++ b/pkg/compiler/lib/src/tokens/token.dart
@@ -416,28 +416,28 @@
       isUnaryOperator(value);
 }
 
-bool isUnaryOperator(String value) => identical(value, '~');
+bool isUnaryOperator(String value) => value == '~';
 
 bool isBinaryOperator(String value) {
   return
-      (identical(value, '==')) ||
-      (identical(value, '[]')) ||
-      (identical(value, '*')) ||
-      (identical(value, '/')) ||
-      (identical(value, '%')) ||
-      (identical(value, '~/')) ||
-      (identical(value, '+')) ||
-      (identical(value, '<<')) ||
-      (identical(value, '>>')) ||
-      (identical(value, '>=')) ||
-      (identical(value, '>')) ||
-      (identical(value, '<=')) ||
-      (identical(value, '<')) ||
-      (identical(value, '&')) ||
-      (identical(value, '^')) ||
-      (identical(value, '|'));
+      value == '==' ||
+      value == '[]' ||
+      value == '*' ||
+      value == '/' ||
+      value == '%' ||
+      value == '~/' ||
+      value == '+' ||
+      value == '<<' ||
+      value == '>>' ||
+      value == '>=' ||
+      value == '>' ||
+      value == '<=' ||
+      value == '<' ||
+      value == '&' ||
+      value == '^' ||
+      value == '|';
 }
 
-bool isTernaryOperator(String value) => identical(value, '[]=');
+bool isTernaryOperator(String value) => value == '[]=';
 
-bool isMinusOperator(String value) => identical(value, '-');
+bool isMinusOperator(String value) => value == '-';
diff --git a/pkg/compiler/lib/src/typechecker.dart b/pkg/compiler/lib/src/typechecker.dart
index 449618b..bd23056 100644
--- a/pkg/compiler/lib/src/typechecker.dart
+++ b/pkg/compiler/lib/src/typechecker.dart
@@ -558,7 +558,7 @@
   bool checkAssignable(Spannable spannable, DartType from, DartType to,
                        {bool isConst: false}) {
     if (!types.isAssignable(from, to)) {
-      if (compiler.enableTypeAssertions && isConst) {
+      if (compiler.options.enableTypeAssertions && isConst) {
         reporter.reportErrorMessage(
             spannable,
             MessageKind.NOT_ASSIGNABLE,
diff --git a/pkg/compiler/lib/src/universe/selector.dart b/pkg/compiler/lib/src/universe/selector.dart
index f8a44e6..014ceef 100644
--- a/pkg/compiler/lib/src/universe/selector.dart
+++ b/pkg/compiler/lib/src/universe/selector.dart
@@ -34,7 +34,12 @@
   static const SelectorKind OPERATOR = const SelectorKind('operator', 3);
   static const SelectorKind INDEX = const SelectorKind('index', 4);
 
+  int get index => hashCode;
+
   String toString() => name;
+
+  static List<SelectorKind> values =
+      const <SelectorKind>[GETTER, SETTER, CALL, OPERATOR, INDEX];
 }
 
 class Selector {
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index 77c1084..73fb979 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -84,7 +84,7 @@
   final StaticUseKind kind;
   final int hashCode;
 
-  StaticUse._(Element element, StaticUseKind kind)
+  StaticUse.internal(Element element, StaticUseKind kind)
       : this.element = element,
         this.kind = kind,
         this.hashCode = Hashing.objectHash(element, Hashing.objectHash(kind)) {
@@ -101,7 +101,7 @@
     assert(invariant(element, element.isStatic || element.isTopLevel,
         message: "Static invoke element $element must be a top-level "
                  "or static method."));
-    return new StaticUse._(element, StaticUseKind.GENERAL);
+    return new StaticUse.internal(element, StaticUseKind.GENERAL);
   }
 
   /// Closurization of a static or top-level function [element].
@@ -109,7 +109,7 @@
     assert(invariant(element, element.isStatic || element.isTopLevel,
         message: "Static tear-off element $element must be a top-level "
                  "or static method."));
-    return new StaticUse._(element, StaticUseKind.STATIC_TEAR_OFF);
+    return new StaticUse.internal(element, StaticUseKind.STATIC_TEAR_OFF);
   }
 
   /// Read access of a static or top-level field or getter [element].
@@ -119,7 +119,7 @@
                  "or static method."));
     assert(invariant(element, element.isField || element.isGetter,
         message: "Static get element $element must be a field or a getter."));
-    return new StaticUse._(element, StaticUseKind.GENERAL);
+    return new StaticUse.internal(element, StaticUseKind.GENERAL);
   }
 
   /// Write access of a static or top-level field or setter [element].
@@ -129,7 +129,7 @@
                  "or static method."));
     assert(invariant(element, element.isField || element.isSetter,
         message: "Static set element $element must be a field or a setter."));
-    return new StaticUse._(element, StaticUseKind.GENERAL);
+    return new StaticUse.internal(element, StaticUseKind.GENERAL);
   }
 
   /// Invocation of the lazy initializer for a static or top-level field
@@ -140,7 +140,7 @@
                  "or static method."));
     assert(invariant(element, element.isField,
         message: "Static init element $element must be a field."));
-    return new StaticUse._(element, StaticUseKind.GENERAL);
+    return new StaticUse.internal(element, StaticUseKind.GENERAL);
   }
 
   /// Invocation of a super method [element] with the given [callStructure].
@@ -149,7 +149,7 @@
     // TODO(johnniwinther): Use the [callStructure].
     assert(invariant(element, element.isInstanceMember,
         message: "Super invoke element $element must be an instance method."));
-    return new StaticUse._(element, StaticUseKind.GENERAL);
+    return new StaticUse.internal(element, StaticUseKind.GENERAL);
   }
 
   /// Read access of a super field or getter [element].
@@ -158,7 +158,7 @@
         message: "Super get element $element must be an instance method."));
     assert(invariant(element, element.isField || element.isGetter,
         message: "Super get element $element must be a field or a getter."));
-    return new StaticUse._(element, StaticUseKind.GENERAL);
+    return new StaticUse.internal(element, StaticUseKind.GENERAL);
   }
 
   /// Write access of a super field [element].
@@ -167,7 +167,7 @@
         message: "Super set element $element must be an instance method."));
     assert(invariant(element, element.isField,
         message: "Super set element $element must be a field."));
-    return new StaticUse._(element, StaticUseKind.SUPER_FIELD_SET);
+    return new StaticUse.internal(element, StaticUseKind.SUPER_FIELD_SET);
   }
 
   /// Write access of a super setter [element].
@@ -176,14 +176,14 @@
         message: "Super set element $element must be an instance method."));
     assert(invariant(element, element.isSetter,
         message: "Super set element $element must be a setter."));
-    return new StaticUse._(element, StaticUseKind.GENERAL);
+    return new StaticUse.internal(element, StaticUseKind.GENERAL);
   }
 
   /// Closurization of a super method [element].
   factory StaticUse.superTearOff(MethodElement element) {
     assert(invariant(element, element.isInstanceMember && element.isFunction,
         message: "Super invoke element $element must be an instance method."));
-    return new StaticUse._(element, StaticUseKind.SUPER_TEAR_OFF);
+    return new StaticUse.internal(element, StaticUseKind.SUPER_TEAR_OFF);
   }
 
   /// Invocation of a constructor [element] through a this or super
@@ -195,7 +195,7 @@
         element.isGenerativeConstructor,
         message: "Constructor invoke element $element must be a "
                  "generative constructor."));
-    return new StaticUse._(element, StaticUseKind.GENERAL);
+    return new StaticUse.internal(element, StaticUseKind.GENERAL);
   }
 
   /// Invocation of a constructor (body) [element] through a this or super
@@ -203,26 +203,26 @@
   factory StaticUse.constructorBodyInvoke(ConstructorBodyElement element,
                                           CallStructure callStructure) {
     // TODO(johnniwinther): Use the [callStructure].
-    return new StaticUse._(element, StaticUseKind.GENERAL);
+    return new StaticUse.internal(element, StaticUseKind.GENERAL);
   }
 
   /// Constructor invocation of [element] with the given [callStructure].
   factory StaticUse.constructorInvoke(ConstructorElement element,
                                       CallStructure callStructure) {
     // TODO(johnniwinther): Use the [callStructure].
-    return new StaticUse._(element, StaticUseKind.GENERAL);
+    return new StaticUse.internal(element, StaticUseKind.GENERAL);
   }
 
   /// Constructor redirection to [element].
   factory StaticUse.constructorRedirect(ConstructorElement element) {
-    return new StaticUse._(element, StaticUseKind.GENERAL);
+    return new StaticUse.internal(element, StaticUseKind.GENERAL);
   }
 
   /// Initialization of an instance field [element].
   factory StaticUse.fieldInit(FieldElement element) {
     assert(invariant(element, element.isInstanceMember,
         message: "Field init element $element must be an instance field."));
-    return new StaticUse._(element, StaticUseKind.GENERAL);
+    return new StaticUse.internal(element, StaticUseKind.GENERAL);
   }
 
   /// Read access of an instance field or boxed field [element].
@@ -231,7 +231,7 @@
         element.isInstanceMember || element is BoxFieldElement,
         message: "Field init element $element must be an instance "
                  "or boxed field."));
-    return new StaticUse._(element, StaticUseKind.FIELD_GET);
+    return new StaticUse.internal(element, StaticUseKind.FIELD_GET);
   }
 
   /// Write access of an instance field or boxed field [element].
@@ -240,18 +240,18 @@
         element.isInstanceMember || element is BoxFieldElement,
         message: "Field init element $element must be an instance "
                  "or boxed field."));
-    return new StaticUse._(element, StaticUseKind.FIELD_SET);
+    return new StaticUse.internal(element, StaticUseKind.FIELD_SET);
   }
 
   /// Read of a local function [element].
   factory StaticUse.closure(LocalFunctionElement element) {
-    return new StaticUse._(element, StaticUseKind.CLOSURE);
+    return new StaticUse.internal(element, StaticUseKind.CLOSURE);
   }
 
   /// Unknown use of [element].
   @deprecated
   factory StaticUse.foreignUse(Element element) {
-    return new StaticUse._(element, StaticUseKind.GENERAL);
+    return new StaticUse.internal(element, StaticUseKind.GENERAL);
   }
 
   bool operator ==(other) {
@@ -279,39 +279,39 @@
   final TypeUseKind kind;
   final int hashCode;
 
-  TypeUse._(DartType type, TypeUseKind kind)
+  TypeUse.internal(DartType type, TypeUseKind kind)
       : this.type = type,
         this.kind = kind,
         this.hashCode = Hashing.objectHash(type, Hashing.objectHash(kind));
 
   /// [type] used in an is check, like `e is T` or `e is! T`.
   factory TypeUse.isCheck(DartType type) {
-    return new TypeUse._(type, TypeUseKind.IS_CHECK);
+    return new TypeUse.internal(type, TypeUseKind.IS_CHECK);
   }
 
   /// [type] used in an as cast, like `e as T`.
   factory TypeUse.asCast(DartType type) {
-    return new TypeUse._(type, TypeUseKind.AS_CAST);
+    return new TypeUse.internal(type, TypeUseKind.AS_CAST);
   }
 
   /// [type] used as a type annotation, like `T foo;`.
   factory TypeUse.checkedModeCheck(DartType type) {
-    return new TypeUse._(type, TypeUseKind.CHECKED_MODE_CHECK);
+    return new TypeUse.internal(type, TypeUseKind.CHECKED_MODE_CHECK);
   }
 
   /// [type] used in a on type catch clause, like `try {} on T catch (e) {}`.
   factory TypeUse.catchType(DartType type) {
-    return new TypeUse._(type, TypeUseKind.CATCH_TYPE);
+    return new TypeUse.internal(type, TypeUseKind.CATCH_TYPE);
   }
 
   /// [type] used as a type literal, like `foo() => T;`.
   factory TypeUse.typeLiteral(DartType type) {
-    return new TypeUse._(type, TypeUseKind.TYPE_LITERAL);
+    return new TypeUse.internal(type, TypeUseKind.TYPE_LITERAL);
   }
 
   /// [type] used in an instantiation, like `new T();`.
   factory TypeUse.instantiation(InterfaceType type) {
-    return new TypeUse._(type, TypeUseKind.INSTANTIATION);
+    return new TypeUse.internal(type, TypeUseKind.INSTANTIATION);
   }
 
   bool operator ==(other) {
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index 3e382e1..a7dbad0 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -653,7 +653,8 @@
     /// properties of the [ClassHierarchyNode] for [cls].
 
     void addSubtypes(ClassElement cls) {
-      if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) {
+      if (compiler.options.hasIncrementalSupport &&
+          !alreadyPopulated.add(cls)) {
         return;
       }
       assert(cls.isDeclaration);
@@ -841,5 +842,5 @@
     return functionsThatMightBePassedToApply.contains(element);
   }
 
-  bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport;
+  bool get hasClosedWorldAssumption => !compiler.options.hasIncrementalSupport;
 }
diff --git a/pkg/dart2js_incremental/lib/caching_compiler.dart b/pkg/dart2js_incremental/lib/caching_compiler.dart
index 4185df1..f7f8f10 100644
--- a/pkg/dart2js_incremental/lib/caching_compiler.dart
+++ b/pkg/dart2js_incremental/lib/caching_compiler.dart
@@ -36,11 +36,11 @@
   CompilerImpl compiler = cachedCompiler;
   if (compiler == null ||
       compiler.libraryRoot != libraryRoot ||
-      !compiler.hasIncrementalSupport ||
+      !compiler.options.hasIncrementalSupport ||
       compiler.hasCrashed ||
       compiler.enqueuer.resolution.hasEnqueuedReflectiveElements ||
       compiler.deferredLoadTask.isProgramSplit) {
-    if (compiler != null && compiler.hasIncrementalSupport) {
+    if (compiler != null && compiler.options.hasIncrementalSupport) {
       print('***FLUSH***');
       if (compiler.hasCrashed) {
         print('Unable to reuse compiler due to crash.');
@@ -57,12 +57,11 @@
         inputProvider,
         outputProvider,
         diagnosticHandler,
-        libraryRoot,
-        packageRoot,
-        options,
-        environment,
-        null,
-        null);
+        new CompilerOptions.parse(
+            libraryRoot: libraryRoot,
+            packageRoot: packageRoot,
+            options: options,
+            environment: environment));
     JavaScriptBackend backend = compiler.backend;
 
     full.Emitter emitter = backend.emitter.emitter;
diff --git a/pkg/dart2js_incremental/lib/dart2js_incremental.dart b/pkg/dart2js_incremental/lib/dart2js_incremental.dart
index 1ce8039..ea42c5a 100644
--- a/pkg/dart2js_incremental/lib/dart2js_incremental.dart
+++ b/pkg/dart2js_incremental/lib/dart2js_incremental.dart
@@ -18,6 +18,7 @@
     CompilerDiagnostics,
     CompilerInput,
     CompilerOutput,
+    CompilerOptions,
     Diagnostic;
 
 import 'package:compiler/src/null_compiler_output.dart' show
diff --git a/pkg/dart2js_incremental/lib/library_updater.dart b/pkg/dart2js_incremental/lib/library_updater.dart
index eb4bbd1..b8a5c62 100644
--- a/pkg/dart2js_incremental/lib/library_updater.dart
+++ b/pkg/dart2js_incremental/lib/library_updater.dart
@@ -796,7 +796,7 @@
     compiler.phase = Compiler.PHASE_DONE_RESOLVING;
 
     // TODO(ahe): Clean this up. Don't call this method in analyze-only mode.
-    if (compiler.analyzeOnly) return "/* analyze only */";
+    if (compiler.options.analyzeOnly) return "/* analyze only */";
 
     Set<ClassElementX> changedClasses =
         new Set<ClassElementX>.from(_classesWithSchemaChanges);
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 5cfce7f..351addb 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -58,6 +58,7 @@
 analyzer/test/generated/constant_test: Pass, Slow # Issue 24914
 analyzer/test/generated/declaration_resolver_test: Pass, Slow # Issue 24914
 analyzer/test/generated/element_test: Pass, Slow # Issue 21628
+analyzer/test/generated/element_resolver_test: Pass, Slow # Issue 21628
 analyzer/test/generated/error_suppression_test: Pass, Slow # Issue 21628
 analyzer/test/generated/engine_test: SkipSlow
 analyzer/test/generated/hint_code_test: Pass, Slow # Issue 21628
diff --git a/pkg/typed_data/LICENSE b/pkg/typed_data/LICENSE
deleted file mode 100644
index ee99930..0000000
--- a/pkg/typed_data/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright 2013, 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/typed_data/README.md b/pkg/typed_data/README.md
deleted file mode 100644
index e1e7db5..0000000
--- a/pkg/typed_data/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-Helper libraries for working with typed data lists.
-
-The `typed_data` package contains utility functions and classes that makes working with typed data lists easier.
-
-## Using
-
-The `typed_data` package can be imported as
-
-    import 'package:typed_data/typed_data.dart';
-
-## Typed buffers: Growable typed data lists
-
-Typed buffers are contains growable lists backed by typed arrays.
-These are similar to the growable lists returned by `new List()`, 
-but stores typed data like a typed data list.
\ No newline at end of file
diff --git a/pkg/typed_data/lib/typed_buffers.dart b/pkg/typed_data/lib/typed_buffers.dart
deleted file mode 100644
index 50ed241..0000000
--- a/pkg/typed_data/lib/typed_buffers.dart
+++ /dev/null
@@ -1,235 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/**
- * Growable typed-data lists.
- *
- * These lists works just as a typed-data list, except that they are growable.
- * They use an underlying buffer, and when that buffer becomes too small, it
- * is replaced by a new buffer.
- *
- * That means that using the [TypedDataView.buffer] getter is not guaranteed
- * to return the same result each time it is used, and that the buffer may
- * be larger than what the list is using.
- */
-library dart.pkg.typed_data.typed_buffers;
-
-import "dart:collection" show ListBase;
-import "dart:typed_data";
-
-abstract class _TypedDataBuffer<E> extends ListBase<E> {
-  static const int INITIAL_LENGTH = 8;
-
-  /// This is a Uint8List for Uint8Buffer. It's both a List<E> and a TypedData,
-  /// which we don't have a type for here.
-  var _buffer;
-  /// The length of the list being built.
-  int _length;
-
-  _TypedDataBuffer(List<E> buffer)
-      : this._buffer = buffer, this._length = buffer.length;
-
-  int get length => _length;
-  E operator[](int index) {
-    if (index >= length) throw new RangeError.index(index, this);
-    return _buffer[index];
-  }
-
-  void operator[]=(int index, E value) {
-    if (index >= length) throw new RangeError.index(index, this);
-    _buffer[index] = value;
-  }
-
-  void set length(int newLength) {
-    if (newLength < _length) {
-      E defaultValue = _defaultValue;
-      for (int i = newLength; i < _length; i++) {
-        _buffer[i] = defaultValue;
-      }
-    } else if (newLength > _buffer.length) {
-      List<E> newBuffer;
-      if (_buffer.length == 0) {
-        newBuffer = _createBuffer(newLength);
-      } else {
-        newBuffer = _createBiggerBuffer(newLength);
-      }
-      newBuffer.setRange(0, _length, _buffer);
-      _buffer = newBuffer;
-    }
-    _length = newLength;
-  }
-
-  void _add(E value) {
-    if (_length == _buffer.length) _grow();
-    _buffer[_length++] = value;
-  }
-
-  // We override the default implementation of `add` and `addAll` because
-  // they grow by setting the length in increments of one. We want to grow
-  // by doubling capacity in most cases.
-  void add(E value) { _add(value); }
-
-  void addAll(Iterable<E> values) {
-    for (E value in values) _add(value);
-  }
-
-  void insert(int index, E element) {
-    if (index < 0 || index > _length) {
-      throw new RangeError.range(index, 0, _length);
-    }
-    if (_length < _buffer.length) {
-      _buffer.setRange(index + 1, _length + 1, _buffer, index);
-      _buffer[index] = element;
-      _length++;
-      return;
-    }
-    List<E> newBuffer = _createBiggerBuffer(null);
-    newBuffer.setRange(0, index, _buffer);
-    newBuffer.setRange(index + 1, _length + 1, _buffer, index);
-    newBuffer[index] = element;
-    _length++;
-    _buffer = newBuffer;
-  }
-
-  /**
-   * Create a bigger buffer.
-   *
-   * This method determines how much bigger a bigger buffer should
-   * be. If [requiredLength] is not null, it will be at least that
-   * size. It will always have at least have double the capacity of
-   * the current buffer.
-   */
-  List<E> _createBiggerBuffer(int requiredLength) {
-    int newLength = _buffer.length * 2;
-    if (requiredLength != null && newLength < requiredLength) {
-      newLength = requiredLength;
-    } else if (newLength < INITIAL_LENGTH) {
-      newLength = INITIAL_LENGTH;
-    }
-    return _createBuffer(newLength);
-  }
-
-  void _grow() {
-    _buffer = _createBiggerBuffer(null)..setRange(0, _length, _buffer);
-  }
-
-  void setRange(int start, int end, Iterable<E> source, [int skipCount = 0]) {
-    if (end > _length) throw new RangeError.range(end, 0, _length);
-    if (source is _TypedDataBuffer<E>) {
-      _buffer.setRange(start, end, source._buffer, skipCount);
-    } else {
-      _buffer.setRange(start, end, source, skipCount);
-    }
-  }
-
-  // TypedData.
-
-  int get elementSizeInBytes => _buffer.elementSizeInBytes;
-
-  int get lengthInBytes => _length * _buffer.elementSizeInBytes;
-
-  int get offsetInBytes => _buffer.offsetInBytes;
-
-  /**
-    * Returns the underlying [ByteBuffer].
-    *
-    * The returned buffer may be replaced by operations that change the [length]
-    * of this list.
-    *
-    * The buffer may be larger than [lengthInBytes] bytes, but never smaller.
-    */
-  ByteBuffer get buffer => _buffer.buffer;
-
-  // Specialization for the specific type.
-
-  // Return zero for integers, 0.0 for floats, etc.
-  // Used to fill buffer when changing length.
-  E get _defaultValue;
-
-  // Create a new typed list to use as buffer.
-  List<E> _createBuffer(int size);
-}
-
-abstract class _IntBuffer extends _TypedDataBuffer<int> {
-  _IntBuffer(buffer): super(buffer);
-  int get _defaultValue => 0;
-}
-
-abstract class _FloatBuffer extends _TypedDataBuffer<double> {
-  _FloatBuffer(buffer): super(buffer);
-  double get _defaultValue => 0.0;
-}
-
-class Uint8Buffer extends _IntBuffer {
-  Uint8Buffer([int initialLength = 0]) : super(new Uint8List(initialLength));
-  Uint8List _createBuffer(int size) => new Uint8List(size);
-}
-
-class Int8Buffer extends _IntBuffer {
-  Int8Buffer([int initialLength = 0]) : super(new Int8List(initialLength));
-  Int8List _createBuffer(int size) => new Int8List(size);
-}
-
-class Uint8ClampedBuffer extends _IntBuffer {
-  Uint8ClampedBuffer([int initialLength = 0])
-      : super(new Uint8ClampedList(initialLength));
-  Uint8ClampedList _createBuffer(int size) => new Uint8ClampedList(size);
-}
-
-class Uint16Buffer extends _IntBuffer {
-  Uint16Buffer([int initialLength = 0]) : super(new Uint16List(initialLength));
-  Uint16List _createBuffer(int size) => new Uint16List(size);
-}
-
-class Int16Buffer extends _IntBuffer {
-  Int16Buffer([int initialLength = 0]) : super(new Int16List(initialLength));
-  Int16List _createBuffer(int size) => new Int16List(size);
-}
-
-class Uint32Buffer extends _IntBuffer {
-  Uint32Buffer([int initialLength = 0]) : super(new Uint32List(initialLength));
-  Uint32List _createBuffer(int size) => new Uint32List(size);
-}
-
-class Int32Buffer extends _IntBuffer {
-  Int32Buffer([int initialLength = 0]) : super(new Int32List(initialLength));
-  Int32List _createBuffer(int size) => new Int32List(size);
-}
-
-class Uint64Buffer extends _IntBuffer {
-  Uint64Buffer([int initialLength = 0]) : super(new Uint64List(initialLength));
-  Uint64List _createBuffer(int size) => new Uint64List(size);
-}
-
-class Int64Buffer extends _IntBuffer {
-  Int64Buffer([int initialLength = 0]) : super(new Int64List(initialLength));
-  Int64List _createBuffer(int size) => new Int64List(size);
-}
-
-class Float32Buffer extends _FloatBuffer {
-  Float32Buffer([int initialLength = 0])
-      : super(new Float32List(initialLength));
-  Float32List _createBuffer(int size) => new Float32List(size);
-}
-
-class Float64Buffer extends _FloatBuffer {
-  Float64Buffer([int initialLength = 0])
-      : super(new Float64List(initialLength));
-  Float64List _createBuffer(int size) => new Float64List(size);
-}
-
-class Int32x4Buffer extends _TypedDataBuffer<Int32x4> {
-  static Int32x4 _zero = new Int32x4(0, 0, 0, 0);
-  Int32x4Buffer([int initialLength = 0])
-      : super(new Int32x4List(initialLength));
-  Int32x4 get _defaultValue => _zero;
-  Int32x4List _createBuffer(int size) => new Int32x4List(size);
-}
-
-class Float32x4Buffer extends _TypedDataBuffer<Float32x4> {
-  Float32x4Buffer([int initialLength = 0])
-      : super(new Float32x4List(initialLength));
-  Float32x4 get _defaultValue => new Float32x4.zero();
-  Float32x4List _createBuffer(int size) => new Float32x4List(size);
-}
diff --git a/pkg/typed_data/lib/typed_data.dart b/pkg/typed_data/lib/typed_data.dart
deleted file mode 100644
index b6619ab..0000000
--- a/pkg/typed_data/lib/typed_data.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/**
- * Utilities and functionality related to the "dart:typed_data" library.
- */
-library dart.pkg.typed_data;
-
-export "package:typed_data/typed_buffers.dart";
diff --git a/pkg/typed_data/pubspec.yaml b/pkg/typed_data/pubspec.yaml
deleted file mode 100644
index b4c3945..0000000
--- a/pkg/typed_data/pubspec.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-name: typed_data
-version: 1.0.1-dev
-author: Dart Team <misc@dartlang.org>
-description: Utility functions and classes related to the 'dart:typed_data' library.
-homepage: http://www.dartlang.org
-dev_dependencies:
-  unittest: ">=0.9.0 <0.10.0"
-environment:
-  sdk: ">=1.5.0 <2.0.0"
diff --git a/pkg/typed_data/test/typed_buffers_test.dart b/pkg/typed_data/test/typed_buffers_test.dart
deleted file mode 100644
index 1cb37b0..0000000
--- a/pkg/typed_data/test/typed_buffers_test.dart
+++ /dev/null
@@ -1,421 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Tests typed-data buffer classes.
-
-import "package:typed_data/typed_buffers.dart";
-import "package:unittest/unittest.dart";
-import "dart:typed_data";
-
-main() {
-  testUint(8, (l) => new Uint8Buffer(l));
-  testInt(8, (l) => new Int8Buffer(l));
-  test("Uint8ClampedBuffer", () {
-    testIntBuffer(8, 0, 255, (l) => new Uint8ClampedBuffer(l), clampUint8);
-  });
-  testUint(16, (l) => new Uint16Buffer(l));
-  testInt(16, (l) => new Int16Buffer(l));
-  testUint(32, (l) => new Uint32Buffer(l));  /// 01: ok
-  testInt(32, (l) => new Int32Buffer(l));
-  testUint(64, (l) => new Uint64Buffer(l));  /// 01: continued
-  testInt(64, (l) => new Int64Buffer(l));    /// 01: continued
-
-  testInt32x4Buffer(intSamples);
-
-  List roundedFloatSamples = floatSamples.map(roundToFloat).toList();
-  testFloatBuffer(32, roundedFloatSamples,
-                  () => new Float32Buffer(),
-                  roundToFloat);
-  testFloatBuffer(64, doubleSamples, () => new Float64Buffer(), (x) => x);
-
-  testFloat32x4Buffer(roundedFloatSamples);
-}
-
-double roundToFloat(double value) {
-  return (new Float32List(1)..[0] = value)[0];
-}
-
-typedef int Rounder(int value);
-
-Rounder roundUint(bits) {
-  int halfbits = (1 << (bits ~/ 2)) - 1;
-  int mask = halfbits | (halfbits << (bits ~/ 2));
-  return (int x) => x & mask;
-}
-
-Rounder roundInt(bits) {
-  int highBit = 1 << (bits - 1);
-  int mask = highBit - 1;
-  return (int x) => (x & mask) - (x & highBit);
-}
-
-int clampUint8(x) => x < 0 ? 0 : x > 255 ? 255 : x;
-
-void testUint(int bits, var buffer) {
-  int min = 0;
-  Function round = roundUint(bits);
-  int max = round(-1);
-  test("Uint${bits}Buffer", () {
-    testIntBuffer(bits, min, max, buffer, round);
-  });
-}
-
-void testInt(int bits, var buffer) {
-  int min = -(1 << (bits - 1));
-  int max = -(min + 1);
-  test("Int${bits}Buffer", () {
-    testIntBuffer(bits, min, max, buffer, roundInt(bits));
-  });
-}
-
-const List<int> intSamples = const [
-  0x10000000000000001,
-  0x10000000000000000,  // 2^64
-  0x0ffffffffffffffff,
-  0xaaaaaaaaaaaaaaaa,
-  0x8000000000000001,
-  0x8000000000000000,   // 2^63
-  0x7fffffffffffffff,
-  0x5555555555555555,
-  0x100000001,
-  0x100000000,  // 2^32
-  0x0ffffffff,
-  0xaaaaaaaa,
-  0x80000001,
-  0x80000000,   // 2^31
-  0x7fffffff,
-  0x55555555,
-  0x10001,
-  0x10000,      // 2^16
-  0x0ffff,
-  0xaaaa,
-  0x8001,
-  0x8000,       // 2^15
-  0x7fff,
-  0x5555,
-  0x101,
-  0x100,        // 2^8
-  0x0ff,
-  0xaa,
-  0x81,
-  0x80,         // 2^7
-  0x7f,
-  0x55,
-  0x02,
-  0x01,
-  0x00
-];
-
-// Takes bit-size, min value, max value, function to create a buffer, and
-// the rounding that is applied when storing values outside the valid range
-// into the buffer.
-void testIntBuffer(int bits, int min, int max,
-                   create(int length),
-                   int round(int)) {
-  assert(round(min) == min);
-  assert(round(max) == max);
-  // All int buffers default to the value 0.
-  var buffer = create(0);
-  List<int> list = buffer;  // Check the type.
-  expect(buffer.length, equals(0));
-  var bytes = bits ~/ 8;
-
-  expect(buffer.elementSizeInBytes, equals(bytes));
-  expect(buffer.lengthInBytes, equals(0));
-  expect(buffer.offsetInBytes, equals(0));
-
-  buffer.add(min);
-  expect(buffer.length, equals(1));
-  expect(buffer[0], equals(min));
-
-  expect(buffer.elementSizeInBytes, equals(bytes));
-  expect(buffer.lengthInBytes, equals(bytes));
-  expect(buffer.offsetInBytes, equals(0));
-
-  buffer.length = 0;
-  expect(buffer.length, equals(0));
-
-  List samples = intSamples.toList()..addAll(intSamples.map((x) => -x));
-  for (int value in samples) {
-    int length = buffer.length;
-    buffer.add(value);
-    expect(buffer.length, equals(length + 1));
-    expect(buffer[length], equals(round(value)));
-  }
-  buffer.addAll(samples);  // Add all the values at once.
-  for (int i = 0; i < samples.length; i++) {
-    expect(buffer[samples.length + i], equals(buffer[i]));
-  }
-
-  // Remove range works and changes length.
-  buffer.removeRange(samples.length, buffer.length);
-  expect(buffer.length, equals(samples.length));
-
-  // Both values are in `samples`, but equality is performed without rounding.
-  expect(buffer.contains(min - 1), isFalse);
-  expect(buffer.contains(max + 1), isFalse);
-  expect(buffer.contains(round(min - 1)), isTrue);
-  expect(buffer.contains(round(max + 1)), isTrue);
-
-  // Accessing the underlying buffer works.
-  buffer.length = 2;
-  buffer[0] = min;
-  buffer[1] = max;
-  var byteBuffer = new Uint8List.view(buffer.buffer);
-  int byteSize = buffer.elementSizeInBytes;
-  for (int i = 0; i < byteSize; i++) {
-    int tmp = byteBuffer[i];
-    byteBuffer[i] = byteBuffer[byteSize + i];
-    byteBuffer[byteSize + i] = tmp;
-  }
-  expect(buffer[0], equals(max));
-  expect(buffer[1], equals(min));
-}
-
-const List doubleSamples = const [
-  0.0,
-  5e-324,                    // Minimal denormal value.
-  2.225073858507201e-308,    // Maximal denormal value.
-  2.2250738585072014e-308,   // Minimal normal value.
-  0.9999999999999999,        // Maximum value < 1.
-  1.0,
-  1.0000000000000002,        // Minimum value > 1.
-  4294967295.0,              // 2^32 -1.
-  4294967296.0,              // 2^32.
-  4503599627370495.5,        // Maximal fractional value.
-  9007199254740992.0,        // Maximal exact value (adding one gets lost).
-  1.7976931348623157e+308,   // Maximal value.
-  1.0/0.0,                   // Infinity.
-  0.0/0.0,                   // NaN.
-  0.49999999999999994,       // Round-traps 1-3 (adding 0.5 and rounding towards
-  4503599627370497.0,        // minus infinity will not be the same as rounding
-  9007199254740991.0         // to nearest with 0.5 rounding up).
-];
-
-const List floatSamples = const [
-  0.0,
-  1.4e-45,          // Minimal denormal value.
-  1.1754942E-38,    // Maximal denormal value.
-  1.17549435E-38,   // Minimal normal value.
-  0.99999994,       // Maximal value < 1.
-  1.0,
-  1.0000001,        // Minimal value > 1.
-  8388607.5,        // Maximal fractional value.
-  16777216.0,       // Maximal exact value.
-  3.4028235e+38,    // Maximal value.
-  1.0/0.0,          // Infinity.
-  0.0/0.0,          // NaN.
-  0.99999994,       // Round traps 1-3.
-  8388609.0,
-  16777215.0
-];
-
-void doubleEqual(x, y) {
-  if (y.isNaN) {
-    expect(x.isNaN, isTrue);
-  } else {
-    if (x != y) {
-    }
-    expect(x, equals(y));
-  }
-}
-
-testFloatBuffer(int bitSize, List samples, create(), double round(double v)) {
-  test("Float${bitSize}Buffer", () {
-    var buffer = create();
-    List<double> list = buffer;  // Test type.
-    int byteSize = bitSize ~/ 8;
-
-    expect(buffer.length, equals(0));
-    buffer.add(0.0);
-    expect(buffer.length, equals(1));
-    expect(buffer.removeLast(), equals(0.0));
-    expect(buffer.length, equals(0));
-
-    for (double value in samples) {
-      buffer.add(value);
-      doubleEqual(buffer[buffer.length - 1], round(value));
-    }
-    expect(buffer.length, equals(samples.length));
-
-    buffer.addAll(samples);
-    expect(buffer.length, equals(samples.length * 2));
-    for (int i = 0; i < samples.length; i++) {
-      doubleEqual(buffer[i], buffer[samples.length + i]);
-    }
-
-    buffer.removeRange(samples.length, buffer.length);
-    expect(buffer.length, equals(samples.length));
-
-    buffer.insertAll(0, samples);
-    expect(buffer.length, equals(samples.length * 2));
-    for (int i = 0; i < samples.length; i++) {
-      doubleEqual(buffer[i], buffer[samples.length + i]);
-    }
-
-    buffer.length = samples.length;
-    expect(buffer.length, equals(samples.length));
-
-    // TypedData.
-    expect(buffer.elementSizeInBytes, equals(byteSize));
-    expect(buffer.lengthInBytes, equals(byteSize * buffer.length));
-    expect(buffer.offsetInBytes, equals(0));
-
-    // Accessing the buffer works.
-    // Accessing the underlying buffer works.
-    buffer.length = 2;
-    buffer[0] = samples[0];
-    buffer[1] = samples[1];
-    var bytes = new Uint8List.view(buffer.buffer);
-    for (int i = 0; i < byteSize; i++) {
-      int tmp = bytes[i];
-      bytes[i] = bytes[byteSize + i];
-      bytes[byteSize + i] = tmp;
-    }
-    doubleEqual(buffer[0], round(samples[1]));
-    doubleEqual(buffer[1], round(samples[0]));
-  });
-}
-
-testFloat32x4Buffer(List floatSamples) {
-  List float4Samples = [];
-  for (int i = 0; i < floatSamples.length - 3; i++) {
-    float4Samples.add(new Float32x4(floatSamples[i],
-                                    floatSamples[i + 1],
-                                    floatSamples[i + 2],
-                                    floatSamples[i + 3]));
-  }
-
-  void floatEquals(x, y) {
-    if (y.isNaN) {
-      expect(x.isNaN, isTrue);
-    } else {
-      expect(x, equals(y));
-    }
-  }
-
-  void x4Equals(Float32x4 x, Float32x4 y) {
-    floatEquals(x.x, y.x);
-    floatEquals(x.y, y.y);
-    floatEquals(x.z, y.z);
-    floatEquals(x.w, y.w);
-  }
-
-  test("Float32x4Buffer", () {
-    var buffer = new Float32x4Buffer(5);
-    List<Float32x4> list = buffer;
-
-    expect(buffer.length, equals(5));
-    expect(buffer.elementSizeInBytes, equals(128 ~/ 8));
-    expect(buffer.lengthInBytes, equals(5 * 128 ~/ 8));
-    expect(buffer.offsetInBytes, equals(0));
-
-    x4Equals(buffer[0], new Float32x4.zero());
-    buffer.length = 0;
-    expect(buffer.length, equals(0));
-
-    for (var sample in float4Samples) {
-      buffer.add(sample);
-      x4Equals(buffer[buffer.length - 1], sample);
-    }
-    expect(buffer.length, equals(float4Samples.length));
-
-    buffer.addAll(float4Samples);
-    expect(buffer.length, equals(float4Samples.length * 2));
-    for (int i = 0; i < float4Samples.length; i++) {
-      x4Equals(buffer[i], buffer[float4Samples.length + i]);
-    }
-
-    buffer.removeRange(4, 4 + float4Samples.length);
-    for (int i = 0; i < float4Samples.length; i++) {
-      x4Equals(buffer[i], float4Samples[i]);
-    }
-
-    // Test underlying buffer.
-    buffer.length = 1;
-    buffer[0] = float4Samples[0];  // Does not contain NaN.
-
-    Float32List floats = new Float32List.view(buffer.buffer);
-    expect(floats[0], equals(buffer[0].x));
-    expect(floats[1], equals(buffer[0].y));
-    expect(floats[2], equals(buffer[0].z));
-    expect(floats[3], equals(buffer[0].w));
-  });
-}
-
-void testInt32x4Buffer(intSamples) {
-  test("Int32x4Buffer", () {
-    Function round = roundInt(32);
-    int bits = 128;
-    int bytes = 128 ~/ 8;
-    Matcher equals32x4(Int32x4 expected) => new MatchesInt32x4(expected);
-
-    var buffer = new Int32x4Buffer(0);
-    List<Int32x4> list = buffer;     // It's a List.
-    expect(buffer.length, equals(0));
-
-    expect(buffer.elementSizeInBytes, equals(bytes));
-    expect(buffer.lengthInBytes, equals(0));
-    expect(buffer.offsetInBytes, equals(0));
-
-    Int32x4 sample = new Int32x4(-0x80000000, -1, 0, 0x7fffffff);
-    buffer.add(sample);
-    expect(buffer.length, equals(1));
-    expect(buffer[0], equals32x4(sample));
-
-    expect(buffer.elementSizeInBytes, equals(bytes));
-    expect(buffer.lengthInBytes, equals(bytes));
-    expect(buffer.offsetInBytes, equals(0));
-
-    buffer.length = 0;
-    expect(buffer.length, equals(0));
-
-    var samples = intSamples
-        .where((value) => value == round(value))   // Issue 15130
-        .map((value) => new Int32x4(value, -value, ~value, ~-value))
-        .toList();
-    for (Int32x4 value in samples) {
-      int length = buffer.length;
-      buffer.add(value);
-      expect(buffer.length, equals(length + 1));
-      expect(buffer[length], equals32x4(value));
-    }
-
-    buffer.addAll(samples);  // Add all the values at once.
-    for (int i = 0; i < samples.length; i++) {
-      expect(buffer[samples.length + i], equals32x4(buffer[i]));
-    }
-
-    // Remove range works and changes length.
-    buffer.removeRange(samples.length, buffer.length);
-    expect(buffer.length, equals(samples.length));
-
-    // Accessing the underlying buffer works.
-    buffer.length = 2;
-    buffer[0] = new Int32x4(-80000000, 0x7fffffff, 0, -1);
-    var byteBuffer = new Uint8List.view(buffer.buffer);
-    int halfBytes = bytes ~/ 2;
-    for (int i = 0; i < halfBytes; i++) {
-      int tmp = byteBuffer[i];
-      byteBuffer[i] = byteBuffer[halfBytes + i];
-      byteBuffer[halfBytes + i] = tmp;
-    }
-    var result = new Int32x4(0, -1, -80000000, 0x7fffffff);
-    expect(buffer[0], equals32x4(result));
-  });
-}
-
-class MatchesInt32x4 extends Matcher {
-  Int32x4 result;
-  MatchesInt32x4(this.result);
-  bool matches(item, Map matchState) {
-    if (item is! Int32x4) return false;
-    Int32x4 value = item;
-    return result.x == value.x && result.y == value.y &&
-           result.z == value.z && result.w == value.w;
-  }
-
-  Description describe(Description description) =>
-      description.add('Int32x4.==');
-}
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 02ba3c4..7a6c70f 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -239,7 +239,10 @@
     "*net/nss_memio.cc",
     "*net/nss_memio.h",
     "*root_certificates.cc",
-    "*secure_socket.cc",
+    "*secure_socket_boringssl.cc",
+    "*secure_socket_boringssl.h",
+    "*secure_socket_macos.cc",
+    "*secure_socket_macos.h",
     "*secure_socket.h",
     "filter.cc",
     "*io_service_unsupported.cc",
@@ -294,7 +297,10 @@
     "*net/nss_memio.cc",
     "*net/nss_memio.h",
     "*root_certificates.cc",
-    "*secure_socket.cc",
+    "*secure_socket_boringssl.cc",
+    "*secure_socket_boringssl.h",
+    "*secure_socket_macos.cc",
+    "*secure_socket_macos.h",
     "*secure_socket.h",
     "*filter_unsupported.cc",
     "*io_service_unsupported.cc",
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index 0840125..5bdd606 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -225,7 +225,7 @@
         ['exclude', '_test\\.(cc|h)$'],
       ],
       'conditions': [
-        ['dart_io_support==1 and dart_io_secure_socket==1', {
+        ['OS != "mac" and dart_io_support==1 and dart_io_secure_socket==1', {
           'dependencies': [
           '../third_party/boringssl/boringssl_dart.gyp:boringssl',
           ],
@@ -260,6 +260,7 @@
             'libraries': [
               '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
               '$(SDKROOT)/System/Library/Frameworks/CoreServices.framework',
+              '$(SDKROOT)/System/Library/Frameworks/Security.framework',
             ],
           },
         }],
@@ -300,7 +301,7 @@
             'bin/zlib.gyp:zlib_dart',
           ],
         }],
-        ['dart_io_support==1 and dart_io_secure_socket==1', {
+        ['OS != "mac" and dart_io_support==1 and dart_io_secure_socket==1', {
           'dependencies': [
             '../third_party/boringssl/boringssl_dart.gyp:boringssl',
           ],
@@ -332,6 +333,7 @@
             'libraries': [
               '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
               '$(SDKROOT)/System/Library/Frameworks/CoreServices.framework',
+              '$(SDKROOT)/System/Library/Frameworks/Security.framework',
             ],
           },
         }],
diff --git a/runtime/bin/builtin.cc b/runtime/bin/builtin.cc
index 021140b..272976f 100644
--- a/runtime/bin/builtin.cc
+++ b/runtime/bin/builtin.cc
@@ -38,10 +38,9 @@
 
     // Prepend the patch library URI to form a unique script URI for the patch.
     intptr_t len = snprintf(NULL, 0, "%s/%s", patch_uri, patch_files[j]);
-    char* patch_filename = reinterpret_cast<char*>(malloc(len + 1));
+    char* patch_filename = DartUtils::ScopedCString(len + 1);
     snprintf(patch_filename, len + 1, "%s/%s", patch_uri, patch_files[j]);
     Dart_Handle patch_file_uri = DartUtils::NewString(patch_filename);
-    free(patch_filename);
 
     DART_CHECK_VALID(Dart_LibraryLoadPatch(library, patch_file_uri, patch_src));
   }
diff --git a/runtime/bin/builtin.dart b/runtime/bin/builtin.dart
index 9a34b51..2f64b77 100644
--- a/runtime/bin/builtin.dart
+++ b/runtime/bin/builtin.dart
@@ -295,7 +295,18 @@
     if (mapping == null) {
       throw "No mapping for '$packageName' package when resolving '$uri'.";
     }
-    var path = uri.path.substring(packageName.length + 1);
+    var path;
+    if (uri.path.length > packageName.length) {
+      path = uri.path.substring(packageName.length + 1);
+    } else {
+      // Handle naked package resolution to the default package name:
+      // package:foo is equivalent to package:foo/foo.dart
+      assert(uri.path.length == packageName.length);
+      path = "$packageName.dart";
+    }
+    if (_traceLoading) {
+      _log("Path to be resolved in package: $path");
+    }
     resolvedUri = mapping.resolve(path);
   }
   if (_traceLoading) {
@@ -754,7 +765,17 @@
   }
   assert(_packagesReady);
 
-  var result = _resolvePackageUri(packageUri);
+  var result;
+  try {
+    result = _resolvePackageUri(packageUri);
+  } catch (e, s) {
+    // Any error during resolution will resolve this package as not mapped,
+    // which is indicated by a null return.
+    if (_traceLoading) {
+      _log("Exception ($e) when resolving package URI: $packageUri");
+    }
+    result = null;
+  }
   if (_traceLoading) {
     _log("Resolved '$packageUri' to '$result'");
   }
diff --git a/runtime/bin/builtin_gen_snapshot.cc b/runtime/bin/builtin_gen_snapshot.cc
index c1263bd..17d4a57 100644
--- a/runtime/bin/builtin_gen_snapshot.cc
+++ b/runtime/bin/builtin_gen_snapshot.cc
@@ -41,7 +41,7 @@
   int num_entries = sizeof(BuiltinEntries) / sizeof(struct NativeEntries);
   for (int i = 0; i < num_entries; i++) {
     struct NativeEntries* entry = &(BuiltinEntries[i]);
-    if (!strcmp(function_name, entry->name_) &&
+    if ((strcmp(function_name, entry->name_) == 0) &&
         (entry->argument_count_ == argument_count)) {
       return reinterpret_cast<Dart_NativeFunction>(entry->function_);
     }
diff --git a/runtime/bin/builtin_natives.cc b/runtime/bin/builtin_natives.cc
index 5ba5637..ba45a73 100644
--- a/runtime/bin/builtin_natives.cc
+++ b/runtime/bin/builtin_natives.cc
@@ -60,7 +60,7 @@
   int num_entries = sizeof(BuiltinEntries) / sizeof(struct NativeEntries);
   for (int i = 0; i < num_entries; i++) {
     struct NativeEntries* entry = &(BuiltinEntries[i]);
-    if (!strcmp(function_name, entry->name_) &&
+    if ((strcmp(function_name, entry->name_) == 0) &&
         (entry->argument_count_ == argument_count)) {
       return reinterpret_cast<Dart_NativeFunction>(entry->function_);
     }
@@ -88,7 +88,9 @@
   uint8_t* chars = NULL;
   Dart_Handle str = Dart_GetNativeArgument(args, 0);
   Dart_Handle result = Dart_StringToUTF8(str, &chars, &length);
-  if (Dart_IsError(result)) Dart_PropagateError(result);
+  if (Dart_IsError(result)) {
+    Dart_PropagateError(result);
+  }
 
   // Uses fwrite to support printing NUL bytes.
   intptr_t res = fwrite(chars, 1, length, stdout);
diff --git a/runtime/bin/builtin_nolib.cc b/runtime/bin/builtin_nolib.cc
index fb4cf02..428927f 100644
--- a/runtime/bin/builtin_nolib.cc
+++ b/runtime/bin/builtin_nolib.cc
@@ -10,7 +10,6 @@
 #include "bin/dartutils.h"
 #include "bin/io_natives.h"
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/crypto_android.cc b/runtime/bin/crypto_android.cc
index be91d4e..7a970d0 100644
--- a/runtime/bin/crypto_android.cc
+++ b/runtime/bin/crypto_android.cc
@@ -8,8 +8,8 @@
 #include <errno.h>  // NOLINT
 #include <fcntl.h>  // NOLINT
 
-#include "bin/fdutils.h"
 #include "bin/crypto.h"
+#include "bin/fdutils.h"
 #include "platform/signal_blocker.h"
 
 namespace dart {
diff --git a/runtime/bin/crypto_linux.cc b/runtime/bin/crypto_linux.cc
index 875ec8e..c2e4ccd 100644
--- a/runtime/bin/crypto_linux.cc
+++ b/runtime/bin/crypto_linux.cc
@@ -8,8 +8,8 @@
 #include <errno.h>  // NOLINT
 #include <fcntl.h>  // NOLINT
 
-#include "bin/fdutils.h"
 #include "bin/crypto.h"
+#include "bin/fdutils.h"
 #include "platform/signal_blocker.h"
 
 namespace dart {
diff --git a/runtime/bin/crypto_macos.cc b/runtime/bin/crypto_macos.cc
index 8a27245..7bea2ae 100644
--- a/runtime/bin/crypto_macos.cc
+++ b/runtime/bin/crypto_macos.cc
@@ -8,8 +8,8 @@
 #include <errno.h>  // NOLINT
 #include <fcntl.h>  // NOLINT
 
-#include "bin/fdutils.h"
 #include "bin/crypto.h"
+#include "bin/fdutils.h"
 #include "platform/signal_blocker.h"
 
 namespace dart {
diff --git a/runtime/bin/directory.cc b/runtime/bin/directory.cc
index 3791197..c2f3dc8 100644
--- a/runtime/bin/directory.cc
+++ b/runtime/bin/directory.cc
@@ -8,7 +8,6 @@
 #include "include/dart_api.h"
 #include "platform/assert.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -28,7 +27,7 @@
   if (argc == 1) {
     path = Dart_GetNativeArgument(args, 0);
   }
-  if (argc != 1 || !Dart_IsString(path)) {
+  if ((argc != 1) || !Dart_IsString(path)) {
     Dart_SetReturnValue(args, DartUtils::NewDartArgumentError(NULL));
   } else {
     if (Directory::SetCurrent(DartUtils::GetStringValue(path))) {
@@ -66,8 +65,7 @@
 }
 
 
-void FUNCTION_NAME(Directory_SystemTemp)(
-    Dart_NativeArguments args) {
+void FUNCTION_NAME(Directory_SystemTemp)(Dart_NativeArguments args) {
   const char* result = Directory::SystemTemp();
   Dart_SetReturnValue(args, DartUtils::NewString(result));
 }
@@ -127,7 +125,9 @@
                Dart_Null(),
                0,
                NULL);
-  if (Dart_IsError(results)) Dart_PropagateError(results);
+  if (Dart_IsError(results)) {
+    Dart_PropagateError(results);
+  }
   SyncDirectoryListing sync_listing(results,
                                     DartUtils::GetStringValue(path),
                                     DartUtils::GetBooleanValue(recursive),
@@ -138,7 +138,7 @@
 
 
 CObject* Directory::CreateRequest(const CObjectArray& request) {
-  if (request.Length() == 1 && request[0]->IsString()) {
+  if ((request.Length() == 1) && request[0]->IsString()) {
     CObjectString path(request[0]);
     if (Directory::Create(path.CString())) {
       return CObject::True();
@@ -151,7 +151,8 @@
 
 
 CObject* Directory::DeleteRequest(const CObjectArray& request) {
-  if (request.Length() == 2 && request[0]->IsString() && request[1]->IsBool()) {
+  if ((request.Length() == 2) &&
+       request[0]->IsString() && request[1]->IsBool()) {
     CObjectString path(request[0]);
     CObjectBool recursive(request[1]);
     if (Directory::Delete(path.CString(), recursive.Value())) {
@@ -167,7 +168,7 @@
 CObject* Directory::ExistsRequest(const CObjectArray& request) {
   static const int kExists = 1;
   static const int kDoesNotExist = 0;
-  if (request.Length() == 1 && request[0]->IsString()) {
+  if ((request.Length() == 1) && request[0]->IsString()) {
     CObjectString path(request[0]);
     Directory::ExistsResult result = Directory::Exists(path.CString());
     if (result == Directory::EXISTS) {
@@ -183,7 +184,7 @@
 
 
 CObject* Directory::CreateTempRequest(const CObjectArray& request) {
-  if (request.Length() == 1 && request[0]->IsString()) {
+  if ((request.Length() == 1) && request[0]->IsString()) {
     CObjectString path(request[0]);
     const char* result = Directory::CreateTemp(path.CString());
     if (result != NULL) {
@@ -209,7 +210,7 @@
 
 
 CObject* Directory::ListStartRequest(const CObjectArray& request) {
-  if (request.Length() == 3 &&
+  if ((request.Length() == 3) &&
       request[0]->IsString() &&
       request[1]->IsBool() &&
       request[2]->IsBool()) {
@@ -273,7 +274,7 @@
 
 
 CObject* Directory::RenameRequest(const CObjectArray& request) {
-  if (request.Length() == 2 &&
+  if ((request.Length() == 2) &&
       request[0]->IsString() &&
       request[1]->IsString()) {
     CObjectString path(request[0]);
diff --git a/runtime/bin/directory.h b/runtime/bin/directory.h
index e37aa76..7a1c5d1 100644
--- a/runtime/bin/directory.h
+++ b/runtime/bin/directory.h
@@ -10,7 +10,6 @@
 #include "bin/thread.h"
 #include "platform/globals.h"
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/directory_android.cc b/runtime/bin/directory_android.cc
index 6571f18..95f42da 100644
--- a/runtime/bin/directory_android.cc
+++ b/runtime/bin/directory_android.cc
@@ -82,8 +82,8 @@
 // A linked list of symbolic links, with their unique file system identifiers.
 // These are scanned to detect loops while doing a recursive directory listing.
 struct LinkList {
-  dev_t dev;
-  ino_t ino;
+  uint64_t dev;
+  uint64_t ino;
   LinkList* next;
 };
 
@@ -366,9 +366,8 @@
 char* Directory::CurrentNoScope() {
   // Android's getcwd adheres closely to the POSIX standard. It won't
   // allocate memory. We need to make our own copy.
-
   char buffer[PATH_MAX];
-  if (NULL == getcwd(buffer, PATH_MAX)) {
+  if (getcwd(buffer, PATH_MAX) == NULL) {
     return NULL;
   }
 
@@ -377,15 +376,17 @@
 
 
 const char* Directory::Current() {
-  char* result = DartUtils::ScopedCString(PATH_MAX);
-  ASSERT(result != NULL);
-  return getcwd(result, PATH_MAX);
+  char buffer[PATH_MAX];
+  if (getcwd(buffer, PATH_MAX) == NULL) {
+    return NULL;
+  }
+  return DartUtils::ScopedCopyCString(buffer);
 }
 
 
 bool Directory::SetCurrent(const char* path) {
   int result = NO_RETRY_EXPECTED(chdir(path));
-  return result == 0;
+  return (result == 0);
 }
 
 
diff --git a/runtime/bin/directory_linux.cc b/runtime/bin/directory_linux.cc
index 8430134..d099b0e 100644
--- a/runtime/bin/directory_linux.cc
+++ b/runtime/bin/directory_linux.cc
@@ -366,11 +366,7 @@
 
 
 char* Directory::CurrentNoScope() {
-  char buffer[PATH_MAX];
-  if (getcwd(buffer, PATH_MAX) == NULL) {
-    return NULL;
-  }
-  return strdup(buffer);
+  return getcwd(NULL, 0);
 }
 
 
@@ -384,7 +380,7 @@
 
 
 bool Directory::SetCurrent(const char* path) {
-  return NO_RETRY_EXPECTED(chdir(path)) == 0;
+  return (NO_RETRY_EXPECTED(chdir(path)) == 0);
 }
 
 
@@ -469,7 +465,7 @@
   if (exists != EXISTS) {
     return false;
   }
-  return NO_RETRY_EXPECTED(rename(path, new_path)) == 0;
+  return (NO_RETRY_EXPECTED(rename(path, new_path)) == 0);
 }
 
 }  // namespace bin
diff --git a/runtime/bin/directory_macos.cc b/runtime/bin/directory_macos.cc
index a10b20a..5c0f5a6 100644
--- a/runtime/bin/directory_macos.cc
+++ b/runtime/bin/directory_macos.cc
@@ -369,15 +369,17 @@
 
 
 const char* Directory::Current() {
-  char* result = DartUtils::ScopedCString(PATH_MAX);
-  ASSERT(result != NULL);
-  return getcwd(result, PATH_MAX);
+  char buffer[PATH_MAX];
+  if (getcwd(buffer, PATH_MAX) == NULL) {
+    return NULL;
+  }
+  return DartUtils::ScopedCopyCString(buffer);
 }
 
 
 bool Directory::SetCurrent(const char* path) {
   int result = NO_RETRY_EXPECTED(chdir(path));
-  return result == 0;
+  return (result == 0);
 }
 
 
diff --git a/runtime/bin/embedded_dart_io.h b/runtime/bin/embedded_dart_io.h
index 4d7dbae..a5b069d 100644
--- a/runtime/bin/embedded_dart_io.h
+++ b/runtime/bin/embedded_dart_io.h
@@ -23,7 +23,6 @@
 // Should Stderr events be captured?
 bool ShouldCaptureStderr();
 
-
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/eventhandler.cc b/runtime/bin/eventhandler.cc
index bb9a7fe..704cc85 100644
--- a/runtime/bin/eventhandler.cc
+++ b/runtime/bin/eventhandler.cc
@@ -10,11 +10,9 @@
 
 #include "include/dart_api.h"
 
-
 namespace dart {
 namespace bin {
 
-
 void TimeoutQueue::UpdateTimeout(Dart_Port port, int64_t timeout) {
   // Find port if present.
   Timeout* last = NULL;
@@ -47,8 +45,8 @@
   next_timeout_ = NULL;
   current = timeouts_;
   while (current != NULL) {
-    if (next_timeout_ == NULL ||
-        current->timeout() < next_timeout_->timeout()) {
+    if ((next_timeout_ == NULL) ||
+        (current->timeout() < next_timeout_->timeout())) {
       next_timeout_ = current;
     }
     current = current->next();
@@ -78,7 +76,9 @@
 
 
 void EventHandler::Stop() {
-  if (event_handler == NULL) return;
+  if (event_handler == NULL) {
+    return;
+  }
 
   // Wait until it has stopped.
   {
@@ -101,7 +101,9 @@
 
 
 EventHandlerImplementation* EventHandler::delegate() {
-  if (event_handler == NULL) return NULL;
+  if (event_handler == NULL) {
+    return NULL;
+  }
   return &event_handler->delegate_;
 }
 
diff --git a/runtime/bin/eventhandler.h b/runtime/bin/eventhandler.h
index c110d34..34f6c65 100644
--- a/runtime/bin/eventhandler.h
+++ b/runtime/bin/eventhandler.h
@@ -108,6 +108,8 @@
  private:
   Timeout* next_timeout_;
   Timeout* timeouts_;
+
+  DISALLOW_COPY_AND_ASSIGN(TimeoutQueue);
 };
 
 
@@ -221,6 +223,8 @@
   };
 
   Entry* head_;
+
+  DISALLOW_COPY_AND_ASSIGN(CircularLinkedList);
 };
 
 
@@ -268,6 +272,9 @@
 
  protected:
   intptr_t fd_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DescriptorInfoBase);
 };
 
 
@@ -281,7 +288,7 @@
   static const int kTokenCount = 16;
 
  public:
-  explicit DescriptorInfoSingleMixin(intptr_t fd, bool disable_tokens)
+  DescriptorInfoSingleMixin(intptr_t fd, bool disable_tokens)
       : DI(fd), port_(0), tokens_(kTokenCount), mask_(0),
         disable_tokens_(disable_tokens) {}
 
@@ -356,6 +363,8 @@
   int tokens_;
   intptr_t mask_;
   bool disable_tokens_;
+
+  DISALLOW_COPY_AND_ASSIGN(DescriptorInfoSingleMixin);
 };
 
 
@@ -400,7 +409,7 @@
   };
 
  public:
-  explicit DescriptorInfoMultipleMixin(intptr_t fd, bool disable_tokens)
+  DescriptorInfoMultipleMixin(intptr_t fd, bool disable_tokens)
       : DI(fd), tokens_map_(&SamePortValue, kTokenCount),
         disable_tokens_(disable_tokens) {}
 
@@ -541,7 +550,7 @@
         pentry->token_count--;
       }
 
-      if (was_ready && pentry->token_count <= 0) {
+      if (was_ready && (pentry->token_count <= 0)) {
         active_readers_.Remove(pentry);
       }
     }
@@ -586,8 +595,9 @@
   HashMap tokens_map_;
 
   bool disable_tokens_;
-};
 
+  DISALLOW_COPY_AND_ASSIGN(DescriptorInfoMultipleMixin);
+};
 
 }  // namespace bin
 }  // namespace dart
@@ -610,6 +620,7 @@
 
 class EventHandler {
  public:
+  EventHandler() {}
   void SendData(intptr_t id, Dart_Port dart_port, int64_t data) {
     delegate_.SendData(id, dart_port, data);
   }
@@ -635,6 +646,8 @@
  private:
   friend class EventHandlerImplementation;
   EventHandlerImplementation delegate_;
+
+  DISALLOW_COPY_AND_ASSIGN(EventHandler);
 };
 
 }  // namespace bin
diff --git a/runtime/bin/eventhandler_android.cc b/runtime/bin/eventhandler_android.cc
index 6fdabfb..5daeb78 100644
--- a/runtime/bin/eventhandler_android.cc
+++ b/runtime/bin/eventhandler_android.cc
@@ -9,13 +9,13 @@
 #include "bin/eventhandler_android.h"
 
 #include <errno.h>  // NOLINT
+#include <fcntl.h>  // NOLINT
 #include <pthread.h>  // NOLINT
 #include <stdio.h>  // NOLINT
 #include <string.h>  // NOLINT
 #include <sys/epoll.h>  // NOLINT
 #include <sys/stat.h>  // NOLINT
 #include <unistd.h>  // NOLINT
-#include <fcntl.h>  // NOLINT
 
 #include "bin/dartutils.h"
 #include "bin/fdutils.h"
@@ -27,17 +27,14 @@
 #include "platform/hashmap.h"
 #include "platform/utils.h"
 
-
 // Android doesn't define EPOLLRDHUP.
 #if !defined(EPOLLRDHUP)
 #define EPOLLRDHUP 0x2000
 #endif  // !defined(EPOLLRDHUP)
 
-
 namespace dart {
 namespace bin {
 
-
 intptr_t DescriptorInfo::GetPollEvents() {
   // Do not ask for EPOLLERR and EPOLLHUP explicitly as they are
   // triggered anyway.
@@ -129,11 +126,11 @@
 void EventHandlerImplementation::UpdateEpollInstance(intptr_t old_mask,
                                                      DescriptorInfo *di) {
   intptr_t new_mask = di->Mask();
-  if (old_mask != 0 && new_mask == 0) {
+  if ((old_mask != 0) && (new_mask == 0)) {
     RemoveFromEpollInstance(epoll_fd_, di);
-  } else if (old_mask == 0 && new_mask != 0) {
+  } else if ((old_mask == 0) && (new_mask != 0)) {
     AddToEpollInstance(epoll_fd_, di);
-  } else if (old_mask != 0 && new_mask != 0 && old_mask != new_mask) {
+  } else if ((old_mask != 0) && (new_mask != 0) && (old_mask != new_mask)) {
     ASSERT(!di->IsListeningSocket());
     RemoveFromEpollInstance(epoll_fd_, di);
     AddToEpollInstance(epoll_fd_, di);
@@ -264,15 +261,28 @@
   }
 }
 
+
 #ifdef DEBUG_POLL
 static void PrintEventMask(intptr_t fd, intptr_t events) {
   Log::Print("%d ", fd);
-  if ((events & EPOLLIN) != 0) Log::Print("EPOLLIN ");
-  if ((events & EPOLLPRI) != 0) Log::Print("EPOLLPRI ");
-  if ((events & EPOLLOUT) != 0) Log::Print("EPOLLOUT ");
-  if ((events & EPOLLERR) != 0) Log::Print("EPOLLERR ");
-  if ((events & EPOLLHUP) != 0) Log::Print("EPOLLHUP ");
-  if ((events & EPOLLRDHUP) != 0) Log::Print("EPOLLRDHUP ");
+  if ((events & EPOLLIN) != 0) {
+    Log::Print("EPOLLIN ");
+  }
+  if ((events & EPOLLPRI) != 0) {
+    Log::Print("EPOLLPRI ");
+  }
+  if ((events & EPOLLOUT) != 0) {
+    Log::Print("EPOLLOUT ");
+  }
+  if ((events & EPOLLERR) != 0) {
+    Log::Print("EPOLLERR ");
+  }
+  if ((events & EPOLLHUP) != 0) {
+    Log::Print("EPOLLHUP ");
+  }
+  if ((events & EPOLLRDHUP) != 0) {
+    Log::Print("EPOLLRDHUP ");
+  }
   int all_events = EPOLLIN | EPOLLPRI | EPOLLOUT |
       EPOLLERR | EPOLLHUP | EPOLLRDHUP;
   if ((events & ~all_events) != 0) {
@@ -284,19 +294,26 @@
 }
 #endif
 
+
 intptr_t EventHandlerImplementation::GetPollEvents(intptr_t events,
                                                    DescriptorInfo* di) {
 #ifdef DEBUG_POLL
   PrintEventMask(di->fd(), events);
 #endif
-  if (events & EPOLLERR) {
+  if ((events & EPOLLERR) != 0) {
     // Return error only if EPOLLIN is present.
-    return (events & EPOLLIN) ? (1 << kErrorEvent) : 0;
+    return ((events & EPOLLIN) != 0) ? (1 << kErrorEvent) : 0;
   }
   intptr_t event_mask = 0;
-  if (events & EPOLLIN) event_mask |= (1 << kInEvent);
-  if (events & EPOLLOUT) event_mask |= (1 << kOutEvent);
-  if (events & (EPOLLHUP | EPOLLRDHUP)) event_mask |= (1 << kCloseEvent);
+  if ((events & EPOLLIN) != 0) {
+    event_mask |= (1 << kInEvent);
+  }
+  if ((events & EPOLLOUT) != 0) {
+    event_mask |= (1 << kOutEvent);
+  }
+  if ((events & (EPOLLHUP | EPOLLRDHUP)) != 0) {
+    event_mask |= (1 << kCloseEvent);
+  }
   return event_mask;
 }
 
@@ -360,8 +377,10 @@
 
   while (!handler_impl->shutdown_) {
     int64_t millis = handler_impl->GetTimeout();
-    ASSERT(millis == kInfinityTimeout || millis >= 0);
-    if (millis > kMaxInt32) millis = kMaxInt32;
+    ASSERT((millis == kInfinityTimeout) || (millis >= 0));
+    if (millis > kMaxInt32) {
+      millis = kMaxInt32;
+    }
     intptr_t result = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER(
         epoll_wait(handler_impl->epoll_fd_, events, kMaxEvents, millis));
     ASSERT(EAGAIN == EWOULDBLOCK);
diff --git a/runtime/bin/eventhandler_android.h b/runtime/bin/eventhandler_android.h
index ee10016..8841861 100644
--- a/runtime/bin/eventhandler_android.h
+++ b/runtime/bin/eventhandler_android.h
@@ -18,7 +18,6 @@
 #include "platform/hashmap.h"
 #include "platform/signal_blocker.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -34,6 +33,9 @@
     VOID_TEMP_FAILURE_RETRY(close(fd_));
     fd_ = -1;
   }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DescriptorInfo);
 };
 
 
@@ -43,6 +45,9 @@
   explicit DescriptorInfoSingle(intptr_t fd)
       : DescriptorInfoSingleMixin(fd, false) {}
   virtual ~DescriptorInfoSingle() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DescriptorInfoSingle);
 };
 
 
@@ -52,6 +57,9 @@
   explicit DescriptorInfoMultiple(intptr_t fd)
       : DescriptorInfoMultipleMixin(fd, false) {}
   virtual ~DescriptorInfoMultiple() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DescriptorInfoMultiple);
 };
 
 
@@ -86,6 +94,8 @@
   bool shutdown_;
   int interrupt_fds_[2];
   int epoll_fd_;
+
+  DISALLOW_COPY_AND_ASSIGN(EventHandlerImplementation);
 };
 
 }  // namespace bin
diff --git a/runtime/bin/eventhandler_linux.cc b/runtime/bin/eventhandler_linux.cc
index 4c605ce..6b69ffc 100644
--- a/runtime/bin/eventhandler_linux.cc
+++ b/runtime/bin/eventhandler_linux.cc
@@ -9,6 +9,7 @@
 #include "bin/eventhandler_linux.h"
 
 #include <errno.h>  // NOLINT
+#include <fcntl.h>  // NOLINT
 #include <pthread.h>  // NOLINT
 #include <stdio.h>  // NOLINT
 #include <string.h>  // NOLINT
@@ -16,7 +17,6 @@
 #include <sys/stat.h>  // NOLINT
 #include <sys/timerfd.h>  // NOLINT
 #include <unistd.h>  // NOLINT
-#include <fcntl.h>  // NOLINT
 
 #include "bin/dartutils.h"
 #include "bin/fdutils.h"
@@ -26,11 +26,9 @@
 #include "bin/thread.h"
 #include "platform/utils.h"
 
-
 namespace dart {
 namespace bin {
 
-
 intptr_t DescriptorInfo::GetPollEvents() {
   // Do not ask for EPOLLERR and EPOLLHUP explicitly as they are
   // triggered anyway.
@@ -138,11 +136,11 @@
 void EventHandlerImplementation::UpdateEpollInstance(intptr_t old_mask,
                                                      DescriptorInfo *di) {
   intptr_t new_mask = di->Mask();
-  if (old_mask != 0 && new_mask == 0) {
+  if ((old_mask != 0) && (new_mask == 0)) {
     RemoveFromEpollInstance(epoll_fd_, di);
-  } else if (old_mask == 0 && new_mask != 0) {
+  } else if ((old_mask == 0) && (new_mask != 0)) {
     AddToEpollInstance(epoll_fd_, di);
-  } else if (old_mask != 0 && new_mask != 0 && old_mask != new_mask) {
+  } else if ((old_mask != 0) && (new_mask != 0) && (old_mask != new_mask)) {
     ASSERT(!di->IsListeningSocket());
     RemoveFromEpollInstance(epoll_fd_, di);
     AddToEpollInstance(epoll_fd_, di);
@@ -156,8 +154,7 @@
   HashMap::Entry* entry = socket_map_.Lookup(
       GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true);
   ASSERT(entry != NULL);
-  DescriptorInfo* di =
-      reinterpret_cast<DescriptorInfo*>(entry->value);
+  DescriptorInfo* di = reinterpret_cast<DescriptorInfo*>(entry->value);
   if (di == NULL) {
     // If there is no data in the hash map for this file descriptor a
     // new DescriptorInfo for the file descriptor is inserted.
@@ -282,15 +279,28 @@
   }
 }
 
+
 #ifdef DEBUG_POLL
 static void PrintEventMask(intptr_t fd, intptr_t events) {
   Log::Print("%d ", fd);
-  if ((events & EPOLLIN) != 0) Log::Print("EPOLLIN ");
-  if ((events & EPOLLPRI) != 0) Log::Print("EPOLLPRI ");
-  if ((events & EPOLLOUT) != 0) Log::Print("EPOLLOUT ");
-  if ((events & EPOLLERR) != 0) Log::Print("EPOLLERR ");
-  if ((events & EPOLLHUP) != 0) Log::Print("EPOLLHUP ");
-  if ((events & EPOLLRDHUP) != 0) Log::Print("EPOLLRDHUP ");
+  if ((events & EPOLLIN) != 0) {
+    Log::Print("EPOLLIN ");
+  }
+  if ((events & EPOLLPRI) != 0) {
+    Log::Print("EPOLLPRI ");
+  }
+  if ((events & EPOLLOUT) != 0) {
+    Log::Print("EPOLLOUT ");
+  }
+  if ((events & EPOLLERR) != 0) {
+    Log::Print("EPOLLERR ");
+  }
+  if ((events & EPOLLHUP) != 0) {
+    Log::Print("EPOLLHUP ");
+  }
+  if ((events & EPOLLRDHUP) != 0) {
+    Log::Print("EPOLLRDHUP ");
+  }
   int all_events = EPOLLIN | EPOLLPRI | EPOLLOUT |
       EPOLLERR | EPOLLHUP | EPOLLRDHUP;
   if ((events & ~all_events) != 0) {
@@ -302,19 +312,26 @@
 }
 #endif
 
+
 intptr_t EventHandlerImplementation::GetPollEvents(intptr_t events,
                                                    DescriptorInfo* di) {
 #ifdef DEBUG_POLL
   PrintEventMask(di->fd(), events);
 #endif
-  if (events & EPOLLERR) {
+  if ((events & EPOLLERR) != 0) {
     // Return error only if EPOLLIN is present.
-    return (events & EPOLLIN) ? (1 << kErrorEvent) : 0;
+    return ((events & EPOLLIN) != 0) ? (1 << kErrorEvent) : 0;
   }
   intptr_t event_mask = 0;
-  if (events & EPOLLIN) event_mask |= (1 << kInEvent);
-  if (events & EPOLLOUT) event_mask |= (1 << kOutEvent);
-  if (events & (EPOLLHUP | EPOLLRDHUP)) event_mask |= (1 << kCloseEvent);
+  if ((events & EPOLLIN) != 0) {
+    event_mask |= (1 << kInEvent);
+  }
+  if ((events & EPOLLOUT) != 0) {
+    event_mask |= (1 << kOutEvent);
+  }
+  if ((events & (EPOLLHUP | EPOLLRDHUP)) != 0) {
+    event_mask |= (1 << kCloseEvent);
+  }
   return event_mask;
 }
 
diff --git a/runtime/bin/eventhandler_linux.h b/runtime/bin/eventhandler_linux.h
index 099bef5..dd87c22 100644
--- a/runtime/bin/eventhandler_linux.h
+++ b/runtime/bin/eventhandler_linux.h
@@ -33,6 +33,9 @@
     VOID_TEMP_FAILURE_RETRY(close(fd_));
     fd_ = -1;
   }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DescriptorInfo);
 };
 
 
@@ -42,6 +45,9 @@
   explicit DescriptorInfoSingle(intptr_t fd)
       : DescriptorInfoSingleMixin(fd, false) {}
   virtual ~DescriptorInfoSingle() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DescriptorInfoSingle);
 };
 
 
@@ -51,6 +57,9 @@
   explicit DescriptorInfoMultiple(intptr_t fd)
       : DescriptorInfoMultipleMixin(fd, false) {}
   virtual ~DescriptorInfoMultiple() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DescriptorInfoMultiple);
 };
 
 
@@ -84,6 +93,8 @@
   int interrupt_fds_[2];
   int epoll_fd_;
   int timer_fd_;
+
+  DISALLOW_COPY_AND_ASSIGN(EventHandlerImplementation);
 };
 
 }  // namespace bin
diff --git a/runtime/bin/eventhandler_macos.cc b/runtime/bin/eventhandler_macos.cc
index faf471b..8d4c683 100644
--- a/runtime/bin/eventhandler_macos.cc
+++ b/runtime/bin/eventhandler_macos.cc
@@ -9,12 +9,12 @@
 #include "bin/eventhandler_macos.h"
 
 #include <errno.h>  // NOLINT
+#include <fcntl.h>  // NOLINT
 #include <pthread.h>  // NOLINT
 #include <stdio.h>  // NOLINT
 #include <string.h>  // NOLINT
 #include <sys/event.h>  // NOLINT
 #include <unistd.h>  // NOLINT
-#include <fcntl.h>  // NOLINT
 
 #include "bin/dartutils.h"
 #include "bin/fdutils.h"
@@ -26,11 +26,9 @@
 #include "platform/hashmap.h"
 #include "platform/utils.h"
 
-
 namespace dart {
 namespace bin {
 
-
 bool DescriptorInfo::HasReadEvent() {
   return (Mask() & (1 << kInEvent)) != 0;
 }
@@ -43,7 +41,9 @@
 
 // Unregister the file descriptor for a SocketData structure with kqueue.
 static void RemoveFromKqueue(intptr_t kqueue_fd_, DescriptorInfo* di) {
-  if (!di->tracked_by_kqueue()) return;
+  if (!di->tracked_by_kqueue()) {
+    return;
+  }
   static const intptr_t kMaxChanges = 2;
   struct kevent events[kMaxChanges];
   EV_SET(events, di->fd(), EVFILT_READ, EV_DELETE, 0, 0, NULL);
@@ -150,9 +150,9 @@
   intptr_t new_mask = di->Mask();
   if (old_mask != 0 && new_mask == 0) {
     RemoveFromKqueue(kqueue_fd_, di);
-  } else if (old_mask == 0 && new_mask != 0) {
+  } else if ((old_mask == 0) && (new_mask != 0)) {
     AddToKqueue(kqueue_fd_, di);
-  } else if (old_mask != 0 && new_mask != 0 && old_mask != new_mask) {
+  } else if ((old_mask != 0) && (new_mask != 0) && (old_mask != new_mask)) {
     ASSERT(!di->IsListeningSocket());
     RemoveFromKqueue(kqueue_fd_, di);
     AddToKqueue(kqueue_fd_, di);
@@ -281,22 +281,39 @@
   }
 }
 
+
 #ifdef DEBUG_KQUEUE
 static void PrintEventMask(intptr_t fd, struct kevent* event) {
   Log::Print("%d ", static_cast<int>(fd));
+
   Log::Print("filter=0x%x:", event->filter);
-  if (event->filter == EVFILT_READ) Log::Print("EVFILT_READ ");
-  if (event->filter == EVFILT_WRITE) Log::Print("EVFILT_WRITE ");
+  if (event->filter == EVFILT_READ) {
+    Log::Print("EVFILT_READ ");
+  }
+  if (event->filter == EVFILT_WRITE) {
+    Log::Print("EVFILT_WRITE ");
+  }
+
   Log::Print("flags: %x: ", event->flags);
-  if ((event->flags & EV_EOF) != 0) Log::Print("EV_EOF ");
-  if ((event->flags & EV_ERROR) != 0) Log::Print("EV_ERROR ");
-  if ((event->flags & EV_CLEAR) != 0) Log::Print("EV_CLEAR ");
-  if ((event->flags & EV_ADD) != 0) Log::Print("EV_ADD ");
-  if ((event->flags & EV_DELETE) != 0) Log::Print("EV_DELETE ");
+  if ((event->flags & EV_EOF) != 0) {
+    Log::Print("EV_EOF ");
+  }
+  if ((event->flags & EV_ERROR) != 0) {
+    Log::Print("EV_ERROR ");
+  }
+  if ((event->flags & EV_CLEAR) != 0) {
+    Log::Print("EV_CLEAR ");
+  }
+  if ((event->flags & EV_ADD) != 0) {
+    Log::Print("EV_ADD ");
+  }
+  if ((event->flags & EV_DELETE) != 0) {
+    Log::Print("EV_DELETE ");
+  }
+
   Log::Print("- fflags: %d ", event->fflags);
   Log::Print("- data: %ld ", event->data);
-  Log::Print("(available %d) ",
-      static_cast<int>(FDUtils::AvailableBytes(fd)));
+  Log::Print("(available %d) ", static_cast<int>(FDUtils::AvailableBytes(fd)));
   Log::Print("\n");
 }
 #endif
@@ -319,7 +336,9 @@
           event_mask |= (1 << kCloseEvent);
         }
       }
-      if (event_mask == 0) event_mask |= (1 << kInEvent);
+      if (event_mask == 0) {
+        event_mask |= (1 << kInEvent);
+      }
     } else {
       UNREACHABLE();
     }
@@ -421,7 +440,9 @@
   while (!handler_impl->shutdown_) {
     int64_t millis = handler_impl->GetTimeout();
     ASSERT(millis == kInfinityTimeout || millis >= 0);
-    if (millis > kMaxInt32) millis = kMaxInt32;
+    if (millis > kMaxInt32) {
+      millis = kMaxInt32;
+    }
     // NULL pointer timespec for infinite timeout.
     ASSERT(kInfinityTimeout < 0);
     struct timespec* timeout = NULL;
diff --git a/runtime/bin/eventhandler_macos.h b/runtime/bin/eventhandler_macos.h
index 48b0b96..b846594 100644
--- a/runtime/bin/eventhandler_macos.h
+++ b/runtime/bin/eventhandler_macos.h
@@ -47,6 +47,9 @@
 
  protected:
   bool tracked_by_kqueue_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DescriptorInfo);
 };
 
 
@@ -56,6 +59,9 @@
   explicit DescriptorInfoSingle(intptr_t fd)
       : DescriptorInfoSingleMixin(fd, false) {}
   virtual ~DescriptorInfoSingle() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DescriptorInfoSingle);
 };
 
 
@@ -65,6 +71,9 @@
   explicit DescriptorInfoMultiple(intptr_t fd)
       : DescriptorInfoMultipleMixin(fd, false) {}
   virtual ~DescriptorInfoMultiple() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DescriptorInfoMultiple);
 };
 
 
@@ -99,6 +108,8 @@
   bool shutdown_;
   int interrupt_fds_[2];
   int kqueue_fd_;
+
+  DISALLOW_COPY_AND_ASSIGN(EventHandlerImplementation);
 };
 
 }  // namespace bin
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
index 8e0adc5..2698253 100644
--- a/runtime/bin/eventhandler_win.cc
+++ b/runtime/bin/eventhandler_win.cc
@@ -8,11 +8,11 @@
 #include "bin/eventhandler.h"
 #include "bin/eventhandler_win.h"
 
+#include <fcntl.h>  // NOLINT
+#include <io.h>  // NOLINT
+#include <mswsock.h>  // NOLINT
 #include <winsock2.h>  // NOLINT
 #include <ws2tcpip.h>  // NOLINT
-#include <mswsock.h>  // NOLINT
-#include <io.h>  // NOLINT
-#include <fcntl.h>  // NOLINT
 
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
@@ -140,10 +140,7 @@
                                             completion_port,
                                             reinterpret_cast<ULONG_PTR>(this),
                                             0);
-  if (completion_port_ == NULL) {
-    return false;
-  }
-  return true;
+  return (completion_port_ != NULL);
 }
 
 
@@ -307,7 +304,7 @@
                        buffer->GetBufferSize(),
                        NULL,
                        buffer->GetCleanOverlapped());
-    if (ok || GetLastError() == ERROR_IO_PENDING) {
+    if (ok || (GetLastError() == ERROR_IO_PENDING)) {
       // Completing asynchronously.
       pending_read_ = buffer;
       return true;
@@ -347,7 +344,7 @@
                       buffer->GetBufferSize(),
                       NULL,
                       buffer->GetCleanOverlapped());
-  if (ok || GetLastError() == ERROR_IO_PENDING) {
+  if (ok || (GetLastError() == ERROR_IO_PENDING)) {
     // Completing asynchronously.
     pending_write_ = buffer;
     return true;
@@ -394,7 +391,7 @@
 void FileHandle::EnsureInitialized(EventHandlerImplementation* event_handler) {
   MonitorLocker ml(monitor_);
   event_handler_ = event_handler;
-  if (SupportsOverlappedIO() && completion_port_ == INVALID_HANDLE_VALUE) {
+  if (SupportsOverlappedIO() && (completion_port_ == INVALID_HANDLE_VALUE)) {
     CreateCompletionPort(event_handler_->completion_port());
   }
 }
@@ -416,14 +413,16 @@
 
 
 bool DirectoryWatchHandle::IsClosed() {
-  return IsClosing() && pending_read_ == NULL;
+  return IsClosing() && (pending_read_ == NULL);
 }
 
 
 bool DirectoryWatchHandle::IssueRead() {
   // It may have been started before, as we start the directory-handler when
   // we create it.
-  if (pending_read_ != NULL || data_ready_ != NULL) return true;
+  if ((pending_read_ != NULL) || (data_ready_ != NULL)) {
+    return true;
+  }
   OverlappedBuffer* buffer = OverlappedBuffer::AllocateReadBuffer(kBufferSize);
   ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
   BOOL ok = ReadDirectoryChangesW(handle_,
@@ -434,7 +433,7 @@
                                   NULL,
                                   buffer->GetCleanOverlapped(),
                                   NULL);
-  if (ok || GetLastError() == ERROR_IO_PENDING) {
+  if (ok || (GetLastError() == ERROR_IO_PENDING)) {
     // Completing asynchronously.
     pending_read_ = buffer;
     return true;
@@ -481,10 +480,7 @@
                         &bytes,
                         NULL,
                         NULL);
-  if (status == SOCKET_ERROR) {
-    return false;
-  }
-  return true;
+  return (status != SOCKET_ERROR);
 }
 
 
@@ -603,7 +599,9 @@
   if (accepted_head_ != NULL) {
     result = accepted_head_;
     accepted_head_ = accepted_head_->next();
-    if (accepted_head_ == NULL) accepted_tail_ = NULL;
+    if (accepted_head_ == NULL) {
+      accepted_tail_ = NULL;
+    }
     result->set_next(NULL);
     accepted_count_--;
   }
@@ -641,7 +639,9 @@
 
 intptr_t Handle::Available() {
   MonitorLocker ml(monitor_);
-  if (data_ready_ == NULL) return 0;
+  if (data_ready_ == NULL) {
+    return 0;
+  }
   ASSERT(!data_ready_->IsEmpty());
   return data_ready_->GetRemainingLength();
 }
@@ -649,13 +649,17 @@
 
 intptr_t Handle::Read(void* buffer, intptr_t num_bytes) {
   MonitorLocker ml(monitor_);
-  if (data_ready_ == NULL) return 0;
+  if (data_ready_ == NULL) {
+    return 0;
+  }
   num_bytes = data_ready_->Read(
       buffer, Utils::Minimum<intptr_t>(num_bytes, INT_MAX));
   if (data_ready_->IsEmpty()) {
     OverlappedBuffer::DisposeBuffer(data_ready_);
     data_ready_ = NULL;
-    if (!IsClosing() && !IsClosedRead()) IssueRead();
+    if (!IsClosing() && !IsClosedRead()) {
+      IssueRead();
+    }
   }
   return num_bytes;
 }
@@ -664,7 +668,9 @@
 intptr_t Handle::RecvFrom(
     void* buffer, intptr_t num_bytes, struct sockaddr* sa, socklen_t sa_len) {
   MonitorLocker ml(monitor_);
-  if (data_ready_ == NULL) return 0;
+  if (data_ready_ == NULL) {
+    return 0;
+  }
   num_bytes = data_ready_->Read(
       buffer, Utils::Minimum<intptr_t>(num_bytes, INT_MAX));
   if (data_ready_->from()->sa_family == AF_INET) {
@@ -679,21 +685,31 @@
   // entirety to match how recvfrom works in a socket.
   OverlappedBuffer::DisposeBuffer(data_ready_);
   data_ready_ = NULL;
-  if (!IsClosing() && !IsClosedRead()) IssueRecvFrom();
+  if (!IsClosing() && !IsClosedRead()) {
+    IssueRecvFrom();
+  }
   return num_bytes;
 }
 
 
 intptr_t Handle::Write(const void* buffer, intptr_t num_bytes) {
   MonitorLocker ml(monitor_);
-  if (pending_write_ != NULL) return 0;
-  if (num_bytes > kBufferSize) num_bytes = kBufferSize;
+  if (pending_write_ != NULL) {
+    return 0;
+  }
+  if (num_bytes > kBufferSize) {
+    num_bytes = kBufferSize;
+  }
   ASSERT(SupportsOverlappedIO());
-  if (completion_port_ == INVALID_HANDLE_VALUE) return 0;
+  if (completion_port_ == INVALID_HANDLE_VALUE) {
+    return 0;
+  }
   int truncated_bytes = Utils::Minimum<intptr_t>(num_bytes, INT_MAX);
   pending_write_ = OverlappedBuffer::AllocateWriteBuffer(truncated_bytes);
   pending_write_->Write(buffer, truncated_bytes);
-  if (!IssueWrite()) return -1;
+  if (!IssueWrite()) {
+    return -1;
+  }
   return truncated_bytes;
 }
 
@@ -703,13 +719,21 @@
                         struct sockaddr* sa,
                         socklen_t sa_len) {
   MonitorLocker ml(monitor_);
-  if (pending_write_ != NULL) return 0;
-  if (num_bytes > kBufferSize) num_bytes = kBufferSize;
+  if (pending_write_ != NULL) {
+    return 0;
+  }
+  if (num_bytes > kBufferSize) {
+    num_bytes = kBufferSize;
+  }
   ASSERT(SupportsOverlappedIO());
-  if (completion_port_ == INVALID_HANDLE_VALUE) return 0;
+  if (completion_port_ == INVALID_HANDLE_VALUE) {
+    return 0;
+  }
   pending_write_ = OverlappedBuffer::AllocateSendToBuffer(num_bytes);
   pending_write_->Write(buffer, num_bytes);
-  if (!IssueSendTo(sa, sa_len)) return -1;
+  if (!IssueSendTo(sa, sa_len)) {
+    return -1;
+  }
   return num_bytes;
 }
 
@@ -765,15 +789,21 @@
 
 intptr_t StdHandle::Write(const void* buffer, intptr_t num_bytes) {
   MonitorLocker ml(monitor_);
-  if (pending_write_ != NULL) return 0;
-  if (num_bytes > kBufferSize) num_bytes = kBufferSize;
+  if (pending_write_ != NULL) {
+    return 0;
+  }
+  if (num_bytes > kBufferSize) {
+    num_bytes = kBufferSize;
+  }
   // In the case of stdout and stderr, OverlappedIO is not supported.
   // Here we'll instead use a thread, to make it async.
   // This code is actually never exposed to the user, as stdout and stderr is
   // not available as a RawSocket, but only wrapped in a Socket.
   // Note that we return '0', unless a thread have already completed a write.
   if (thread_wrote_ > 0) {
-    if (num_bytes > thread_wrote_) num_bytes = thread_wrote_;
+    if (num_bytes > thread_wrote_) {
+      num_bytes = thread_wrote_;
+    }
     thread_wrote_ -= num_bytes;
     return num_bytes;
   }
@@ -826,17 +856,18 @@
                         &bytes,
                         NULL,
                         NULL);
-  if (status == SOCKET_ERROR) {
-    return false;
-  }
-  return true;
+  return (status != SOCKET_ERROR);
 }
 
 
 void ClientSocket::Shutdown(int how) {
   int rc = shutdown(socket(), how);
-  if (how == SD_RECEIVE) MarkClosedRead();
-  if (how == SD_SEND) MarkClosedWrite();
+  if (how == SD_RECEIVE) {
+    MarkClosedRead();
+  }
+  if (how == SD_SEND) {
+    MarkClosedWrite();
+  }
   if (how == SD_BOTH) {
     MarkClosedRead();
     MarkClosedWrite();
@@ -870,7 +901,7 @@
                    &flags,
                    buffer->GetCleanOverlapped(),
                    NULL);
-  if (rc == NO_ERROR || WSAGetLastError() == WSA_IO_PENDING) {
+  if ((rc == NO_ERROR) || (WSAGetLastError() == WSA_IO_PENDING)) {
     pending_read_ = buffer;
     return true;
   }
@@ -894,7 +925,7 @@
                    0,
                    pending_write_->GetCleanOverlapped(),
                    NULL);
-  if (rc == NO_ERROR || WSAGetLastError() == WSA_IO_PENDING) {
+  if ((rc == NO_ERROR) || (WSAGetLastError() == WSA_IO_PENDING)) {
     return true;
   }
   OverlappedBuffer::DisposeBuffer(pending_write_);
@@ -910,7 +941,7 @@
     socket(), buffer->GetCleanOverlapped(), TF_REUSE_SOCKET, 0);
   // DisconnectEx works like other OverlappedIO APIs, where we can get either an
   // immediate success or delayed operation by WSA_IO_PENDING being set.
-  if (ok || WSAGetLastError() != WSA_IO_PENDING) {
+  if (ok || (WSAGetLastError() != WSA_IO_PENDING)) {
     DisconnectComplete(buffer);
   }
   NotifyAllDartPorts(1 << kDestroyedEvent);
@@ -975,7 +1006,7 @@
                      sa_len,
                      pending_write_->GetCleanOverlapped(),
                      NULL);
-  if (rc == NO_ERROR || WSAGetLastError() == WSA_IO_PENDING) {
+  if ((rc == NO_ERROR) || (WSAGetLastError() == WSA_IO_PENDING)) {
     return true;
   }
   OverlappedBuffer::DisposeBuffer(pending_write_);
@@ -1004,7 +1035,7 @@
                        buffer->from_len_addr(),
                        buffer->GetCleanOverlapped(),
                        NULL);
-  if (rc == NO_ERROR || WSAGetLastError() == WSA_IO_PENDING) {
+  if ((rc == NO_ERROR) || (WSAGetLastError() == WSA_IO_PENDING)) {
     pending_read_ = buffer;
     return true;
   }
@@ -1174,8 +1205,8 @@
   if (!listen_socket->IsClosing() && listen_socket->CanAccept()) {
     intptr_t event_mask = 1 << kInEvent;
     for (int i = 0;
-         i < listen_socket->accepted_count() &&
-         listen_socket->Mask() == event_mask;
+         (i < listen_socket->accepted_count()) &&
+         (listen_socket->Mask() == event_mask);
          i++) {
       Dart_Port port = listen_socket->NextNotifyDartPort(event_mask);
       DartUtils::PostInt32(port, event_mask);
@@ -1280,7 +1311,9 @@
 
 
 void EventHandlerImplementation::HandleTimeout() {
-  if (!timeout_queue_.HasTimeout()) return;
+  if (!timeout_queue_.HasTimeout()) {
+    return;
+  }
   DartUtils::PostNull(timeout_queue_.CurrentPort());
   timeout_queue_.RemoveCurrent();
 }
@@ -1389,7 +1422,9 @@
     OVERLAPPED* overlapped;
     int64_t millis = handler_impl->GetTimeout();
     ASSERT(millis == kInfinityTimeout || millis >= 0);
-    if (millis > kMaxInt32) millis = kMaxInt32;
+    if (millis > kMaxInt32) {
+      millis = kMaxInt32;
+    }
     ASSERT(sizeof(int32_t) == sizeof(DWORD));
     BOOL ok = GetQueuedCompletionStatus(handler_impl->completion_port(),
                                         &bytes,
@@ -1397,7 +1432,7 @@
                                         &overlapped,
                                         static_cast<DWORD>(millis));
 
-    if (!ok && overlapped == NULL) {
+    if (!ok && (overlapped == NULL)) {
       if (GetLastError() == ERROR_ABANDONED_WAIT_0) {
         // The completion port should never be closed.
         Log::Print("Completion port closed\n");
@@ -1413,10 +1448,10 @@
       // ERROR_NETNAME_DELETED occurs when the client closes
       // the socket it is reading from.
       DWORD last_error = GetLastError();
-      if (last_error == ERROR_CONNECTION_ABORTED ||
-          last_error == ERROR_OPERATION_ABORTED ||
-          last_error == ERROR_NETNAME_DELETED ||
-          last_error == ERROR_BROKEN_PIPE) {
+      if ((last_error == ERROR_CONNECTION_ABORTED) ||
+          (last_error == ERROR_OPERATION_ABORTED) ||
+          (last_error == ERROR_NETNAME_DELETED) ||
+          (last_error == ERROR_BROKEN_PIPE)) {
         ASSERT(bytes == 0);
         handler_impl->HandleIOCompletion(bytes, key, overlapped);
       } else if (last_error == ERROR_MORE_DATA) {
diff --git a/runtime/bin/eventhandler_win.h b/runtime/bin/eventhandler_win.h
index 38509dd..edb5c48 100644
--- a/runtime/bin/eventhandler_win.h
+++ b/runtime/bin/eventhandler_win.h
@@ -9,14 +9,13 @@
 #error Do not include eventhandler_win.h directly; use eventhandler.h instead.
 #endif
 
+#include <mswsock.h>
 #include <winsock2.h>
 #include <ws2tcpip.h>
-#include <mswsock.h>
 
 #include "bin/builtin.h"
 #include "bin/thread.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -28,7 +27,6 @@
 class ClientSocket;
 class ListenSocket;
 
-
 // An OverlappedBuffer encapsulates the OVERLAPPED structure and the
 // associated data buffer. For accept it also contains the pre-created
 // socket for the client.
@@ -149,6 +147,8 @@
   // object as the object is allocated larger than it's definition
   // indicate to extend this array.
   uint8_t buffer_data_[1];
+
+  DISALLOW_COPY_AND_ASSIGN(OverlappedBuffer);
 };
 
 
@@ -273,6 +273,8 @@
   void NotifyReadThreadFinished();
 
   int flags_;
+
+  DISALLOW_COPY_AND_ASSIGN(Handle);
 };
 
 
@@ -285,6 +287,9 @@
 
   virtual void EnsureInitialized(EventHandlerImplementation* event_handler);
   virtual bool IsClosed();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(FileHandle);
 };
 
 
@@ -310,6 +315,8 @@
   intptr_t thread_wrote_;
   bool write_thread_exists_;
   bool write_thread_running_;
+
+  DISALLOW_COPY_AND_ASSIGN(StdHandle);
 };
 
 
@@ -332,6 +339,8 @@
  private:
   int events_;
   bool recursive_;
+
+  DISALLOW_COPY_AND_ASSIGN(DirectoryWatchHandle);
 };
 
 
@@ -348,6 +357,8 @@
 
  private:
   const SOCKET socket_;
+
+  DISALLOW_COPY_AND_ASSIGN(SocketHandle);
 };
 
 
@@ -403,6 +414,8 @@
   // The number of accepted connections which are waiting to be removed from
   // this queue and processed by dart isolates.
   int accepted_count_;
+
+  DISALLOW_COPY_AND_ASSIGN(ListenSocket);
 };
 
 
@@ -460,6 +473,8 @@
   ClientSocket* next_;
   bool connected_;
   bool closed_;
+
+  DISALLOW_COPY_AND_ASSIGN(ClientSocket);
 };
 
 
@@ -482,8 +497,12 @@
   virtual void EnsureInitialized(EventHandlerImplementation* event_handler);
   virtual void DoClose();
   virtual bool IsClosed();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DatagramSocket);
 };
 
+
 // Event handler.
 class EventHandlerImplementation {
  public:
@@ -523,6 +542,8 @@
   TimeoutQueue timeout_queue_;  // Time for next timeout.
   bool shutdown_;
   HANDLE completion_port_;
+
+  DISALLOW_COPY_AND_ASSIGN(EventHandlerImplementation);
 };
 
 }  // namespace bin
diff --git a/runtime/bin/extensions.cc b/runtime/bin/extensions.cc
index eaed7bb..7fa06fd 100644
--- a/runtime/bin/extensions.cc
+++ b/runtime/bin/extensions.cc
@@ -6,12 +6,11 @@
 
 #include <stdio.h>
 
+#include "bin/dartutils.h"
+#include "bin/file.h"
 #include "include/dart_api.h"
 #include "platform/assert.h"
 #include "platform/globals.h"
-#include "bin/dartutils.h"
-#include "bin/file.h"
-
 
 namespace dart {
 namespace bin {
@@ -25,17 +24,15 @@
     return Dart_NewApiError("Cannot load native extensions over http:");
   }
   const char* library_strings[] = { extension_directory, extension_file, NULL };
-  char* library_file = Concatenate(library_strings);
+  const char* library_file = Concatenate(library_strings);
   void* library_handle = LoadExtensionLibrary(library_file);
-  free(library_file);
   if (library_handle == NULL) {
     return GetError();
   }
 
   const char* strings[] = { extension_name, "_Init", NULL };
-  char* init_function_name = Concatenate(strings);
+  const char* init_function_name = Concatenate(strings);
   void* init_function = ResolveSymbol(library_handle, init_function_name);
-  free(init_function_name);
   Dart_Handle result = GetError();
   if (Dart_IsError(result)) {
     return result;
@@ -48,13 +45,13 @@
 
 
 // Concatenates a NULL terminated array of strings.
-// The returned string must be freed.
-char* Extensions::Concatenate(const char** strings) {
+// The returned string is scope allocated.
+const char* Extensions::Concatenate(const char** strings) {
   int size = 1;  // null termination.
   for (int i = 0; strings[i] != NULL; i++) {
     size += strlen(strings[i]);
   }
-  char* result = reinterpret_cast<char*>(malloc(size));
+  char* result = reinterpret_cast<char*>(Dart_ScopeAllocate(size));
   int index = 0;
   for (int i = 0; strings[i] != NULL; i++) {
     index += snprintf(result + index, size - index, "%s", strings[i]);
diff --git a/runtime/bin/extensions.h b/runtime/bin/extensions.h
index 8c172b8..da18615 100644
--- a/runtime/bin/extensions.h
+++ b/runtime/bin/extensions.h
@@ -8,7 +8,6 @@
 #include "include/dart_api.h"
 #include "platform/globals.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -28,8 +27,8 @@
  private:
   static Dart_Handle GetError();
 
-  // The returned string must be freed.
-  static char* Concatenate(const char** strings);
+  // The returned string is scope allocated.
+  static const char* Concatenate(const char** strings);
 
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(Extensions);
diff --git a/runtime/bin/extensions_android.cc b/runtime/bin/extensions_android.cc
index e33c195..c34902c 100644
--- a/runtime/bin/extensions_android.cc
+++ b/runtime/bin/extensions_android.cc
@@ -8,7 +8,6 @@
 #include "bin/extensions.h"
 #include <dlfcn.h>  // NOLINT
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/extensions_linux.cc b/runtime/bin/extensions_linux.cc
index 54a88a4..8a25cba 100644
--- a/runtime/bin/extensions_linux.cc
+++ b/runtime/bin/extensions_linux.cc
@@ -8,7 +8,6 @@
 #include "bin/extensions.h"
 #include <dlfcn.h>  // NOLINT
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/extensions_macos.cc b/runtime/bin/extensions_macos.cc
index 0edb6b5..9910f10 100644
--- a/runtime/bin/extensions_macos.cc
+++ b/runtime/bin/extensions_macos.cc
@@ -8,7 +8,6 @@
 #include "bin/extensions.h"
 #include <dlfcn.h>  // NOLINT
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/extensions_win.cc b/runtime/bin/extensions_win.cc
index 224bcdf..493acad 100644
--- a/runtime/bin/extensions_win.cc
+++ b/runtime/bin/extensions_win.cc
@@ -9,7 +9,6 @@
 #include "bin/utils.h"
 #include "bin/utils_win.h"
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/fdutils.h b/runtime/bin/fdutils.h
index da4fcf5..93bebfb 100644
--- a/runtime/bin/fdutils.h
+++ b/runtime/bin/fdutils.h
@@ -8,7 +8,6 @@
 #include "bin/builtin.h"
 #include "platform/globals.h"
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/fdutils_android.cc b/runtime/bin/fdutils_android.cc
index 83e4913..3c22a04 100644
--- a/runtime/bin/fdutils_android.cc
+++ b/runtime/bin/fdutils_android.cc
@@ -5,15 +5,15 @@
 #include "platform/globals.h"
 #if defined(TARGET_OS_ANDROID)
 
+#include "bin/fdutils.h"
+
 #include <errno.h>  // NOLINT
 #include <fcntl.h>  // NOLINT
-#include <unistd.h>  // NOLINT
 #include <sys/ioctl.h>  // NOLINT
+#include <unistd.h>  // NOLINT
 
-#include "bin/fdutils.h"
 #include "platform/signal_blocker.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -72,9 +72,7 @@
   if (result < 0) {
     return result;
   }
-#ifdef DEBUG
   ASSERT(available >= 0);
-#endif
   return static_cast<intptr_t>(available);
 }
 
@@ -98,7 +96,7 @@
       ASSERT(errno != EWOULDBLOCK);
       return -1;
     } else {
-      ASSERT((bytes_read > 0));
+      ASSERT(bytes_read > 0);
       remaining -= bytes_read;
       buffer_pos += bytes_read;
     }
diff --git a/runtime/bin/fdutils_linux.cc b/runtime/bin/fdutils_linux.cc
index e8984dd..f80356e 100644
--- a/runtime/bin/fdutils_linux.cc
+++ b/runtime/bin/fdutils_linux.cc
@@ -5,15 +5,15 @@
 #include "platform/globals.h"
 #if defined(TARGET_OS_LINUX)
 
+#include "bin/fdutils.h"
+
 #include <errno.h>  // NOLINT
 #include <fcntl.h>  // NOLINT
-#include <unistd.h>  // NOLINT
 #include <sys/ioctl.h>  // NOLINT
+#include <unistd.h>  // NOLINT
 
-#include "bin/fdutils.h"
 #include "platform/signal_blocker.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -72,9 +72,7 @@
   if (result < 0) {
     return result;
   }
-#ifdef DEBUG
   ASSERT(available >= 0);
-#endif
   return static_cast<intptr_t>(available);
 }
 
@@ -98,7 +96,7 @@
       ASSERT(errno != EWOULDBLOCK);
       return -1;
     } else {
-      ASSERT((bytes_read > 0));
+      ASSERT(bytes_read > 0);
       remaining -= bytes_read;
       buffer_pos += bytes_read;
     }
diff --git a/runtime/bin/fdutils_macos.cc b/runtime/bin/fdutils_macos.cc
index 2ecf600..41f1d24 100644
--- a/runtime/bin/fdutils_macos.cc
+++ b/runtime/bin/fdutils_macos.cc
@@ -5,15 +5,14 @@
 #include "platform/globals.h"
 #if defined(TARGET_OS_MACOS)
 
-#include <errno.h>  // NOLINT
-#include <fcntl.h>  // NOLINT
-#include <unistd.h>  // NOLINT
-#include <sys/ioctl.h>  // NOLINT
-
 #include "bin/fdutils.h"
 
-#include "platform/signal_blocker.h"
+#include <errno.h>  // NOLINT
+#include <fcntl.h>  // NOLINT
+#include <sys/ioctl.h>  // NOLINT
+#include <unistd.h>  // NOLINT
 
+#include "platform/signal_blocker.h"
 
 namespace dart {
 namespace bin {
@@ -73,9 +72,7 @@
   if (result < 0) {
     return result;
   }
-#ifdef DEBUG
   ASSERT(available >= 0);
-#endif
   return static_cast<intptr_t>(available);
 }
 
@@ -99,7 +96,7 @@
       ASSERT(errno != EWOULDBLOCK);
       return -1;
     } else {
-      ASSERT((bytes_read > 0));
+      ASSERT(bytes_read > 0);
       remaining -= bytes_read;
       buffer_pos += bytes_read;
     }
diff --git a/runtime/bin/file.cc b/runtime/bin/file.cc
index 7cc3e71..7d9ea28 100644
--- a/runtime/bin/file.cc
+++ b/runtime/bin/file.cc
@@ -565,7 +565,9 @@
 
 void FUNCTION_NAME(File_OpenStdio)(Dart_NativeArguments args) {
   int64_t fd = DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
-  ASSERT(fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO);
+  ASSERT((fd == STDIN_FILENO) ||
+         (fd == STDOUT_FILENO) ||
+         (fd == STDERR_FILENO));
   File* file = File::OpenStdio(static_cast<int>(fd));
   Dart_SetReturnValue(args, Dart_NewInteger(reinterpret_cast<intptr_t>(file)));
 }
@@ -573,7 +575,9 @@
 
 void FUNCTION_NAME(File_GetStdioHandleType)(Dart_NativeArguments args) {
   int64_t fd = DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
-  ASSERT(fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO);
+  ASSERT((fd == STDIN_FILENO) ||
+         (fd == STDOUT_FILENO) ||
+         (fd == STDERR_FILENO));
   File::StdioHandleType type = File::GetStdioHandleType(static_cast<int>(fd));
   Dart_SetReturnValue(args, Dart_NewInteger(type));
 }
diff --git a/runtime/bin/file.h b/runtime/bin/file.h
index 315ebbe..3c8255f 100644
--- a/runtime/bin/file.h
+++ b/runtime/bin/file.h
@@ -5,9 +5,9 @@
 #ifndef BIN_FILE_H_
 #define BIN_FILE_H_
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <stdio.h>
 #include <sys/types.h>
 
 #include "bin/builtin.h"
diff --git a/runtime/bin/file_android.cc b/runtime/bin/file_android.cc
index c672914..a115715 100644
--- a/runtime/bin/file_android.cc
+++ b/runtime/bin/file_android.cc
@@ -9,11 +9,11 @@
 
 #include <errno.h>  // NOLINT
 #include <fcntl.h>  // NOLINT
+#include <libgen.h>  // NOLINT
+#include <sys/sendfile.h>  // NOLINT
 #include <sys/stat.h>  // NOLINT
 #include <sys/types.h>  // NOLINT
-#include <sys/sendfile.h>  // NOLINT
 #include <unistd.h>  // NOLINT
-#include <libgen.h>  // NOLINT
 
 #include "bin/builtin.h"
 #include "bin/log.h"
@@ -21,7 +21,6 @@
 #include "platform/signal_blocker.h"
 #include "platform/utils.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -114,7 +113,7 @@
 
 bool File::Lock(File::LockType lock, int64_t start, int64_t end) {
   ASSERT(handle_->fd() >= 0);
-  ASSERT(end == -1 || end > start);
+  ASSERT((end == -1) || (end > start));
   struct flock fl;
   switch (lock) {
     case File::kLockUnlock:
@@ -399,7 +398,7 @@
 
 
 bool File::IsAbsolutePath(const char* pathname) {
-  return (pathname != NULL && pathname[0] == '/');
+  return ((pathname != NULL) && (pathname[0] == '/'));
 }
 
 
diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc
index 495dacd..3099715 100644
--- a/runtime/bin/file_linux.cc
+++ b/runtime/bin/file_linux.cc
@@ -9,11 +9,11 @@
 
 #include <errno.h>  // NOLINT
 #include <fcntl.h>  // NOLINT
+#include <libgen.h>  // NOLINT
+#include <sys/sendfile.h>  // NOLINT
 #include <sys/stat.h>  // NOLINT
 #include <sys/types.h>  // NOLINT
-#include <sys/sendfile.h>  // NOLINT
 #include <unistd.h>  // NOLINT
-#include <libgen.h>  // NOLINT
 
 #include "bin/builtin.h"
 #include "bin/log.h"
diff --git a/runtime/bin/file_macos.cc b/runtime/bin/file_macos.cc
index 1211fad..81412f6 100644
--- a/runtime/bin/file_macos.cc
+++ b/runtime/bin/file_macos.cc
@@ -7,13 +7,13 @@
 
 #include "bin/file.h"
 
+#include <copyfile.h>  // NOLINT
 #include <errno.h>  // NOLINT
 #include <fcntl.h>  // NOLINT
-#include <copyfile.h>  // NOLINT
-#include <sys/stat.h>  // NOLINT
-#include <unistd.h>  // NOLINT
 #include <libgen.h>  // NOLINT
 #include <limits.h>  // NOLINT
+#include <sys/stat.h>  // NOLINT
+#include <unistd.h>  // NOLINT
 
 #include "bin/builtin.h"
 #include "bin/fdutils.h"
diff --git a/runtime/bin/file_system_watcher.h b/runtime/bin/file_system_watcher.h
index 6a6164a..7e142d8 100644
--- a/runtime/bin/file_system_watcher.h
+++ b/runtime/bin/file_system_watcher.h
@@ -5,15 +5,14 @@
 #ifndef BIN_FILE_SYSTEM_WATCHER_H_
 #define BIN_FILE_SYSTEM_WATCHER_H_
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <stdio.h>
 #include <sys/types.h>
 
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/file_system_watcher_android.cc b/runtime/bin/file_system_watcher_android.cc
index ac2ad5f..ccf54da 100644
--- a/runtime/bin/file_system_watcher_android.cc
+++ b/runtime/bin/file_system_watcher_android.cc
@@ -11,10 +11,8 @@
 #include <sys/inotify.h>  // NOLINT
 
 #include "bin/fdutils.h"
-
 #include "platform/signal_blocker.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -46,10 +44,18 @@
                                       int events,
                                       bool recursive) {
   int list_events = IN_DELETE_SELF | IN_MOVE_SELF;
-  if (events & kCreate) list_events |= IN_CREATE;
-  if (events & kModifyContent) list_events |= IN_CLOSE_WRITE | IN_ATTRIB;
-  if (events & kDelete) list_events |= IN_DELETE;
-  if (events & kMove) list_events |= IN_MOVE;
+  if ((events & kCreate) != 0) {
+    list_events |= IN_CREATE;
+  }
+  if ((events & kModifyContent) != 0) {
+    list_events |= IN_CLOSE_WRITE | IN_ATTRIB;
+  }
+  if ((events & kDelete) != 0) {
+    list_events |= IN_DELETE;
+  }
+  if ((events & kMove) != 0) {
+    list_events |= IN_MOVE;
+  }
   int path_id = NO_RETRY_EXPECTED(inotify_add_watch(id, path, list_events));
   if (path_id < 0) {
     return -1;
@@ -69,6 +75,33 @@
 }
 
 
+static int InotifyEventToMask(struct inotify_event* e) {
+  int mask = 0;
+  if ((e->mask & IN_CLOSE_WRITE) != 0) {
+    mask |= FileSystemWatcher::kModifyContent;
+  }
+  if ((e->mask & IN_ATTRIB) != 0) {
+    mask |= FileSystemWatcher::kModefyAttribute;
+  }
+  if ((e->mask & IN_CREATE) != 0) {
+    mask |= FileSystemWatcher::kCreate;
+  }
+  if ((e->mask & IN_MOVE) != 0) {
+    mask |= FileSystemWatcher::kMove;
+  }
+  if ((e->mask & IN_DELETE) != 0) {
+    mask |= FileSystemWatcher::kDelete;
+  }
+  if ((e->mask & (IN_DELETE_SELF | IN_MOVE_SELF)) != 0) {
+    mask |= FileSystemWatcher::kDeleteSelf;
+  }
+  if ((e->mask & IN_ISDIR) != 0) {
+    mask |= FileSystemWatcher::kIsDir;
+  }
+  return mask;
+}
+
+
 Dart_Handle FileSystemWatcher::ReadEvents(intptr_t id, intptr_t path_id) {
   USE(path_id);
   const intptr_t kEventSize = sizeof(struct inotify_event);
@@ -87,14 +120,7 @@
         reinterpret_cast<struct inotify_event*>(buffer + offset);
     if ((e->mask & IN_IGNORED) == 0) {;
       Dart_Handle event = Dart_NewList(5);
-      int mask = 0;
-      if (e->mask & IN_CLOSE_WRITE) mask |= kModifyContent;
-      if (e->mask & IN_ATTRIB) mask |= kModefyAttribute;
-      if (e->mask & IN_CREATE) mask |= kCreate;
-      if (e->mask & IN_MOVE) mask |= kMove;
-      if (e->mask & IN_DELETE) mask |= kDelete;
-      if (e->mask & (IN_DELETE_SELF | IN_MOVE_SELF)) mask |= kDeleteSelf;
-      if (e->mask & IN_ISDIR) mask |= kIsDir;
+      int mask = InotifyEventToMask(e);
       Dart_ListSetAt(event, 0, Dart_NewInteger(mask));
       Dart_ListSetAt(event, 1, Dart_NewInteger(e->cookie));
       if (e->len > 0) {
diff --git a/runtime/bin/file_system_watcher_linux.cc b/runtime/bin/file_system_watcher_linux.cc
index 48c7323..e692f0d 100644
--- a/runtime/bin/file_system_watcher_linux.cc
+++ b/runtime/bin/file_system_watcher_linux.cc
@@ -12,10 +12,8 @@
 
 #include "bin/fdutils.h"
 #include "bin/socket.h"
-
 #include "platform/signal_blocker.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -26,7 +24,9 @@
 
 intptr_t FileSystemWatcher::Init() {
   int id = NO_RETRY_EXPECTED(inotify_init1(IN_CLOEXEC));
-  if (id < 0) return -1;
+  if (id < 0) {
+    return -1;
+  }
   // Some systems dosn't support setting this as non-blocking. Since watching
   // internals are kept away from the user, we know it's possible to continue,
   // even if setting non-blocking fails.
@@ -45,10 +45,18 @@
                                       int events,
                                       bool recursive) {
   int list_events = IN_DELETE_SELF | IN_MOVE_SELF;
-  if (events & kCreate) list_events |= IN_CREATE;
-  if (events & kModifyContent) list_events |= IN_CLOSE_WRITE | IN_ATTRIB;
-  if (events & kDelete) list_events |= IN_DELETE;
-  if (events & kMove) list_events |= IN_MOVE;
+  if ((events & kCreate) != 0) {
+    list_events |= IN_CREATE;
+  }
+  if ((events & kModifyContent) != 0) {
+    list_events |= IN_CLOSE_WRITE | IN_ATTRIB;
+  }
+  if ((events & kDelete) != 0) {
+    list_events |= IN_DELETE;
+  }
+  if ((events & kMove) != 0) {
+    list_events |= IN_MOVE;
+  }
   int path_id = NO_RETRY_EXPECTED(inotify_add_watch(id, path, list_events));
   if (path_id < 0) {
     return -1;
@@ -68,6 +76,33 @@
 }
 
 
+static int InotifyEventToMask(struct inotify_event* e) {
+  int mask = 0;
+  if ((e->mask & IN_CLOSE_WRITE) != 0) {
+    mask |= FileSystemWatcher::kModifyContent;
+  }
+  if ((e->mask & IN_ATTRIB) != 0) {
+    mask |= FileSystemWatcher::kModefyAttribute;
+  }
+  if ((e->mask & IN_CREATE) != 0) {
+    mask |= FileSystemWatcher::kCreate;
+  }
+  if ((e->mask & IN_MOVE) != 0) {
+    mask |= FileSystemWatcher::kMove;
+  }
+  if ((e->mask & IN_DELETE) != 0) {
+    mask |= FileSystemWatcher::kDelete;
+  }
+  if ((e->mask & (IN_DELETE_SELF | IN_MOVE_SELF)) != 0) {
+    mask |= FileSystemWatcher::kDeleteSelf;
+  }
+  if ((e->mask & IN_ISDIR) != 0) {
+    mask |= FileSystemWatcher::kIsDir;
+  }
+  return mask;
+}
+
+
 Dart_Handle FileSystemWatcher::ReadEvents(intptr_t id, intptr_t path_id) {
   USE(path_id);
   const intptr_t kEventSize = sizeof(struct inotify_event);
@@ -86,14 +121,7 @@
         reinterpret_cast<struct inotify_event*>(buffer + offset);
     if ((e->mask & IN_IGNORED) == 0) {;
       Dart_Handle event = Dart_NewList(5);
-      int mask = 0;
-      if (e->mask & IN_CLOSE_WRITE) mask |= kModifyContent;
-      if (e->mask & IN_ATTRIB) mask |= kModefyAttribute;
-      if (e->mask & IN_CREATE) mask |= kCreate;
-      if (e->mask & IN_MOVE) mask |= kMove;
-      if (e->mask & IN_DELETE) mask |= kDelete;
-      if (e->mask & (IN_DELETE_SELF | IN_MOVE_SELF)) mask |= kDeleteSelf;
-      if (e->mask & IN_ISDIR) mask |= kIsDir;
+      int mask = InotifyEventToMask(e);
       Dart_ListSetAt(event, 0, Dart_NewInteger(mask));
       Dart_ListSetAt(event, 1, Dart_NewInteger(e->cookie));
       if (e->len > 0) {
diff --git a/runtime/bin/file_system_watcher_macos.cc b/runtime/bin/file_system_watcher_macos.cc
index 5c0d430..ff64288 100644
--- a/runtime/bin/file_system_watcher_macos.cc
+++ b/runtime/bin/file_system_watcher_macos.cc
@@ -19,10 +19,8 @@
 #include "bin/file.h"
 #include "bin/socket.h"
 #include "bin/thread.h"
-
 #include "platform/signal_blocker.h"
 
-
 #ifndef MAC_OS_X_VERSION_10_7
 enum {
   kFSEventStreamCreateFlagFileEvents = 0x00000010
@@ -42,7 +40,6 @@
 };
 #endif
 
-
 namespace dart {
 namespace bin {
 
@@ -55,6 +52,7 @@
   uint8_t bytes[PATH_MAX + 8];
 };
 
+
 class FSEventsWatcher {
  public:
   class Node {
@@ -180,6 +178,8 @@
     int write_fd_;
     bool recursive_;
     FSEventStreamRef ref_;
+
+    DISALLOW_COPY_AND_ASSIGN(Node);
   };
 
 
@@ -287,15 +287,21 @@
                            Thread::GetCurrentThreadId()));
     // `ready` is set on same thread as this callback is invoked, so we don't
     // need to lock here.
-    if (!node->ready()) return;
+    if (!node->ready()) {
+      return;
+    }
     for (size_t i = 0; i < num_events; i++) {
       char *path = reinterpret_cast<char**>(event_paths)[i];
       FSEvent event;
       event.data.exists = File::GetType(path, false) != File::kDoesNotExist;
       path += node->base_path_length();
       // If path is longer the base, skip next character ('/').
-      if (path[0] != '\0') path += 1;
-      if (!node->recursive() && strstr(path, "/") != NULL) continue;
+      if (path[0] != '\0') {
+        path += 1;
+      }
+      if (!node->recursive() && (strstr(path, "/") != NULL)) {
+        continue;
+      }
       event.data.flags = event_flags[i];
       memmove(event.data.path, path, strlen(path) + 1);
       write(node->write_fd(), event.bytes, sizeof(event));
@@ -305,6 +311,8 @@
   Monitor monitor_;
   CFRunLoopRef run_loop_;
   ThreadId threadId_;
+
+  DISALLOW_COPY_AND_ASSIGN(FSEventsWatcher);
 };
 
 
@@ -348,7 +356,9 @@
   intptr_t fd = GetSocketId(id, path_id);
   intptr_t avail = FDUtils::AvailableBytes(fd);
   int count = avail / sizeof(FSEvent);
-  if (count <= 0) return Dart_NewList(0);
+  if (count <= 0) {
+    return Dart_NewList(0);
+  }
   Dart_Handle events = Dart_NewList(count);
   FSEvent e;
   for (int i = 0; i < count; i++) {
@@ -360,7 +370,7 @@
     Dart_Handle event = Dart_NewList(5);
     int flags = e.data.flags;
     int mask = 0;
-    if (flags & kFSEventStreamEventFlagItemRenamed) {
+    if ((flags & kFSEventStreamEventFlagItemRenamed) != 0) {
       if (path_len == 0) {
         // The moved path is the path being watched.
         mask |= kDeleteSelf;
@@ -368,11 +378,19 @@
         mask |= e.data.exists ? kCreate : kDelete;
       }
     }
-    if (flags & kFSEventStreamEventFlagItemModified) mask |= kModifyContent;
-    if (flags & kFSEventStreamEventFlagItemXattrMod) mask |= kModefyAttribute;
-    if (flags & kFSEventStreamEventFlagItemCreated) mask |= kCreate;
-    if (flags & kFSEventStreamEventFlagItemIsDir) mask |= kIsDir;
-    if (flags & kFSEventStreamEventFlagItemRemoved) {
+    if ((flags & kFSEventStreamEventFlagItemModified) != 0) {
+      mask |= kModifyContent;
+    }
+    if ((flags & kFSEventStreamEventFlagItemXattrMod) != 0) {
+      mask |= kModefyAttribute;
+    }
+    if ((flags & kFSEventStreamEventFlagItemCreated) != 0) {
+      mask |= kCreate;
+    }
+    if ((flags & kFSEventStreamEventFlagItemIsDir) != 0) {
+      mask |= kIsDir;
+    }
+    if ((flags & kFSEventStreamEventFlagItemRemoved) != 0) {
       if (path_len == 0) {
         // The removed path is the path being watched.
         mask |= kDeleteSelf;
@@ -404,24 +422,30 @@
   return DartUtils::NewDartOSError();
 }
 
+
 intptr_t FileSystemWatcher::GetSocketId(intptr_t id, intptr_t path_id) {
   return -1;
 }
 
+
 bool FileSystemWatcher::IsSupported() {
   return false;
 }
 
+
 void FileSystemWatcher::UnwatchPath(intptr_t id, intptr_t path_id) {
 }
 
+
 intptr_t FileSystemWatcher::Init() {
   return -1;
 }
 
+
 void FileSystemWatcher::Close(intptr_t id) {
 }
 
+
 intptr_t FileSystemWatcher::WatchPath(intptr_t id,
                                       const char* path,
                                       int events,
@@ -433,5 +457,4 @@
 }  // namespace dart
 
 #endif  // !TARGET_OS_IOS
-
 #endif  // defined(TARGET_OS_MACOS)
diff --git a/runtime/bin/file_system_watcher_win.cc b/runtime/bin/file_system_watcher_win.cc
index a772c6d..e6b091a 100644
--- a/runtime/bin/file_system_watcher_win.cc
+++ b/runtime/bin/file_system_watcher_win.cc
@@ -6,16 +6,15 @@
 #if defined(TARGET_OS_WINDOWS)
 
 #include "bin/file_system_watcher.h"
-#include "bin/eventhandler.h"
 
 #include <WinIoCtl.h>  // NOLINT
 
 #include "bin/builtin.h"
+#include "bin/eventhandler.h"
 #include "bin/log.h"
 #include "bin/utils.h"
 #include "bin/utils_win.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -55,11 +54,13 @@
   }
 
   int list_events = 0;
-  if (events & (kCreate | kMove | kDelete)) {
+  if ((events & (kCreate | kMove | kDelete)) != 0) {
     list_events |= FILE_NOTIFY_CHANGE_FILE_NAME |
                    FILE_NOTIFY_CHANGE_DIR_NAME;
   }
-  if (events & kModifyContent) list_events |= FILE_NOTIFY_CHANGE_LAST_WRITE;
+  if ((events & kModifyContent) != 0) {
+    list_events |= FILE_NOTIFY_CHANGE_LAST_WRITE;
+  }
 
   DirectoryWatchHandle* handle =
       new DirectoryWatchHandle(dir, list_events, recursive);
@@ -102,11 +103,21 @@
 
     Dart_Handle event = Dart_NewList(5);
     int mask = 0;
-    if (e->Action == FILE_ACTION_ADDED) mask |= kCreate;
-    if (e->Action == FILE_ACTION_REMOVED) mask |= kDelete;
-    if (e->Action == FILE_ACTION_MODIFIED) mask |= kModifyContent;
-    if (e->Action == FILE_ACTION_RENAMED_OLD_NAME) mask |= kMove;
-    if (e->Action == FILE_ACTION_RENAMED_NEW_NAME) mask |= kMove;
+    if (e->Action == FILE_ACTION_ADDED) {
+      mask |= kCreate;
+    }
+    if (e->Action == FILE_ACTION_REMOVED) {
+      mask |= kDelete;
+    }
+    if (e->Action == FILE_ACTION_MODIFIED) {
+      mask |= kModifyContent;
+    }
+    if (e->Action == FILE_ACTION_RENAMED_OLD_NAME) {
+      mask |= kMove;
+    }
+    if (e->Action == FILE_ACTION_RENAMED_NEW_NAME) {
+      mask |= kMove;
+    }
     Dart_ListSetAt(event, 0, Dart_NewInteger(mask));
     // Move events come in pairs. Just 'enable' by default.
     Dart_ListSetAt(event, 1, Dart_NewInteger(1));
@@ -116,7 +127,9 @@
     Dart_ListSetAt(event, 4, Dart_NewInteger(path_id));
     Dart_ListSetAt(events, i, event);
     i++;
-    if (e->NextEntryOffset == 0) break;
+    if (e->NextEntryOffset == 0) {
+      break;
+    }
     offset += e->NextEntryOffset;
   }
   return events;
diff --git a/runtime/bin/file_test.cc b/runtime/bin/file_test.cc
index 7cc9af3..518e6e5 100644
--- a/runtime/bin/file_test.cc
+++ b/runtime/bin/file_test.cc
@@ -7,7 +7,6 @@
 #include "platform/globals.h"
 #include "vm/unit_test.h"
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 7c1268f..054370a 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -20,7 +20,6 @@
 #include "bin/utils_win.h"
 #include "platform/utils.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -110,7 +109,7 @@
 
 bool File::Lock(File::LockType lock, int64_t start, int64_t end) {
   ASSERT(handle_->fd() >= 0);
-  ASSERT(end == -1 || end > start);
+  ASSERT((end == -1) || (end > start));
   HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(handle_->fd()));
   OVERLAPPED overlapped;
   ZeroMemory(&overlapped, sizeof(OVERLAPPED));
@@ -125,7 +124,6 @@
   int32_t length_low = Utils::Low32Bits(length);
   int32_t length_high = Utils::High32Bits(length);
 
-
   BOOL rc;
   switch (lock) {
     case File::kLockUnlock:
@@ -549,9 +547,9 @@
   if (pathname == NULL) {
     return false;
   }
-  return (strlen(pathname) > 2) &&
+  return ((strlen(pathname) > 2) &&
       (pathname[1] == ':') &&
-      (pathname[2] == '\\' || pathname[2] == '/');
+      ((pathname[2] == '\\') || (pathname[2] == '/')));
 }
 
 
diff --git a/runtime/bin/filter.h b/runtime/bin/filter.h
index 85592ab..889326f 100644
--- a/runtime/bin/filter.h
+++ b/runtime/bin/filter.h
@@ -10,7 +10,6 @@
 
 #include "zlib/zlib.h"
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/filter_unsupported.cc b/runtime/bin/filter_unsupported.cc
index f01b3db..442b9e6 100644
--- a/runtime/bin/filter_unsupported.cc
+++ b/runtime/bin/filter_unsupported.cc
@@ -7,7 +7,6 @@
 
 #include "include/dart_api.h"
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 20cc410..258b9a7 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -5,14 +5,12 @@
 // Generate a snapshot file after loading all the scripts specified on the
 // command line.
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <stdio.h>
 
 #include <cstdarg>
 
-#include "include/dart_api.h"
-
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
 #include "bin/eventhandler.h"
@@ -22,8 +20,9 @@
 #include "bin/utils.h"
 #include "bin/vmservice_impl.h"
 
-#include "platform/globals.h"
+#include "include/dart_api.h"
 
+#include "platform/globals.h"
 
 namespace dart {
 namespace bin {
@@ -181,16 +180,16 @@
     return -1;
   }
 
-  if (instructions_snapshot_filename != NULL &&
-      embedder_entry_points_manifest == NULL) {
+  if ((instructions_snapshot_filename != NULL) &&
+      (embedder_entry_points_manifest == NULL)) {
     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) {
+  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");
@@ -828,7 +827,7 @@
 static Dart_QualifiedFunctionName* ParseEntryPointsManifestIfPresent() {
   Dart_QualifiedFunctionName* entries =
       ParseEntryPointsManifestFile(embedder_entry_points_manifest);
-  if (entries == NULL && IsSnapshottingForPrecompilation()) {
+  if ((entries == NULL) && IsSnapshottingForPrecompilation()) {
     Log::PrintErr(
         "Could not find native embedder entry points during precompilation\n");
     exit(255);
@@ -1042,6 +1041,7 @@
       NULL,
       NULL,
       NULL,
+      NULL,
       DartUtils::OpenFile,
       DartUtils::ReadFile,
       DartUtils::WriteFile,
diff --git a/runtime/bin/io_buffer.cc b/runtime/bin/io_buffer.cc
index c69d9c7..2317afa 100644
--- a/runtime/bin/io_buffer.cc
+++ b/runtime/bin/io_buffer.cc
@@ -4,7 +4,6 @@
 
 #include "bin/io_buffer.h"
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/io_buffer.h b/runtime/bin/io_buffer.h
index 386402d..fe38932 100644
--- a/runtime/bin/io_buffer.h
+++ b/runtime/bin/io_buffer.h
@@ -5,10 +5,8 @@
 #ifndef BIN_IO_BUFFER_H_
 #define BIN_IO_BUFFER_H_
 
-#include "platform/globals.h"
-
 #include "include/dart_api.h"
-
+#include "platform/globals.h"
 
 namespace dart {
 namespace bin {
diff --git a/runtime/bin/io_impl_sources.gypi b/runtime/bin/io_impl_sources.gypi
index 03d20d4..9f1fe1b 100644
--- a/runtime/bin/io_impl_sources.gypi
+++ b/runtime/bin/io_impl_sources.gypi
@@ -43,8 +43,11 @@
     'process_macos.cc',
     'process_win.cc',
     '../../third_party/root_certificates/root_certificates.cc',
-    'secure_socket.cc',
     'secure_socket.h',
+    'secure_socket_boringssl.cc',
+    'secure_socket_boringssl.h',
+    'secure_socket_macos.cc',
+    'secure_socket_macos.h',
     'secure_socket_unsupported.cc',
     'socket.cc',
     'socket.h',
@@ -72,13 +75,25 @@
             'io_service_no_ssl.h',
             'secure_socket_unsupported.cc',
           ],
+          'conditions': [
+            ['OS=="mac"', {
+              # On Mac, we use the system keystore, so do not compile in the
+              # root certs.
+              'sources!': [
+                '../../third_party/root_certificates/root_certificates.cc',
+              ],
+            }],
+          ],
         }, {  # else dart_io_secure_socket == 0
           'sources!' : [
             '../../third_party/root_certificates/root_certificates.cc',
             'io_service.cc',
             'io_service.h',
-            'secure_socket.cc',
             'secure_socket.h',
+            'secure_socket_boringssl.cc',
+            'secure_socket_boringssl.h',
+            'secure_socket_macos.cc',
+            'secure_socket_macos.h',
           ],
         }],
       ],
@@ -95,8 +110,11 @@
         'io_service_no_ssl.cc',
         'io_service_no_ssl.h',
         '../../third_party/root_certificates/root_certificates.cc',
-        'secure_socket.cc',
         'secure_socket.h',
+        'secure_socket_boringssl.cc',
+        'secure_socket_boringssl.h',
+        'secure_socket_macos.cc',
+        'secure_socket_macos.h',
       ],
     }],
   ],
diff --git a/runtime/bin/io_natives.cc b/runtime/bin/io_natives.cc
index 91cc1e8..39946a7 100644
--- a/runtime/bin/io_natives.cc
+++ b/runtime/bin/io_natives.cc
@@ -12,7 +12,6 @@
 #include "include/dart_api.h"
 #include "platform/assert.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -107,6 +106,7 @@
   V(SecureSocket_Renegotiate, 4)                                               \
   V(SecurityContext_Allocate, 1)                                               \
   V(SecurityContext_UsePrivateKeyBytes, 3)                                     \
+  V(SecurityContext_AlpnSupported, 0)                                          \
   V(SecurityContext_SetAlpnProtocols, 3)                                       \
   V(SecurityContext_SetClientAuthoritiesBytes, 3)                              \
   V(SecurityContext_SetTrustedCertificatesBytes, 3)                            \
@@ -169,7 +169,7 @@
   int num_entries = sizeof(IOEntries) / sizeof(struct NativeEntries);
   for (int i = 0; i < num_entries; i++) {
     struct NativeEntries* entry = &(IOEntries[i]);
-    if (!strcmp(function_name, entry->name_) &&
+    if ((strcmp(function_name, entry->name_) == 0) &&
         (entry->argument_count_ == argument_count)) {
       return reinterpret_cast<Dart_NativeFunction>(entry->function_);
     }
diff --git a/runtime/bin/io_natives.h b/runtime/bin/io_natives.h
index d44f839..c17dce5 100644
--- a/runtime/bin/io_natives.h
+++ b/runtime/bin/io_natives.h
@@ -7,7 +7,6 @@
 
 #include "include/dart_api.h"
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/io_service.cc b/runtime/bin/io_service.cc
index 77b722c..004e3d2 100644
--- a/runtime/bin/io_service.cc
+++ b/runtime/bin/io_service.cc
@@ -11,11 +11,10 @@
 #include "bin/socket.h"
 #include "bin/utils.h"
 
-#include "platform/globals.h"
-#include "platform/utils.h"
-
 #include "include/dart_api.h"
 
+#include "platform/globals.h"
+#include "platform/utils.h"
 
 namespace dart {
 namespace bin {
@@ -30,8 +29,8 @@
   Dart_Port reply_port_id = ILLEGAL_PORT;
   CObject* response = CObject::IllegalArgumentError();
   CObjectArray request(message);
-  if (message->type == Dart_CObject_kArray &&
-      request.Length() == 4 &&
+  if ((message->type == Dart_CObject_kArray) &&
+      (request.Length() == 4) &&
       request[0]->IsInt32() &&
       request[1]->IsSendPort() &&
       request[2]->IsInt32() &&
@@ -57,10 +56,7 @@
 
 
 Dart_Port IOService::GetServicePort() {
-  Dart_Port result = Dart_NewNativePort("IOService",
-                                        IOServiceCallback,
-                                        true);
-  return result;
+  return Dart_NewNativePort("IOService", IOServiceCallback, true);
 }
 
 
@@ -74,6 +70,5 @@
   }
 }
 
-
 }  // namespace bin
 }  // namespace dart
diff --git a/runtime/bin/io_service.h b/runtime/bin/io_service.h
index 87810d0..c165e90 100644
--- a/runtime/bin/io_service.h
+++ b/runtime/bin/io_service.h
@@ -8,7 +8,6 @@
 #include "bin/builtin.h"
 #include "bin/utils.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -65,6 +64,10 @@
   };
 
   static Dart_Port GetServicePort();
+
+ private:
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(IOService);
 };
 
 }  // namespace bin
diff --git a/runtime/bin/io_service_no_ssl.cc b/runtime/bin/io_service_no_ssl.cc
index b63f8c8..5c70fe4 100644
--- a/runtime/bin/io_service_no_ssl.cc
+++ b/runtime/bin/io_service_no_ssl.cc
@@ -10,11 +10,10 @@
 #include "bin/socket.h"
 #include "bin/utils.h"
 
-#include "platform/globals.h"
-#include "platform/utils.h"
-
 #include "include/dart_api.h"
 
+#include "platform/globals.h"
+#include "platform/utils.h"
 
 namespace dart {
 namespace bin {
@@ -29,8 +28,8 @@
   Dart_Port reply_port_id = ILLEGAL_PORT;
   CObject* response = CObject::IllegalArgumentError();
   CObjectArray request(message);
-  if (message->type == Dart_CObject_kArray &&
-      request.Length() == 4 &&
+  if ((message->type == Dart_CObject_kArray) &&
+      (request.Length() == 4) &&
       request[0]->IsInt32() &&
       request[1]->IsSendPort() &&
       request[2]->IsInt32() &&
@@ -56,10 +55,7 @@
 
 
 Dart_Port IOService::GetServicePort() {
-  Dart_Port result = Dart_NewNativePort("IOService",
-                                        IOServiceCallback,
-                                        true);
-  return result;
+  return Dart_NewNativePort("IOService", IOServiceCallback, true);
 }
 
 
@@ -73,6 +69,5 @@
   }
 }
 
-
 }  // namespace bin
 }  // namespace dart
diff --git a/runtime/bin/io_service_no_ssl.h b/runtime/bin/io_service_no_ssl.h
index 9cc7fc1..db2af1c 100644
--- a/runtime/bin/io_service_no_ssl.h
+++ b/runtime/bin/io_service_no_ssl.h
@@ -8,7 +8,6 @@
 #include "bin/builtin.h"
 #include "bin/utils.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -66,6 +65,10 @@
   };
 
   static Dart_Port GetServicePort();
+
+ private:
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(IOService);
 };
 
 }  // namespace bin
diff --git a/runtime/bin/io_service_unsupported.cc b/runtime/bin/io_service_unsupported.cc
index 9e51ca1..29a8730 100644
--- a/runtime/bin/io_service_unsupported.cc
+++ b/runtime/bin/io_service_unsupported.cc
@@ -7,7 +7,6 @@
 
 #include "include/dart_api.h"
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/isolate_data.h b/runtime/bin/isolate_data.h
index d3f411f..7ff2bfa 100644
--- a/runtime/bin/isolate_data.h
+++ b/runtime/bin/isolate_data.h
@@ -9,7 +9,6 @@
 #include "platform/assert.h"
 #include "platform/globals.h"
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/lockers.h b/runtime/bin/lockers.h
index 87e44e8..0aefd99 100644
--- a/runtime/bin/lockers.h
+++ b/runtime/bin/lockers.h
@@ -8,7 +8,6 @@
 #include "bin/thread.h"
 #include "platform/assert.h"
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/log.h b/runtime/bin/log.h
index 10629d5..51a4379 100644
--- a/runtime/bin/log.h
+++ b/runtime/bin/log.h
@@ -9,7 +9,6 @@
 
 #include "platform/globals.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -34,6 +33,7 @@
 
   static void VPrintErr(const char* format, va_list args);
 
+ private:
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(Log);
 };
diff --git a/runtime/bin/log_android.cc b/runtime/bin/log_android.cc
index e8d8e68..6e5a621 100644
--- a/runtime/bin/log_android.cc
+++ b/runtime/bin/log_android.cc
@@ -7,9 +7,8 @@
 
 #include "bin/log.h"
 
-#include <stdio.h>  // NOLINT
 #include <android/log.h>  // NOLINT
-
+#include <stdio.h>  // NOLINT
 
 namespace dart {
 namespace bin {
diff --git a/runtime/bin/log_linux.cc b/runtime/bin/log_linux.cc
index f398c9e..abb1983 100644
--- a/runtime/bin/log_linux.cc
+++ b/runtime/bin/log_linux.cc
@@ -9,7 +9,6 @@
 
 #include <stdio.h>  // NOLINT
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/log_macos.cc b/runtime/bin/log_macos.cc
index 3711245..913a60d 100644
--- a/runtime/bin/log_macos.cc
+++ b/runtime/bin/log_macos.cc
@@ -9,7 +9,6 @@
 
 #include <stdio.h>  // NOLINT
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/log_win.cc b/runtime/bin/log_win.cc
index 9fb69cf..d8dfe96 100644
--- a/runtime/bin/log_win.cc
+++ b/runtime/bin/log_win.cc
@@ -9,7 +9,6 @@
 
 #include <stdio.h>  // NOLINT
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 4601588..0eafb9c 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -218,7 +218,7 @@
 static bool ProcessPackagesOption(const char* arg,
                                      CommandLineOptions* vm_options) {
   ASSERT(arg != NULL);
-  if (*arg == '\0' || *arg == '-') {
+  if ((*arg == '\0') || (*arg == '-')) {
     return false;
   }
   commandline_packages_file = arg;
@@ -1076,7 +1076,7 @@
                               const intptr_t size) {
   char* concat = NULL;
   const char* qualified_filename;
-  if ((snapshot_directory != NULL) && strlen(snapshot_directory) > 0) {
+  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);
@@ -1110,7 +1110,7 @@
                              const uint8_t** buffer) {
   char* concat = NULL;
   const char* qualified_filename;
-  if ((snapshot_directory != NULL) && strlen(snapshot_directory) > 0) {
+  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);
@@ -1129,7 +1129,7 @@
   }
   intptr_t len = -1;
   DartUtils::ReadFile(buffer, &len, file);
-  if (*buffer == NULL || len == -1) {
+  if ((*buffer == NULL) || (len == -1)) {
     fprintf(stderr,
             "Error: Unable to read snapshot file %s\n", qualified_filename);
     fflush(stderr);
@@ -1147,7 +1147,7 @@
                                const char* symname) {
   char* concat = NULL;
   const char* qualified_libname;
-  if ((snapshot_directory != NULL) && strlen(snapshot_directory) > 0) {
+  if ((snapshot_directory != NULL) && (strlen(snapshot_directory) > 0)) {
     intptr_t len = snprintf(NULL, 0, "%s/%s", snapshot_directory, libname);
     concat = new char[len + 1];
     snprintf(concat, len + 1, "%s/%s", snapshot_directory, libname);
@@ -1635,6 +1635,7 @@
   char* error = Dart_Initialize(
       vm_isolate_snapshot_buffer, instructions_snapshot, data_snapshot,
       CreateIsolateAndSetup, NULL, NULL, ShutdownIsolate,
+      NULL,
       DartUtils::OpenFile,
       DartUtils::ReadFile,
       DartUtils::WriteFile,
diff --git a/runtime/bin/platform.cc b/runtime/bin/platform.cc
index 75324f1..716ef29 100644
--- a/runtime/bin/platform.cc
+++ b/runtime/bin/platform.cc
@@ -13,7 +13,7 @@
 namespace bin {
 
 const char* Platform::executable_name_ = NULL;
-const char* Platform::resolved_executable_name_ = NULL;
+char* Platform::resolved_executable_name_ = NULL;
 int Platform::script_index_ = 1;
 char** Platform::argv_ = NULL;
 
diff --git a/runtime/bin/platform.h b/runtime/bin/platform.h
index d4f96bd..79cb7be 100644
--- a/runtime/bin/platform.h
+++ b/runtime/bin/platform.h
@@ -7,7 +7,6 @@
 
 #include "bin/builtin.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -49,7 +48,7 @@
   static const char* GetResolvedExecutableName() {
     if (resolved_executable_name_ == NULL) {
       // Try to resolve the executable path using platform specific APIs.
-      resolved_executable_name_ = Platform::ResolveExecutablePath();
+      resolved_executable_name_ = strdup(Platform::ResolveExecutablePath());
     }
     return resolved_executable_name_;
   }
@@ -72,7 +71,7 @@
   // The path to the executable.
   static const char* executable_name_;
   // The path to the resolved executable.
-  static const char* resolved_executable_name_;
+  static char* resolved_executable_name_;
 
   static int script_index_;
   static char** argv_;  // VM flags are argv_[1 ... script_index_ - 1]
diff --git a/runtime/bin/platform_macos.cc b/runtime/bin/platform_macos.cc
index b9a1faa..e21ff13 100644
--- a/runtime/bin/platform_macos.cc
+++ b/runtime/bin/platform_macos.cc
@@ -5,22 +5,19 @@
 #include "platform/globals.h"
 #if defined(TARGET_OS_MACOS)
 
-#include <mach-o/dyld.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-
-#include "bin/file.h"
-#include "bin/platform.h"
-
 #if !TARGET_OS_IOS
 #include <crt_externs.h>  // NOLINT
 #endif  // !TARGET_OS_IOS
+#include <mach-o/dyld.h>
 #include <signal.h>  // NOLINT
 #include <string.h>  // NOLINT
+#include <sys/sysctl.h>  // NOLINT
+#include <sys/types.h>  // NOLINT
 #include <unistd.h>  // NOLINT
 
 #include "bin/fdutils.h"
-
+#include "bin/file.h"
+#include "bin/platform.h"
 
 namespace dart {
 namespace bin {
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index 9bc01bc..78f6cdc 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -6,13 +6,12 @@
 #if defined(TARGET_OS_WINDOWS)
 
 #include "bin/file.h"
-#include "bin/platform.h"
 #include "bin/log.h"
+#include "bin/platform.h"
 #include "bin/socket.h"
 #include "bin/utils.h"
 #include "bin/utils_win.h"
 
-
 namespace dart {
 
 // Defined in vm/os_thread_win.cc
diff --git a/runtime/bin/process.cc b/runtime/bin/process.cc
index 4a87e29..3896505 100644
--- a/runtime/bin/process.cc
+++ b/runtime/bin/process.cc
@@ -34,7 +34,7 @@
   }
   // Protect against user-defined list implementations that can have
   // arbitrary length.
-  if (len < 0 || len > kMaxArgumentListLength) {
+  if ((len < 0) || (len > kMaxArgumentListLength)) {
     result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
     if (Dart_IsError(result)) {
       Dart_PropagateError(result);
diff --git a/runtime/bin/process.h b/runtime/bin/process.h
index bd40086..359c8c1 100644
--- a/runtime/bin/process.h
+++ b/runtime/bin/process.h
@@ -12,7 +12,6 @@
 #include "platform/globals.h"
 #include "platform/utils.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -183,6 +182,8 @@
   Dart_Port port_;
   SignalInfo* next_;
   SignalInfo* prev_;
+
+  DISALLOW_COPY_AND_ASSIGN(SignalInfo);
 };
 
 
@@ -285,6 +286,9 @@
 
   // Number of free bytes in the last node in the list.
   intptr_t free_size_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BufferListBase);
 };
 
 }  // namespace bin
diff --git a/runtime/bin/process_android.cc b/runtime/bin/process_android.cc
index 6f2394d..5e53dbe 100644
--- a/runtime/bin/process_android.cc
+++ b/runtime/bin/process_android.cc
@@ -25,10 +25,8 @@
 #include "platform/signal_blocker.h"
 #include "platform/utils.h"
 
-
 extern char **environ;
 
-
 namespace dart {
 namespace bin {
 
@@ -54,6 +52,8 @@
   pid_t pid_;
   intptr_t fd_;
   ProcessInfo* next_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProcessInfo);
 };
 
 
@@ -108,6 +108,9 @@
   // Mutex protecting all accesses to the linked list of active
   // processes.
   static Mutex* mutex_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList);
 };
 
 
@@ -175,7 +178,7 @@
     while (true) {
       {
         MonitorLocker locker(monitor_);
-        while (running_ && process_count_ == 0) {
+        while (running_ && (process_count_ == 0)) {
           monitor_->Wait(Monitor::kNoTimeout);
         }
         if (!running_) {
@@ -204,9 +207,9 @@
           // pipe has been closed. It is therefore not a problem that
           // write fails with a broken pipe error. Other errors should
           // not happen.
-          if (result != -1 && result != sizeof(message)) {
+          if ((result != -1) && (result != sizeof(message))) {
             FATAL("Failed to write entire process exit message");
-          } else if (result == -1 && errno != EPIPE) {
+          } else if ((result == -1) && (errno != EPIPE)) {
             FATAL1("Failed to write exit code: %d", errno);
           }
           ProcessInfoList::RemoveProcess(pid);
@@ -223,6 +226,9 @@
   static int process_count_;
   static bool running_;
   static Monitor* monitor_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler);
 };
 
 
@@ -265,7 +271,8 @@
     exec_control_[0] = -1;
     exec_control_[1] = -1;
 
-    program_arguments_ = new char*[arguments_length + 2];
+    program_arguments_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
+        (arguments_length + 2) * sizeof(*program_arguments_)));
     program_arguments_[0] = const_cast<char*>(path_);
     for (int i = 0; i < arguments_length; i++) {
       program_arguments_[i + 1] = arguments[i];
@@ -274,7 +281,8 @@
 
     program_environment_ = NULL;
     if (environment != NULL) {
-      program_environment_ = new char*[environment_length + 1];
+      program_environment_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
+          (environment_length + 1) * sizeof(*program_environment_)));
       for (int i = 0; i < environment_length; i++) {
         program_environment_[i] = environment[i];
       }
@@ -283,16 +291,12 @@
   }
 
 
-  ~ProcessStarter() {
-    delete[] program_arguments_;
-    delete[] program_environment_;
-  }
-
-
   int Start() {
     // Create pipes required.
     int err = CreatePipes();
-    if (err != 0) return err;
+    if (err != 0) {
+      return err;
+    }
 
     // Fork to create the new process.
     pid_t pid = TEMP_FAILURE_RETRY(fork());
@@ -312,7 +316,9 @@
     // Register the child process if not detached.
     if (mode_ == kNormal) {
       err = RegisterProcess(pid);
-      if (err != 0) return err;
+      if (err != 0) {
+        return err;
+      }
     }
 
     // Notify child process to start. This is done to delay the call to exec
@@ -491,8 +497,8 @@
             SetupDetachedWithStdio();
           }
 
-          if (working_directory_ != NULL &&
-              TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) {
+          if ((working_directory_ != NULL) &&
+              (TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1)) {
             ReportChildError();
           }
 
@@ -534,9 +540,8 @@
     // Read exec result from child. If no data is returned the exec was
     // successful and the exec call closed the pipe. Otherwise the errno
     // is written to the pipe.
-    bytes_read =
-        FDUtils::ReadFromBlocking(
-            exec_control_[0], &child_errno, sizeof(child_errno));
+    bytes_read = FDUtils::ReadFromBlocking(
+        exec_control_[0], &child_errno, sizeof(child_errno));
     if (bytes_read == sizeof(child_errno)) {
       ReadChildError();
       return child_errno;
@@ -555,8 +560,7 @@
     // is written to the pipe as well.
     int result[2];
     bytes_read =
-        FDUtils::ReadFromBlocking(
-            exec_control_[0], result, sizeof(result));
+        FDUtils::ReadFromBlocking(exec_control_[0], result, sizeof(result));
     if (bytes_read == sizeof(int)) {
       *pid = result[0];
     } else if (bytes_read == 2 * sizeof(int)) {
@@ -576,7 +580,9 @@
 
     // Close all open file descriptors except for exec_control_[1].
     int max_fds = sysconf(_SC_OPEN_MAX);
-    if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+    if (max_fds == -1) {
+      max_fds = _POSIX_OPEN_MAX;
+    }
     for (int fd = 0; fd < max_fds; fd++) {
       if (fd != exec_control_[1]) {
         VOID_TEMP_FAILURE_RETRY(close(fd));
@@ -605,12 +611,14 @@
     // exec_control_[1], write_out_[0], read_in_[1] and
     // read_err_[1].
     int max_fds = sysconf(_SC_OPEN_MAX);
-    if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+    if (max_fds == -1) {
+      max_fds = _POSIX_OPEN_MAX;
+    }
     for (int fd = 0; fd < max_fds; fd++) {
-      if (fd != exec_control_[1] &&
-          fd != write_out_[0] &&
-          fd != read_in_[1] &&
-          fd != read_err_[1]) {
+      if ((fd != exec_control_[1]) &&
+          (fd != write_out_[0]) &&
+          (fd != read_in_[1]) &&
+          (fd != read_err_[1])) {
         VOID_TEMP_FAILURE_RETRY(close(fd));
       }
     }
@@ -731,6 +739,9 @@
   intptr_t* id_;
   intptr_t* exit_event_;
   char** os_error_message_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter);
 };
 
 
@@ -766,10 +777,14 @@
 
 class BufferList: public BufferListBase {
  public:
+  BufferList() {}
+
   bool Read(int fd, intptr_t available) {
     // Read all available bytes.
     while (available > 0) {
-      if (free_size_ == 0) Allocate();
+      if (free_size_ == 0) {
+        Allocate();
+      }
       ASSERT(free_size_ > 0);
       ASSERT(free_size_ <= kBufferSize);
       intptr_t block_size = dart::Utils::Minimum(free_size_, available);
@@ -777,13 +792,18 @@
           fd,
           reinterpret_cast<void*>(FreeSpaceAddress()),
           block_size));
-      if (bytes < 0) return false;
+      if (bytes < 0) {
+        return false;
+      }
       data_size_ += bytes;
       free_size_ -= bytes;
       available -= bytes;
     }
     return true;
   }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BufferList);
 };
 
 
@@ -835,7 +855,7 @@
     // Process incoming data.
     int current_alive = alive;
     for (int i = 0; i < current_alive; i++) {
-      if (fds[i].revents & POLLIN) {
+      if ((fds[i].revents & POLLIN) != 0) {
         intptr_t avail = FDUtils::AvailableBytes(fds[i].fd);
         if (fds[i].fd == out) {
           if (!out_data.Read(out, avail)) {
@@ -857,7 +877,7 @@
           UNREACHABLE();
         }
       }
-      if (fds[i].revents & POLLHUP) {
+      if ((fds[i].revents & POLLHUP) != 0) {
         VOID_TEMP_FAILURE_RETRY(close(fds[i].fd));
         alive--;
         if (i < alive) {
@@ -874,7 +894,9 @@
   // Calculate the exit code.
   intptr_t exit_code = exit_code_data.ints[0];
   intptr_t negative = exit_code_data.ints[1];
-  if (negative) exit_code = -exit_code;
+  if (negative != 0) {
+    exit_code = -exit_code;
+  }
   result->set_exit_code(exit_code);
 
   return true;
@@ -936,7 +958,9 @@
       break;
     }
   }
-  if (!found) return -1;
+  if (!found) {
+    return -1;
+  }
   int fds[2];
   if (NO_RETRY_EXPECTED(pipe2(fds, O_CLOEXEC)) != 0) {
     return -1;
@@ -986,7 +1010,9 @@
     bool remove = false;
     if (handler->signal() == signal) {
       if (handler->port() == Dart_GetMainPortId()) {
-        if (signal_handlers == handler) signal_handlers = handler->next();
+        if (signal_handlers == handler) {
+          signal_handlers = handler->next();
+        }
         handler->Unlink();
         remove = true;
       } else {
@@ -994,7 +1020,9 @@
       }
     }
     SignalInfo* next = handler->next();
-    if (remove) delete handler;
+    if (remove) {
+      delete handler;
+    }
     handler = next;
   }
   if (unlisten) {
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index 572ced7..b657235 100644
--- a/runtime/bin/process_linux.cc
+++ b/runtime/bin/process_linux.cc
@@ -24,10 +24,8 @@
 #include "platform/signal_blocker.h"
 #include "platform/utils.h"
 
-
 extern char **environ;
 
-
 namespace dart {
 namespace bin {
 
@@ -53,6 +51,8 @@
   pid_t pid_;
   intptr_t fd_;
   ProcessInfo* next_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProcessInfo);
 };
 
 
@@ -107,6 +107,9 @@
   // Mutex protecting all accesses to the linked list of active
   // processes.
   static Mutex* mutex_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList);
 };
 
 
@@ -203,9 +206,9 @@
           // pipe has been closed. It is therefore not a problem that
           // write fails with a broken pipe error. Other errors should
           // not happen.
-          if (result != -1 && result != sizeof(message)) {
+          if ((result != -1) && (result != sizeof(message))) {
             FATAL("Failed to write entire process exit message");
-          } else if (result == -1 && errno != EPIPE) {
+          } else if ((result == -1) && (errno != EPIPE)) {
             FATAL1("Failed to write exit code: %d", errno);
           }
           ProcessInfoList::RemoveProcess(pid);
@@ -222,6 +225,9 @@
   static int process_count_;
   static bool running_;
   static Monitor* monitor_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler);
 };
 
 
@@ -264,7 +270,8 @@
     exec_control_[0] = -1;
     exec_control_[1] = -1;
 
-    program_arguments_ = new char*[arguments_length + 2];
+    program_arguments_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
+        (arguments_length + 2) * sizeof(*program_arguments_)));
     program_arguments_[0] = const_cast<char*>(path_);
     for (int i = 0; i < arguments_length; i++) {
       program_arguments_[i + 1] = arguments[i];
@@ -273,7 +280,8 @@
 
     program_environment_ = NULL;
     if (environment != NULL) {
-      program_environment_ = new char*[environment_length + 1];
+      program_environment_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
+          (environment_length + 1) * sizeof(*program_environment_)));
       for (int i = 0; i < environment_length; i++) {
         program_environment_[i] = environment[i];
       }
@@ -282,16 +290,12 @@
   }
 
 
-  ~ProcessStarter() {
-    delete[] program_arguments_;
-    delete[] program_environment_;
-  }
-
-
   int Start() {
     // Create pipes required.
     int err = CreatePipes();
-    if (err != 0) return err;
+    if (err != 0) {
+      return err;
+    }
 
     // Fork to create the new process.
     pid_t pid = TEMP_FAILURE_RETRY(fork());
@@ -311,7 +315,9 @@
     // Register the child process if not detached.
     if (mode_ == kNormal) {
       err = RegisterProcess(pid);
-      if (err != 0) return err;
+      if (err != 0) {
+        return err;
+      }
     }
 
     // Notify child process to start. This is done to delay the call to exec
@@ -490,8 +496,8 @@
             SetupDetachedWithStdio();
           }
 
-          if (working_directory_ != NULL &&
-              TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) {
+          if ((working_directory_ != NULL) &&
+              (TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1)) {
             ReportChildError();
           }
 
@@ -533,9 +539,8 @@
     // Read exec result from child. If no data is returned the exec was
     // successful and the exec call closed the pipe. Otherwise the errno
     // is written to the pipe.
-    bytes_read =
-        FDUtils::ReadFromBlocking(
-            exec_control_[0], &child_errno, sizeof(child_errno));
+    bytes_read = FDUtils::ReadFromBlocking(
+        exec_control_[0], &child_errno, sizeof(child_errno));
     if (bytes_read == sizeof(child_errno)) {
       ReadChildError();
       return child_errno;
@@ -554,8 +559,7 @@
     // is written to the pipe as well.
     int result[2];
     bytes_read =
-        FDUtils::ReadFromBlocking(
-            exec_control_[0], result, sizeof(result));
+        FDUtils::ReadFromBlocking(exec_control_[0], result, sizeof(result));
     if (bytes_read == sizeof(int)) {
       *pid = result[0];
     } else if (bytes_read == 2 * sizeof(int)) {
@@ -575,7 +579,9 @@
 
     // Close all open file descriptors except for exec_control_[1].
     int max_fds = sysconf(_SC_OPEN_MAX);
-    if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+    if (max_fds == -1) {
+      max_fds = _POSIX_OPEN_MAX;
+    }
     for (int fd = 0; fd < max_fds; fd++) {
       if (fd != exec_control_[1]) {
         VOID_TEMP_FAILURE_RETRY(close(fd));
@@ -604,12 +610,14 @@
     // exec_control_[1], write_out_[0], read_in_[1] and
     // read_err_[1].
     int max_fds = sysconf(_SC_OPEN_MAX);
-    if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+    if (max_fds == -1) {
+      max_fds = _POSIX_OPEN_MAX;
+    }
     for (int fd = 0; fd < max_fds; fd++) {
-      if (fd != exec_control_[1] &&
-          fd != write_out_[0] &&
-          fd != read_in_[1] &&
-          fd != read_err_[1]) {
+      if ((fd != exec_control_[1]) &&
+          (fd != write_out_[0]) &&
+          (fd != read_in_[1]) &&
+          (fd != read_err_[1])) {
         VOID_TEMP_FAILURE_RETRY(close(fd));
       }
     }
@@ -659,9 +667,8 @@
     const int kBufferSize = 1024;
     char error_buf[kBufferSize];
     char* os_error_message = Utils::StrError(errno, error_buf, kBufferSize);
-    int bytes_written =
-        FDUtils::WriteToBlocking(
-            exec_control_[1], &child_errno, sizeof(child_errno));
+    int bytes_written = FDUtils::WriteToBlocking(
+        exec_control_[1], &child_errno, sizeof(child_errno));
     if (bytes_written == sizeof(child_errno)) {
       FDUtils::WriteToBlocking(
           exec_control_[1], os_error_message, strlen(os_error_message) + 1);
@@ -730,6 +737,9 @@
   intptr_t* id_;
   intptr_t* exit_event_;
   char** os_error_message_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter);
 };
 
 
@@ -765,10 +775,14 @@
 
 class BufferList: public BufferListBase {
  public:
+  BufferList() {}
+
   bool Read(int fd, intptr_t available) {
     // Read all available bytes.
     while (available > 0) {
-      if (free_size_ == 0) Allocate();
+      if (free_size_ == 0) {
+        Allocate();
+      }
       ASSERT(free_size_ > 0);
       ASSERT(free_size_ <= kBufferSize);
       intptr_t block_size = dart::Utils::Minimum(free_size_, available);
@@ -776,13 +790,18 @@
           fd,
           reinterpret_cast<void*>(FreeSpaceAddress()),
           block_size));
-      if (bytes < 0) return false;
+      if (bytes < 0) {
+        return false;
+      }
       data_size_ += bytes;
       free_size_ -= bytes;
       available -= bytes;
     }
     return true;
   }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BufferList);
 };
 
 
@@ -834,7 +853,7 @@
     // Process incoming data.
     int current_alive = alive;
     for (int i = 0; i < current_alive; i++) {
-      if (fds[i].revents & POLLIN) {
+      if ((fds[i].revents & POLLIN) != 0) {
         intptr_t avail = FDUtils::AvailableBytes(fds[i].fd);
         if (fds[i].fd == out) {
           if (!out_data.Read(out, avail)) {
@@ -856,7 +875,7 @@
           UNREACHABLE();
         }
       }
-      if (fds[i].revents & POLLHUP) {
+      if ((fds[i].revents & POLLHUP) != 0) {
         VOID_TEMP_FAILURE_RETRY(close(fds[i].fd));
         alive--;
         if (i < alive) {
@@ -873,7 +892,9 @@
   // Calculate the exit code.
   intptr_t exit_code = exit_code_data.ints[0];
   intptr_t negative = exit_code_data.ints[1];
-  if (negative) exit_code = -exit_code;
+  if (negative != 0) {
+    exit_code = -exit_code;
+  }
   result->set_exit_code(exit_code);
 
   return true;
@@ -935,7 +956,9 @@
       break;
     }
   }
-  if (!found) return -1;
+  if (!found) {
+    return -1;
+  }
   int fds[2];
   if (NO_RETRY_EXPECTED(pipe2(fds, O_CLOEXEC)) != 0) {
     return -1;
@@ -982,7 +1005,9 @@
     bool remove = false;
     if (handler->signal() == signal) {
       if (handler->port() == Dart_GetMainPortId()) {
-        if (signal_handlers == handler) signal_handlers = handler->next();
+        if (signal_handlers == handler) {
+          signal_handlers = handler->next();
+        }
         handler->Unlink();
         remove = true;
       } else {
@@ -990,7 +1015,9 @@
       }
     }
     SignalInfo* next = handler->next();
-    if (remove) delete handler;
+    if (remove) {
+      delete handler;
+    }
     handler = next;
   }
   if (unlisten) {
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index 00869a1..00b2d8e 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -28,8 +28,6 @@
 #include "platform/signal_blocker.h"
 #include "platform/utils.h"
 
-
-
 namespace dart {
 namespace bin {
 
@@ -55,6 +53,8 @@
   pid_t pid_;
   intptr_t fd_;
   ProcessInfo* next_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProcessInfo);
 };
 
 
@@ -109,6 +109,9 @@
   // Mutex protecting all accesses to the linked list of active
   // processes.
   static Mutex* mutex_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList);
 };
 
 
@@ -205,9 +208,9 @@
           // pipe has been closed. It is therefore not a problem that
           // write fails with a broken pipe error. Other errors should
           // not happen.
-          if (result != -1 && result != sizeof(message)) {
+          if ((result != -1) && (result != sizeof(message))) {
             FATAL("Failed to write entire process exit message");
-          } else if (result == -1 && errno != EPIPE) {
+          } else if ((result == -1) && (errno != EPIPE)) {
             FATAL1("Failed to write exit code: %d", errno);
           }
           ProcessInfoList::RemoveProcess(pid);
@@ -224,6 +227,9 @@
   static int process_count_;
   static bool running_;
   static Monitor* monitor_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler);
 };
 
 
@@ -266,7 +272,8 @@
     exec_control_[0] = -1;
     exec_control_[1] = -1;
 
-    program_arguments_ = new char*[arguments_length + 2];
+    program_arguments_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
+        (arguments_length + 2) * sizeof(*program_arguments_)));
     program_arguments_[0] = const_cast<char*>(path_);
     for (int i = 0; i < arguments_length; i++) {
       program_arguments_[i + 1] = arguments[i];
@@ -275,7 +282,8 @@
 
     program_environment_ = NULL;
     if (environment != NULL) {
-      program_environment_ = new char*[environment_length + 1];
+      program_environment_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
+          (environment_length + 1) * sizeof(*program_environment_)));
       for (int i = 0; i < environment_length; i++) {
         program_environment_[i] = environment[i];
       }
@@ -284,12 +292,6 @@
   }
 
 
-  ~ProcessStarter() {
-    delete[] program_arguments_;
-    delete[] program_environment_;
-  }
-
-
   int Start() {
     // Create pipes required.
     int err = CreatePipes();
@@ -509,8 +511,8 @@
             SetupDetachedWithStdio();
           }
 
-          if (working_directory_ != NULL &&
-              TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) {
+          if ((working_directory_ != NULL) &&
+              (TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1)) {
             ReportChildError();
           }
 
@@ -554,9 +556,8 @@
     // Read exec result from child. If no data is returned the exec was
     // successful and the exec call closed the pipe. Otherwise the errno
     // is written to the pipe.
-    bytes_read =
-        FDUtils::ReadFromBlocking(
-            exec_control_[0], &child_errno, sizeof(child_errno));
+    bytes_read = FDUtils::ReadFromBlocking(
+        exec_control_[0], &child_errno, sizeof(child_errno));
     if (bytes_read == sizeof(child_errno)) {
       ReadChildError();
       return child_errno;
@@ -575,8 +576,7 @@
     // is written to the pipe as well.
     int result[2];
     bytes_read =
-        FDUtils::ReadFromBlocking(
-            exec_control_[0], result, sizeof(result));
+        FDUtils::ReadFromBlocking(exec_control_[0], result, sizeof(result));
     if (bytes_read == sizeof(int)) {
       *pid = result[0];
     } else if (bytes_read == 2 * sizeof(int)) {
@@ -596,7 +596,9 @@
 
     // Close all open file descriptors except for exec_control_[1].
     int max_fds = sysconf(_SC_OPEN_MAX);
-    if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+    if (max_fds == -1) {
+      max_fds = _POSIX_OPEN_MAX;
+    }
     for (int fd = 0; fd < max_fds; fd++) {
       if (fd != exec_control_[1]) {
         VOID_TEMP_FAILURE_RETRY(close(fd));
@@ -625,12 +627,14 @@
     // exec_control_[1], write_out_[0], read_in_[1] and
     // read_err_[1].
     int max_fds = sysconf(_SC_OPEN_MAX);
-    if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+    if (max_fds == -1) {
+      max_fds = _POSIX_OPEN_MAX;
+    }
     for (int fd = 0; fd < max_fds; fd++) {
-      if (fd != exec_control_[1] &&
-          fd != write_out_[0] &&
-          fd != read_in_[1] &&
-          fd != read_err_[1]) {
+      if ((fd != exec_control_[1]) &&
+          (fd != write_out_[0]) &&
+          (fd != read_in_[1]) &&
+          (fd != read_err_[1])) {
         VOID_TEMP_FAILURE_RETRY(close(fd));
       }
     }
@@ -680,9 +684,8 @@
     const int kBufferSize = 1024;
     char os_error_message[kBufferSize];
     Utils::StrError(errno, os_error_message, kBufferSize);
-    int bytes_written =
-        FDUtils::WriteToBlocking(
-            exec_control_[1], &child_errno, sizeof(child_errno));
+    int bytes_written = FDUtils::WriteToBlocking(
+        exec_control_[1], &child_errno, sizeof(child_errno));
     if (bytes_written == sizeof(child_errno)) {
       FDUtils::WriteToBlocking(
           exec_control_[1], os_error_message, strlen(os_error_message) + 1);
@@ -751,6 +754,9 @@
   intptr_t* id_;
   intptr_t* exit_event_;
   char** os_error_message_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter);
 };
 
 
@@ -786,10 +792,14 @@
 
 class BufferList: public BufferListBase {
  public:
+  BufferList() {}
+
   bool Read(int fd, intptr_t available) {
     // Read all available bytes.
     while (available > 0) {
-      if (free_size_ == 0) Allocate();
+      if (free_size_ == 0) {
+        Allocate();
+      }
       ASSERT(free_size_ > 0);
       ASSERT(free_size_ <= kBufferSize);
       size_t block_size = dart::Utils::Minimum(free_size_, available);
@@ -797,13 +807,18 @@
           fd,
           reinterpret_cast<void*>(FreeSpaceAddress()),
           block_size));
-      if (bytes < 0) return false;
+      if (bytes < 0) {
+        return false;
+      }
       data_size_ += bytes;
       free_size_ -= bytes;
       available -= bytes;
     }
     return true;
   }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BufferList);
 };
 
 
@@ -856,7 +871,7 @@
     int current_alive = alive;
     for (int i = 0; i < current_alive; i++) {
       intptr_t avail;
-      if (fds[i].revents & POLLIN) {
+      if ((fds[i].revents & POLLIN) != 0) {
         avail = FDUtils::AvailableBytes(fds[i].fd);
         // On Mac OS POLLIN can be set with zero available
         // bytes. POLLHUP is most likely also set in this case.
@@ -882,8 +897,8 @@
           }
         }
       }
-      if (fds[i].revents & POLLHUP ||
-          ((fds[i].revents & POLLIN) && avail == 0)) {
+      if (((fds[i].revents & POLLHUP) != 0) ||
+          (((fds[i].revents & POLLIN) != 0) && (avail == 0))) {
         VOID_TEMP_FAILURE_RETRY(close(fds[i].fd));
         alive--;
         if (i < alive) {
@@ -900,7 +915,9 @@
   // Calculate the exit code.
   intptr_t exit_code = exit_code_data.ints[0];
   intptr_t negative = exit_code_data.ints[1];
-  if (negative) exit_code = -exit_code;
+  if (negative != 0) {
+    exit_code = -exit_code;
+  }
   result->set_exit_code(exit_code);
 
   return true;
@@ -992,7 +1009,9 @@
 
 intptr_t Process::SetSignalHandler(intptr_t signal) {
   signal = SignalMap(signal);
-  if (signal == -1) return -1;
+  if (signal == -1) {
+    return -1;
+  }
   bool found = false;
   for (int i = 0; i < kSignalsCount; i++) {
     if (kSignals[i] == signal) {
@@ -1000,7 +1019,9 @@
       break;
     }
   }
-  if (!found) return -1;
+  if (!found) {
+    return -1;
+  }
   int fds[2];
   if (NO_RETRY_EXPECTED(pipe(fds)) != 0) {
     return -1;
@@ -1045,7 +1066,9 @@
 
 void Process::ClearSignalHandler(intptr_t signal) {
   signal = SignalMap(signal);
-  if (signal == -1) return;
+  if (signal == -1) {
+    return;
+  }
   ThreadSignalBlocker blocker(kSignalsCount, kSignals);
   MutexLocker lock(signal_mutex);
   SignalInfo* handler = signal_handlers;
@@ -1054,7 +1077,9 @@
     bool remove = false;
     if (handler->signal() == signal) {
       if (handler->port() == Dart_GetMainPortId()) {
-        if (signal_handlers == handler) signal_handlers = handler->next();
+        if (signal_handlers == handler) {
+          signal_handlers = handler->next();
+        }
         handler->Unlink();
         remove = true;
       } else {
@@ -1062,7 +1087,9 @@
       }
     }
     SignalInfo* next = handler->next();
-    if (remove) delete handler;
+    if (remove) {
+      delete handler;
+    }
     handler = next;
   }
   if (unlisten) {
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
index 1c0a03d..9777c55 100644
--- a/runtime/bin/process_win.cc
+++ b/runtime/bin/process_win.cc
@@ -5,11 +5,12 @@
 #include "platform/globals.h"
 #if defined(TARGET_OS_WINDOWS)
 
+#include "bin/process.h"
+
 #include <process.h>  // NOLINT
 
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
-#include "bin/process.h"
 #include "bin/eventhandler.h"
 #include "bin/lockers.h"
 #include "bin/log.h"
@@ -18,7 +19,6 @@
 #include "bin/utils.h"
 #include "bin/utils_win.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -72,6 +72,8 @@
   HANDLE exit_pipe_;
   // Link to next ProcessInfo object in the singly-linked list.
   ProcessInfo* next_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProcessInfo);
 };
 
 
@@ -143,7 +145,9 @@
   // Callback called when an exit code is available from one of the
   // processes in the list.
   static void CALLBACK ExitCodeCallback(PVOID data, BOOLEAN timed_out) {
-    if (timed_out) return;
+    if (timed_out) {
+      return;
+    }
     DWORD pid = reinterpret_cast<DWORD>(data);
     HANDLE handle;
     HANDLE wait_handle;
@@ -154,13 +158,12 @@
     }
     // Unregister the event in a non-blocking way.
     BOOL ok = UnregisterWait(wait_handle);
-    if (!ok && GetLastError() != ERROR_IO_PENDING) {
+    if (!ok && (GetLastError() != ERROR_IO_PENDING)) {
       FATAL("Failed unregistering wait operation");
     }
     // Get and report the exit code to Dart.
     int exit_code;
-    ok = GetExitCodeProcess(handle,
-                            reinterpret_cast<DWORD*>(&exit_code));
+    ok = GetExitCodeProcess(handle, reinterpret_cast<DWORD*>(&exit_code));
     if (!ok) {
       FATAL1("GetExitCodeProcess failed %d\n", GetLastError());
     }
@@ -176,9 +179,9 @@
     // pipe has been closed. It is therefore not a problem that
     // WriteFile fails with a closed pipe error
     // (ERROR_NO_DATA). Other errors should not happen.
-    if (ok && written != sizeof(message)) {
+    if (ok && (written != sizeof(message))) {
       FATAL("Failed to write entire process exit message");
-    } else if (!ok && GetLastError() != ERROR_NO_DATA) {
+    } else if (!ok && (GetLastError() != ERROR_NO_DATA)) {
       FATAL1("Failed to write exit code: %d", GetLastError());
     }
     // Remove the process from the list of active processes.
@@ -191,6 +194,9 @@
   // Mutex protecting all accesses to the linked list of active
   // processes.
   static Mutex* mutex_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList);
 };
 
 
@@ -249,7 +255,7 @@
       return false;
     }
   } else {
-    ASSERT(type == kInheritWrite || type == kInheritNone);
+    ASSERT((type == kInheritWrite) || (type == kInheritNone));
     handles[kReadHandle] =
         CreateNamedPipeW(pipe_name,
                          PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
@@ -357,19 +363,19 @@
   HMODULE kernel32_module = GetModuleHandleW(L"kernel32.dll");
   if (!load_attempted) {
     MutexLocker locker(mutex);
-    if (load_attempted) return delete_proc_thread_attr_list != NULL;
+    if (load_attempted) {
+      return (delete_proc_thread_attr_list != NULL);
+    }
     init_proc_thread_attr_list = reinterpret_cast<InitProcThreadAttrListFn>(
         GetProcAddress(kernel32_module, "InitializeProcThreadAttributeList"));
-    update_proc_thread_attr =
-        reinterpret_cast<UpdateProcThreadAttrFn>(
-            GetProcAddress(kernel32_module, "UpdateProcThreadAttribute"));
+    update_proc_thread_attr = reinterpret_cast<UpdateProcThreadAttrFn>(
+        GetProcAddress(kernel32_module, "UpdateProcThreadAttribute"));
     delete_proc_thread_attr_list = reinterpret_cast<DeleteProcThreadAttrListFn>(
-        reinterpret_cast<DeleteProcThreadAttrListFn>(
-            GetProcAddress(kernel32_module, "DeleteProcThreadAttributeList")));
+        GetProcAddress(kernel32_module, "DeleteProcThreadAttributeList"));
     load_attempted = true;
-    return delete_proc_thread_attr_list != NULL;
+    return (delete_proc_thread_attr_list != NULL);
   }
-  return delete_proc_thread_attr_list != NULL;
+  return (delete_proc_thread_attr_list != NULL);
 }
 
 
@@ -378,7 +384,7 @@
 static int GenerateNames(wchar_t pipe_names[Count][kMaxPipeNameSize]) {
   UUID uuid;
   RPC_STATUS status = UuidCreateSequential(&uuid);
-  if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) {
+  if ((status != RPC_S_OK) && (status != RPC_S_UUID_LOCAL_ONLY)) {
     return status;
   }
   RPC_WSTR uuid_string;
@@ -451,7 +457,8 @@
     command_line_length += arguments_length + 1;
 
     // Put together command-line string.
-    command_line_ = new wchar_t[command_line_length];
+    command_line_ = reinterpret_cast<wchar_t*>(Dart_ScopeAllocate(
+        command_line_length * sizeof(*command_line_)));
     int len = 0;
     int remaining = command_line_length;
     int written =
@@ -460,9 +467,8 @@
     remaining -= written;
     ASSERT(remaining >= 0);
     for (int i = 0; i < arguments_length; i++) {
-      written =
-          _snwprintf(
-              command_line_ + len, remaining, L" %s", system_arguments[i]);
+      written = _snwprintf(
+          command_line_ + len, remaining, L" %s", system_arguments[i]);
       len += written;
       remaining -= written;
       ASSERT(remaining >= 0);
@@ -485,7 +491,8 @@
       for (intptr_t i = 0; i < environment_length; i++) {
         block_size += wcslen(system_environment[i]) + 1;
       }
-      environment_block_ = new wchar_t[block_size];
+      environment_block_ = reinterpret_cast<wchar_t*>(Dart_ScopeAllocate(
+          block_size * sizeof(*environment_block_)));
       intptr_t block_index = 0;
       for (intptr_t i = 0; i < environment_length; i++) {
         intptr_t len = wcslen(system_environment[i]);
@@ -513,12 +520,8 @@
 
 
   ~ProcessStarter() {
-    // Deallocate command-line and environment block strings.
-    delete[] command_line_;
-    delete[] environment_block_;
     if (attribute_list_ != NULL) {
       delete_proc_thread_attr_list(attribute_list_);
-      free(attribute_list_);
     }
   }
 
@@ -526,7 +529,9 @@
   int Start() {
     // Create pipes required.
     int err = CreatePipes();
-    if (err != 0) return err;
+    if (err != 0) {
+      return err;
+    }
 
     // Setup info structures.
     STARTUPINFOEXW startup_info;
@@ -545,11 +550,11 @@
       // The call to determine the size of an attribute list always fails with
       // ERROR_INSUFFICIENT_BUFFER and that error should be ignored.
       if (!init_proc_thread_attr_list(NULL, 1, 0, &size) &&
-          GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+          (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
         return CleanupAndReturnError();
       }
-      attribute_list_ =
-          reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(size));
+      attribute_list_ = reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(
+          Dart_ScopeAllocate(size));
       ZeroMemory(attribute_list_, size);
       if (!init_proc_thread_attr_list(attribute_list_, 1, 0, &size)) {
         return CleanupAndReturnError();
@@ -650,10 +655,19 @@
         }
       }
     } else {
-      // Open NUL for stdin, stdout and stderr.
-      if ((stdin_handles_[kReadHandle] = OpenNul()) == INVALID_HANDLE_VALUE ||
-          (stdout_handles_[kWriteHandle] = OpenNul()) == INVALID_HANDLE_VALUE ||
-          (stderr_handles_[kWriteHandle] = OpenNul()) == INVALID_HANDLE_VALUE) {
+      // Open NUL for stdin, stdout, and stderr.
+      stdin_handles_[kReadHandle] = OpenNul();
+      if (stdin_handles_[kReadHandle] == INVALID_HANDLE_VALUE) {
+        return CleanupAndReturnError();
+      }
+
+      stdout_handles_[kWriteHandle] = OpenNul();
+      if (stdout_handles_[kWriteHandle] == INVALID_HANDLE_VALUE) {
+        return CleanupAndReturnError();
+      }
+
+      stderr_handles_[kWriteHandle] = OpenNul();
+      if (stderr_handles_[kWriteHandle] == INVALID_HANDLE_VALUE) {
         return CleanupAndReturnError();
       }
     }
@@ -688,6 +702,10 @@
   intptr_t* id_;
   intptr_t* exit_handler_;
   char** os_error_message_;
+
+ private:
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter);
 };
 
 
@@ -738,7 +756,9 @@
   // The access to the read buffer for overlapped read.
   void GetReadBuffer(uint8_t** buffer, intptr_t* size) {
     ASSERT(!read_pending_);
-    if (free_size_ == 0) Allocate();
+    if (free_size_ == 0) {
+      Allocate();
+    }
     ASSERT(free_size_ > 0);
     ASSERT(free_size_ <= kBufferSize);
     *buffer = FreeSpaceAddress();
@@ -763,11 +783,15 @@
 
  private:
   bool read_pending_;
+
+  DISALLOW_COPY_AND_ASSIGN(BufferList);
 };
 
 
 class OverlappedHandle {
  public:
+  OverlappedHandle() {}
+
   void Init(HANDLE handle, HANDLE event) {
     handle_ = handle;
     event_ = event;
@@ -775,7 +799,7 @@
   }
 
   bool HasEvent(HANDLE event) {
-    return event_ == event;
+    return (event_ == event);
   }
 
   bool Read() {
@@ -793,7 +817,9 @@
       intptr_t buffer_size;
       buffer_.GetReadBuffer(&buffer, &buffer_size);
       BOOL ok = ReadFile(handle_, buffer, buffer_size, NULL, &overlapped_);
-      if (!ok) return GetLastError() == ERROR_IO_PENDING;
+      if (!ok) {
+        return (GetLastError() == ERROR_IO_PENDING);
+      }
       buffer_.DataIsRead(overlapped_.InternalHigh);
     }
   }
@@ -833,6 +859,7 @@
   BufferList buffer_;
 
   DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(OverlappedHandle);
 };
 
 
@@ -905,12 +932,14 @@
 
   // Calculate the exit code.
   ASSERT(oh[2].GetDataSize() == 8);
-  uint32_t exit[2];
-  memmove(&exit, oh[2].GetFirstDataBuffer(), sizeof(exit));
+  uint32_t exit_codes[2];
+  memmove(&exit_codes, oh[2].GetFirstDataBuffer(), sizeof(exit_codes));
   oh[2].FreeDataBuffer();
-  intptr_t exit_code = exit[0];
-  intptr_t negative = exit[1];
-  if (negative) exit_code = -exit_code;
+  intptr_t exit_code = exit_codes[0];
+  intptr_t negative = exit_codes[1];
+  if (negative != 0) {
+    exit_code = -exit_code;
+  }
   result->set_exit_code(exit_code);
   return true;
 }
@@ -931,7 +960,9 @@
   if (!success) {
     process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, id);
     // The process is already dead.
-    if (process_handle == INVALID_HANDLE_VALUE) return false;
+    if (process_handle == INVALID_HANDLE_VALUE) {
+      return false;
+    }
   }
   BOOL result = TerminateProcess(process_handle, -1);
   return result ? true : false;
@@ -985,12 +1016,16 @@
 
 intptr_t Process::SetSignalHandler(intptr_t signal) {
   signal = GetWinSignal(signal);
-  if (signal == -1) return -1;
+  if (signal == -1) {
+    return -1;
+  }
 
   // Generate a unique pipe name for the named pipe.
   wchar_t pipe_name[kMaxPipeNameSize];
   int status = GenerateNames<1>(&pipe_name);
-  if (status != 0) return status;
+  if (status != 0) {
+    return status;
+  }
 
   HANDLE fds[2];
   if (!CreateProcessPipe(fds, pipe_name, kInheritNone)) {
@@ -1019,12 +1054,14 @@
 
 void Process::ClearSignalHandler(intptr_t signal) {
   signal = GetWinSignal(signal);
-  if (signal == -1) return;
+  if (signal == -1) {
+    return;
+  }
   MutexLocker lock(signal_mutex);
   SignalInfo* handler = signal_handlers;
   while (handler != NULL) {
-    if (handler->port() == Dart_GetMainPortId() &&
-        handler->signal() == signal) {
+    if ((handler->port() == Dart_GetMainPortId()) &&
+        (handler->signal() == signal)) {
       handler->Unlink();
       break;
     }
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index ec9479a..5b62b20 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -4,8 +4,8 @@
 
 #include <stdio.h>
 
-#include "bin/file.h"
 #include "bin/dartutils.h"
+#include "bin/file.h"
 #include "bin/platform.h"
 
 #include "vm/benchmark_test.h"
@@ -108,6 +108,7 @@
   const char* err_msg = Dart::InitOnce(dart::bin::vm_isolate_snapshot_buffer,
                                        NULL, NULL,
                                        NULL, NULL,
+                                       NULL,
                                        dart::bin::DartUtils::OpenFile,
                                        dart::bin::DartUtils::ReadFile,
                                        dart::bin::DartUtils::WriteFile,
diff --git a/runtime/bin/secure_socket.h b/runtime/bin/secure_socket.h
index 754d240..d9fb968 100644
--- a/runtime/bin/secure_socket.h
+++ b/runtime/bin/secure_socket.h
@@ -9,126 +9,15 @@
 #error "secure_socket.h can only be included on builds with SSL enabled"
 #endif
 
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <sys/types.h>
-
-#include <openssl/bio.h>
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#include <openssl/x509.h>
-
-#include "bin/builtin.h"
-#include "bin/dartutils.h"
-#include "bin/socket.h"
-#include "bin/thread.h"
-#include "bin/utils.h"
-
-namespace dart {
-namespace bin {
-
-/* These are defined in root_certificates.cc. */
-extern const unsigned char* root_certificates_pem;
-extern unsigned int root_certificates_pem_length;
-
-/*
- * SSLFilter encapsulates the NSS SSL(TLS) 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:
-  // These enums must agree with those in sdk/lib/io/secure_socket.dart.
-  enum BufferIndex {
-    kReadPlaintext,
-    kWritePlaintext,
-    kReadEncrypted,
-    kWriteEncrypted,
-    kNumBuffers,
-    kFirstEncrypted = kReadEncrypted
-  };
-
-  SSLFilter()
-      : callback_error(NULL),
-        ssl_(NULL),
-        socket_side_(NULL),
-        string_start_(NULL),
-        string_length_(NULL),
-        handshake_complete_(NULL),
-        bad_certificate_callback_(NULL),
-        in_handshake_(false),
-        hostname_(NULL) { }
-
-  ~SSLFilter();
-
-  Dart_Handle Init(Dart_Handle dart_this);
-  void Connect(const char* hostname,
-               SSL_CTX* context,
-               bool is_server,
-               bool request_client_certificate,
-               bool require_client_certificate,
-               Dart_Handle protocols_handle);
-  void Destroy();
-  void Handshake();
-  void GetSelectedProtocol(Dart_NativeArguments args);
-  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 bad_certificate_callback() {
-    return Dart_HandleFromPersistent(bad_certificate_callback_);
-  }
-  int ProcessReadPlaintextBuffer(int start, int end);
-  int ProcessWritePlaintextBuffer(int start, int end);
-  int ProcessReadEncryptedBuffer(int start, int end);
-  int ProcessWriteEncryptedBuffer(int start, int end);
-  bool ProcessAllBuffers(int starts[kNumBuffers],
-                         int ends[kNumBuffers],
-                         bool in_handshake);
-  Dart_Handle PeerCertificate();
-  static void InitializeLibrary();
-  Dart_Handle callback_error;
-
-  static CObject* ProcessFilterRequest(const CObjectArray& request);
-
-  // The index of the external data field in _ssl that points to the SSLFilter.
-  static int filter_ssl_index;
-
-  // TODO(whesse): make private:
-  SSL* ssl_;
-  BIO* socket_side_;
-
-
- private:
-  static bool library_initialized_;
-  static Mutex* mutex_;  // To protect library initialization.
-
-  uint8_t* buffers_[kNumBuffers];
-  int buffer_size_;
-  int 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 is_server_;
-  char* hostname_;
-
-  static bool isBufferEncrypted(int i) {
-    return static_cast<BufferIndex>(i) >= kFirstEncrypted;
-  }
-  Dart_Handle InitializeBuffers(Dart_Handle dart_this);
-  void InitializePlatformData();
-
-  DISALLOW_COPY_AND_ASSIGN(SSLFilter);
-};
-
-}  // namespace bin
-}  // namespace dart
+#include "platform/globals.h"
+#if defined(TARGET_OS_ANDROID) || \
+    defined(TARGET_OS_LINUX)   || \
+    defined(TARGET_OS_WINDOWS)
+#include "bin/secure_socket_boringssl.h"
+#elif defined(TARGET_OS_MACOS)
+#include "bin/secure_socket_macos.h"
+#else
+#error Unknown target os.
+#endif
 
 #endif  // BIN_SECURE_SOCKET_H_
diff --git a/runtime/bin/secure_socket.cc b/runtime/bin/secure_socket_boringssl.cc
similarity index 98%
rename from runtime/bin/secure_socket.cc
rename to runtime/bin/secure_socket_boringssl.cc
index a269134..6c4df2b 100644
--- a/runtime/bin/secure_socket.cc
+++ b/runtime/bin/secure_socket_boringssl.cc
@@ -2,13 +2,19 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+#include "platform/globals.h"
+#if defined(TARGET_OS_ANDROID) || \
+    defined(TARGET_OS_LINUX)   || \
+    defined(TARGET_OS_WINDOWS)
+
 #include "bin/secure_socket.h"
+#include "bin/secure_socket_boringssl.h"
 
 #include <errno.h>
 #include <fcntl.h>
-#include <sys/stat.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/stat.h>
 
 #include <openssl/bio.h>
 #include <openssl/err.h>
@@ -83,8 +89,7 @@
 /* Handle an error reported from the BoringSSL library. */
 static void ThrowIOException(int status,
                              const char* exception_type,
-                             const char* message,
-                             bool free_message = false) {
+                             const char* message) {
   char error_string[SSL_ERROR_MESSAGE_BUFFER_SIZE];
   FetchErrorString(error_string, SSL_ERROR_MESSAGE_BUFFER_SIZE);
   OSError os_error_struct(status, error_string, OSError::kBoringSSL);
@@ -92,9 +97,6 @@
   Dart_Handle exception =
       DartUtils::NewDartIOException(exception_type, message, os_error);
   ASSERT(!Dart_IsError(exception));
-  if (free_message) {
-    free(const_cast<char*>(message));
-  }
   Dart_ThrowException(exception);
   UNREACHABLE();
 }
@@ -677,7 +679,7 @@
                                              const char* password) {
   ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
   if (p12.get() == NULL) {
-    return NULL;
+    return 0;
   }
 
   EVP_PKEY* key = NULL;
@@ -764,6 +766,11 @@
 }
 
 
+void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) {
+  Dart_SetReturnValue(args, Dart_NewBoolean(true));
+}
+
+
 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)(
     Dart_NativeArguments args) {
   SSL_CTX* context = GetSecurityContext(args);
@@ -787,7 +794,7 @@
                                const char* password) {
   ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
   if (p12.get() == NULL) {
-    return NULL;
+    return 0;
   }
 
   EVP_PKEY* key = NULL;
@@ -1658,3 +1665,5 @@
 
 }  // namespace bin
 }  // namespace dart
+
+#endif  // defined(TARGET_OS_LINUX)
diff --git a/runtime/bin/secure_socket_boringssl.h b/runtime/bin/secure_socket_boringssl.h
new file mode 100644
index 0000000..9dbe250
--- /dev/null
+++ b/runtime/bin/secure_socket_boringssl.h
@@ -0,0 +1,133 @@
+// 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.
+
+#ifndef BIN_SECURE_SOCKET_BORINGSSL_H_
+#define BIN_SECURE_SOCKET_BORINGSSL_H_
+
+#if !defined(BIN_SECURE_SOCKET_H_)
+#error Do not include secure_socket_boringssl.h directly. Use secure_socket.h.
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+#include "bin/builtin.h"
+#include "bin/dartutils.h"
+#include "bin/socket.h"
+#include "bin/thread.h"
+#include "bin/utils.h"
+
+namespace dart {
+namespace bin {
+
+/* These are defined in root_certificates.cc. */
+extern const unsigned char* root_certificates_pem;
+extern unsigned int root_certificates_pem_length;
+
+/*
+ * SSLFilter encapsulates the NSS SSL(TLS) 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:
+  // These enums must agree with those in sdk/lib/io/secure_socket.dart.
+  enum BufferIndex {
+    kReadPlaintext,
+    kWritePlaintext,
+    kReadEncrypted,
+    kWriteEncrypted,
+    kNumBuffers,
+    kFirstEncrypted = kReadEncrypted
+  };
+
+  SSLFilter()
+      : callback_error(NULL),
+        ssl_(NULL),
+        socket_side_(NULL),
+        string_start_(NULL),
+        string_length_(NULL),
+        handshake_complete_(NULL),
+        bad_certificate_callback_(NULL),
+        in_handshake_(false),
+        hostname_(NULL) { }
+
+  ~SSLFilter();
+
+  Dart_Handle Init(Dart_Handle dart_this);
+  void Connect(const char* hostname,
+               SSL_CTX* context,
+               bool is_server,
+               bool request_client_certificate,
+               bool require_client_certificate,
+               Dart_Handle protocols_handle);
+  void Destroy();
+  void Handshake();
+  void GetSelectedProtocol(Dart_NativeArguments args);
+  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 bad_certificate_callback() {
+    return Dart_HandleFromPersistent(bad_certificate_callback_);
+  }
+  int ProcessReadPlaintextBuffer(int start, int end);
+  int ProcessWritePlaintextBuffer(int start, int end);
+  int ProcessReadEncryptedBuffer(int start, int end);
+  int ProcessWriteEncryptedBuffer(int start, int end);
+  bool ProcessAllBuffers(int starts[kNumBuffers],
+                         int ends[kNumBuffers],
+                         bool in_handshake);
+  Dart_Handle PeerCertificate();
+  static void InitializeLibrary();
+  Dart_Handle callback_error;
+
+  static CObject* ProcessFilterRequest(const CObjectArray& request);
+
+  // The index of the external data field in _ssl that points to the SSLFilter.
+  static int filter_ssl_index;
+
+  // TODO(whesse): make private:
+  SSL* ssl_;
+  BIO* socket_side_;
+
+ private:
+  static bool library_initialized_;
+  static Mutex* mutex_;  // To protect library initialization.
+
+  uint8_t* buffers_[kNumBuffers];
+  int buffer_size_;
+  int 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 is_server_;
+  char* hostname_;
+
+  static bool isBufferEncrypted(int i) {
+    return static_cast<BufferIndex>(i) >= kFirstEncrypted;
+  }
+  Dart_Handle InitializeBuffers(Dart_Handle dart_this);
+  void InitializePlatformData();
+
+  DISALLOW_COPY_AND_ASSIGN(SSLFilter);
+};
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // BIN_SECURE_SOCKET_BORINGSSL_H_
diff --git a/runtime/bin/secure_socket_macos.cc b/runtime/bin/secure_socket_macos.cc
new file mode 100644
index 0000000..53c9ae7
--- /dev/null
+++ b/runtime/bin/secure_socket_macos.cc
@@ -0,0 +1,2074 @@
+// 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 "platform/globals.h"
+#if defined(TARGET_OS_MACOS)
+
+#include "bin/secure_socket.h"
+#include "bin/secure_socket_macos.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/syslimits.h>
+#include <stdio.h>
+#include <string.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/log.h"
+#include "bin/socket.h"
+#include "bin/thread.h"
+#include "bin/utils.h"
+
+#include "platform/text_buffer.h"
+#include "platform/utils.h"
+
+#include "include/dart_api.h"
+
+// Return the error from the containing function if handle is an error handle.
+#define RETURN_IF_ERROR(handle)                                                \
+  {                                                                            \
+    Dart_Handle __handle = handle;                                             \
+    if (Dart_IsError((__handle))) {                                            \
+      return __handle;                                                         \
+    }                                                                          \
+  }
+
+// We need to access this private API function to create a SecIdentityRef
+// without writing a custom keychain to the filesystem. This is the approach
+// taken in WebKit:
+// https://webkit.googlesource.com/WebKit/+/master/Source/WebKit2/Shared/cf/ArgumentCodersCF.cpp
+extern "C" {
+SecIdentityRef SecIdentityCreate(CFAllocatorRef allocator,
+                                 SecCertificateRef certificate,
+                                 SecKeyRef private_key);
+}
+
+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:
+  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 const int kSSLFilterNativeFieldIndex = 0;
+static const int kSecurityContextNativeFieldIndex = 0;
+static const int kX509NativeFieldIndex = 0;
+
+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;
+
+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;
+}
+
+
+// Handle an error reported from the SecureTransport library.
+static void ThrowIOException(OSStatus status,
+                             const char* exception_type,
+                             const char* message) {
+  TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE);
+  CFStringRef error_string = SecCopyErrorMessageString(status, NULL);
+  if (error_string == NULL) {
+    status_message.Printf("OSStatus = %ld: https://www.osstatus.com",
+        static_cast<intptr_t>(status));
+  } else {
+    char* error = CFStringRefToCString(error_string);
+    status_message.Printf("OSStatus = %ld: %s",
+        static_cast<intptr_t>(status), error);
+    CFRelease(error_string);
+  }
+  OSError os_error_struct(status, status_message.buf(), OSError::kBoringSSL);
+  Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct);
+  Dart_Handle exception =
+      DartUtils::NewDartIOException(exception_type, message, os_error);
+  ASSERT(!Dart_IsError(exception));
+  Dart_ThrowException(exception);
+  UNREACHABLE();
+}
+
+
+static void CheckStatus(OSStatus status,
+                        const char* type,
+                        const char* message) {
+  if (status == noErr) {
+    return;
+  }
+  ThrowIOException(status, type, message);
+}
+
+
+static SSLFilter* GetFilter(Dart_NativeArguments args) {
+  SSLFilter* filter;
+  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+  ASSERT(Dart_IsInstance(dart_this));
+  ThrowIfError(Dart_GetNativeInstanceField(
+      dart_this,
+      kSSLFilterNativeFieldIndex,
+      reinterpret_cast<intptr_t*>(&filter)));
+  return filter;
+}
+
+
+static void DeleteFilter(void* isolate_data,
+                         Dart_WeakPersistentHandle handle,
+                         void* context_pointer) {
+  SSLFilter* filter = reinterpret_cast<SSLFilter*>(context_pointer);
+  delete filter;
+}
+
+
+static Dart_Handle SetFilter(Dart_NativeArguments args, SSLFilter* filter) {
+  ASSERT(filter != NULL);
+  const int approximate_size_of_filter = 1500;
+  Dart_Handle dart_this = Dart_GetNativeArgument(args, 0);
+  RETURN_IF_ERROR(dart_this);
+  ASSERT(Dart_IsInstance(dart_this));
+  Dart_Handle err = Dart_SetNativeInstanceField(
+      dart_this,
+      kSSLFilterNativeFieldIndex,
+      reinterpret_cast<intptr_t>(filter));
+  RETURN_IF_ERROR(err);
+  Dart_NewWeakPersistentHandle(dart_this,
+                               reinterpret_cast<void*>(filter),
+                               approximate_size_of_filter,
+                               DeleteFilter);
+  return Dart_Null();
+}
+
+
+static SSLCertContext* GetSecurityContext(Dart_NativeArguments args) {
+  SSLCertContext* context;
+  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+  ASSERT(Dart_IsInstance(dart_this));
+  ThrowIfError(Dart_GetNativeInstanceField(
+      dart_this,
+      kSecurityContextNativeFieldIndex,
+      reinterpret_cast<intptr_t*>(&context)));
+  return context;
+}
+
+
+static void DeleteCertContext(void* isolate_data,
+                              Dart_WeakPersistentHandle handle,
+                              void* context_pointer) {
+  SSLCertContext* context = static_cast<SSLCertContext*>(context_pointer);
+  delete context;
+}
+
+
+static Dart_Handle SetSecurityContext(Dart_NativeArguments args,
+                                      SSLCertContext* context) {
+  const int approximate_size_of_context = 1500;
+  Dart_Handle dart_this = Dart_GetNativeArgument(args, 0);
+  RETURN_IF_ERROR(dart_this);
+  ASSERT(Dart_IsInstance(dart_this));
+  Dart_Handle err = Dart_SetNativeInstanceField(
+      dart_this,
+      kSecurityContextNativeFieldIndex,
+      reinterpret_cast<intptr_t>(context));
+  RETURN_IF_ERROR(err);
+  Dart_NewWeakPersistentHandle(dart_this,
+                               context,
+                               approximate_size_of_context,
+                               DeleteCertContext);
+  return Dart_Null();
+}
+
+
+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) {
+  SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(context_pointer);
+  CFRelease(cert);
+}
+
+
+static Dart_Handle WrappedX509Certificate(SecCertificateRef certificate) {
+  const intptr_t approximate_size_of_certificate = 1500;
+  if (certificate == NULL) {
+    return Dart_Null();
+  }
+  Dart_Handle x509_type =
+      DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate");
+  if (Dart_IsError(x509_type)) {
+    return x509_type;
+  }
+  Dart_Handle arguments[] = { NULL };
+
+  Dart_Handle result =
+      Dart_New(x509_type, DartUtils::NewString("_"), 0, arguments);
+  if (Dart_IsError(result)) {
+    return result;
+  }
+  ASSERT(Dart_IsInstance(result));
+
+  // CFRetain in case the returned Dart object outlives the SecurityContext.
+  // CFRelease is in the Dart object's finalizer
+  CFRetain(certificate);
+  Dart_NewWeakPersistentHandle(result,
+                               reinterpret_cast<void*>(certificate),
+                               approximate_size_of_certificate,
+                               ReleaseCertificate);
+
+  Dart_Handle status = Dart_SetNativeInstanceField(
+      result,
+      kX509NativeFieldIndex,
+      reinterpret_cast<intptr_t>(certificate));
+  if (Dart_IsError(status)) {
+    return status;
+  }
+  return result;
+}
+
+
+// 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);
+};
+
+
+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 GetKeyAndCerts(CFArrayRef items,
+                               CFIndex items_length,
+                               CFArrayRef* out_certs,
+                               SecKeyRef* out_key) {
+  OSStatus status = noErr;
+
+  // Loop through the items, take only the first private key/identity, ignore
+  // any others, populate out_certs.
+  CFMutableArrayRef certs =
+      CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+  SecKeyRef key = NULL;
+
+  for (CFIndex i = 0; i < items_length; ++i) {
+    CFTypeRef item =
+        reinterpret_cast<CFTypeRef>(CFArrayGetValueAtIndex(items, i));
+    CFTypeID item_type = CFGetTypeID(item);
+    if (item_type == SecCertificateGetTypeID()) {
+      if (SSL_LOG_CERTS) {
+        Log::Print("\titem %ld: Certificate\n", i);
+      }
+      CFArrayAppendValue(certs, item);
+    } else if ((item_type == SecKeyGetTypeID()) && (key == NULL)) {
+      if (SSL_LOG_CERTS) {
+        Log::Print("\titem %ld: Key\n", i);
+      }
+      key = reinterpret_cast<SecKeyRef>(const_cast<void*>(item));
+      CFRetain(key);
+    } else if ((item_type == SecIdentityGetTypeID()) && (key == NULL)) {
+      if (SSL_LOG_CERTS) {
+        Log::Print("\titem %ld: Identity\n", i);
+      }
+      SecIdentityRef identity =
+          reinterpret_cast<SecIdentityRef>(const_cast<void*>(item));
+      SecCertificateRef cert = NULL;
+
+      status = SecIdentityCopyPrivateKey(identity, &key);
+      if (status != noErr) {
+        CFRelease(certs);
+        return status;
+      }
+
+      status = SecIdentityCopyCertificate(identity, &cert);
+      if (status != noErr) {
+        CFRelease(key);
+        CFRelease(certs);
+        return status;
+      }
+      CFArrayAppendValue(certs, cert);
+      CFRelease(cert);
+    }
+    // Other item types are ignored.
+  }
+
+  if (out_key == NULL) {
+    if (key != NULL) {
+      CFRelease(key);
+    }
+  } else {
+    *out_key = key;
+  }
+
+  if (out_certs == NULL) {
+    if (certs != NULL) {
+      CFRelease(certs);
+    }
+  } else {
+    *out_certs = certs;
+  }
+  return status;
+}
+
+
+static OSStatus TryPEMImport(CFDataRef cfdata,
+                             CFStringRef password,
+                             CFArrayRef* out_certs,
+                             SecKeyRef* out_key) {
+  OSStatus status = noErr;
+
+  SecExternalFormat format = kSecFormatPEMSequence;
+  SecExternalItemType sitem_type = kSecItemTypeAggregate;
+
+  SecItemImportExportKeyParameters params;
+  memset(&params, 0, sizeof(params));
+  params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
+  params.flags = kSecKeyNoAccessControl;
+  params.passphrase = password;
+
+  CFArrayRef items = NULL;
+  status = SecItemImport(
+      cfdata, NULL, &format, &sitem_type, 0, &params, NULL, &items);
+
+  if (status != noErr) {
+    if (SSL_LOG_CERTS) {
+      Log::Print("TrySecItemImport failed with: %ld, type = %d, format = %d\n",
+          static_cast<intptr_t>(status), sitem_type, format);
+    }
+    return status;
+  }
+
+  CFIndex items_length = (items == NULL) ? 0 : CFArrayGetCount(items);
+  if (SSL_LOG_CERTS) {
+    Log::Print(
+        "TrySecItemImport succeeded, type = %d, format = %d, count = %ld\n",
+        sitem_type, format, items_length);
+  }
+
+  // Empty list indicates a decoding failure of some sort.
+  if ((items != NULL) && (items_length == 0)) {
+    CFRelease(items);
+    return errSSLBadCert;
+  }
+
+  status = GetKeyAndCerts(items, items_length, out_certs, out_key);
+  CFRelease(items);
+  return status;
+}
+
+
+static char* TempKeychainPath() {
+  const char* exes = "keychaindir.XXXX";
+  const char* fname = "keychain";
+  const char* temp_dir = getenv("TMPDIR");
+  if (temp_dir == NULL) {
+    temp_dir = getenv("TMP");
+  }
+  if (temp_dir == NULL) {
+    temp_dir = "/tmp/";
+  }
+  ASSERT(temp_dir != NULL);
+
+  TextBuffer path(PATH_MAX);
+  path.Printf("%s/%s", temp_dir, exes);
+  char* ret = mkdtemp(path.buf());
+  ASSERT(ret != NULL);
+  path.Printf("/%s", fname);
+
+  char* result =
+      reinterpret_cast<char*>(Dart_ScopeAllocate(path.length() + 1));
+  return strncpy(result, path.buf(), path.length() + 1);
+}
+
+
+static OSStatus CreateKeychain(SecKeychainRef* keychain) {
+  ASSERT(keychain != NULL);
+  OSStatus status = noErr;
+  const char* temp_keychain_pwd = "dartdart";
+  char* temp_file_path = TempKeychainPath();
+  ASSERT(temp_file_path != NULL);
+  if (SSL_LOG_CERTS) {
+    Log::Print("Temporary keychain at: '%s'\n", temp_file_path);
+  }
+  status = SecKeychainCreate(temp_file_path,
+                             strlen(temp_keychain_pwd) + 1,
+                             reinterpret_cast<const void*>(temp_keychain_pwd),
+                             FALSE,  // Prompt user? Definitely no.
+                             NULL,  // Default access rights.
+                             keychain);
+  if (status != noErr) {
+    return status;
+  }
+  ASSERT(*keychain != NULL);
+  return status;
+}
+
+
+static OSStatus TryPKCS12Import(CFDataRef cfdata,
+                                CFStringRef password,
+                                CFArrayRef* out_certs,
+                                SecKeyRef* out_key,
+                                SecKeychainRef* out_keychain) {
+  OSStatus status = noErr;
+
+  SecExternalFormat format = kSecFormatPKCS12;
+  SecExternalItemType sitem_type = kSecItemTypeAggregate;
+
+  SecItemImportExportKeyParameters params;
+  memset(&params, 0, sizeof(params));
+  params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
+  params.flags = kSecKeyNoAccessControl;
+  params.passphrase = password;
+
+  CFArrayRef items = NULL;
+  if (SSL_LOG_CERTS) {
+    Log::Print("Trying PKCS12 import with: type = %d, format = %d\n",
+        sitem_type, format);
+  }
+
+  // The documentation for SecKeychainItemImport here:
+  //
+  // https://developer.apple.com/library/mac/documentation/Security/Reference/keychainservices/index.html
+  //
+  // states that when the SecKeychainRef argument is NULL, the CFArrayRef*
+  // argument will be populated by an array containing all keys, identities,
+  // and certificates from the data in the CFDataRef argument.
+  //
+  // Unfortunately, this is not true. The code to populate the CFArrayRef with
+  // keys and identities from PKCS12 data has been skipped and/or commented out,
+  // here:
+  //
+  // https://github.com/Apple-FOSS-Mirror/Security/blob/master/libsecurity_keychain/lib/SecImportExportAgg.cpp#L636
+  //
+  // as "floating" SecKeyRefs from the PKCS12 decoder haven't been implemented.
+  // That is, each private key instance coming from the PKCS12 decoder has to be
+  // associated with a keychain instance. Thus, as a workaround, we create a
+  // temporary keychain here if one is needed, and stash it below in a
+  // SecurityContext. This has the drawbacks:
+  // 1.) We need to make a temporary directory to hold the keychain file, and
+  // 2.) SecKeychainItemImport() probably does blocking IO to create and
+  //     manipulate the keychain file.
+  // So if the API is updated, this keychain should not be used.
+  SecKeychainRef keychain = NULL;
+  if (out_key != NULL) {
+    ASSERT(out_keychain != NULL);
+    status = CreateKeychain(&keychain);
+    if (status != noErr) {
+      return status;
+    }
+    *out_keychain = keychain;
+  }
+
+  status = SecItemImport(
+      cfdata, NULL, &format, &sitem_type, 0, &params, keychain, &items);
+  if (status != noErr) {
+    if (SSL_LOG_CERTS) {
+      Log::Print("TrySecItemImport failed with: %ld, it = %d, format = %d\n",
+          static_cast<intptr_t>(status), sitem_type, format);
+    }
+    return status;
+  }
+
+  CFIndex items_length = (items == NULL) ? 0 : CFArrayGetCount(items);
+  if (SSL_LOG_CERTS) {
+    Log::Print("TrySecItemImport 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;
+  }
+
+  status = GetKeyAndCerts(items, items_length, out_certs, out_key);
+  CFRelease(items);
+  return status;
+}
+
+
+static OSStatus ExtractSecItems(uint8_t* buffer,
+                                intptr_t length,
+                                const char* password,
+                                CFArrayRef* out_certs,
+                                SecKeyRef* out_key,
+                                SecKeychainRef* out_keychain) {
+  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 = TryPEMImport(cfdata, cfpassword, out_certs, out_key);
+  if (status != noErr) {
+    status =
+        TryPKCS12Import(cfdata, cfpassword, out_certs, out_key, out_keychain);
+  }
+
+  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;
+    Dart_PropagateError(err);
+  }
+  err = filter->Init(dart_this);
+  if (Dart_IsError(err)) {
+    // The finalizer was set up by SetFilter. It will delete `filter` if there
+    // is an error.
+    filter->Destroy();
+    Dart_PropagateError(err);
+  }
+}
+
+
+void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) {
+  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+  Dart_Handle host_name_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
+  Dart_Handle context_object = ThrowIfError(Dart_GetNativeArgument(args, 2));
+  bool is_server = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
+  bool request_client_certificate =
+      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4));
+  bool require_client_certificate =
+      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 5));
+
+  const char* host_name = NULL;
+  // TODO(whesse): Is truncating a Dart string containing \0 what we want?
+  ThrowIfError(Dart_StringToCString(host_name_object, &host_name));
+
+  SSLCertContext* context = NULL;
+  if (!Dart_IsNull(context_object)) {
+    ThrowIfError(Dart_GetNativeInstanceField(
+        context_object,
+        kSecurityContextNativeFieldIndex,
+        reinterpret_cast<intptr_t*>(&context)));
+  }
+
+  GetFilter(args)->Connect(dart_this,
+                           host_name,
+                           context,
+                           is_server,
+                           request_client_certificate,
+                           require_client_certificate);
+}
+
+
+void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) {
+  SSLFilter* filter = GetFilter(args);
+  // The SSLFilter is deleted in the finalizer for the Dart object created by
+  // SetFilter. There is no need to NULL-out the native field for the SSLFilter
+  // here because the SSLFilter won't be deleted until the finalizer for the
+  // Dart object runs while the Dart object is being GCd. This approach avoids a
+  // leak if Destroy isn't called, and avoids a NULL-dereference if Destroy is
+  // called more than once.
+  filter->Destroy();
+}
+
+
+void FUNCTION_NAME(SecureSocket_Handshake)(Dart_NativeArguments args) {
+  OSStatus status = GetFilter(args)->CheckHandshake();
+  CheckStatus(status, "HandshakeException", "Handshake error");
+}
+
+
+void FUNCTION_NAME(SecureSocket_GetSelectedProtocol)(
+    Dart_NativeArguments args) {
+  Dart_SetReturnValue(args, Dart_Null());
+}
+
+
+void FUNCTION_NAME(SecureSocket_Renegotiate)(Dart_NativeArguments args) {
+  bool use_session_cache =
+      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 1));
+  bool request_client_certificate =
+      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 2));
+  bool require_client_certificate =
+      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
+  GetFilter(args)->Renegotiate(use_session_cache,
+                               request_client_certificate,
+                               require_client_certificate);
+}
+
+
+void FUNCTION_NAME(SecureSocket_RegisterHandshakeCompleteCallback)(
+    Dart_NativeArguments args) {
+  Dart_Handle handshake_complete =
+      ThrowIfError(Dart_GetNativeArgument(args, 1));
+  if (!Dart_IsClosure(handshake_complete)) {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "Illegal argument to RegisterHandshakeCompleteCallback"));
+  }
+  GetFilter(args)->RegisterHandshakeCompleteCallback(handshake_complete);
+}
+
+
+void FUNCTION_NAME(SecureSocket_RegisterBadCertificateCallback)(
+    Dart_NativeArguments args) {
+  Dart_Handle callback =
+      ThrowIfError(Dart_GetNativeArgument(args, 1));
+  if (!Dart_IsClosure(callback) && !Dart_IsNull(callback)) {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "Illegal argument to RegisterBadCertificateCallback"));
+  }
+  GetFilter(args)->RegisterBadCertificateCallback(callback);
+}
+
+
+void FUNCTION_NAME(SecureSocket_PeerCertificate)
+    (Dart_NativeArguments args) {
+  Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate());
+}
+
+
+void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) {
+  intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args));
+  Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer));
+}
+
+
+void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) {
+  SSLCertContext* cert_context = new SSLCertContext();
+  // cert_context deleted in DeleteCertContext finalizer.
+  Dart_Handle err = SetSecurityContext(args, cert_context);
+  if (Dart_IsError(err)) {
+    delete cert_context;
+    Dart_PropagateError(err);
+  }
+}
+
+
+void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)(
+    Dart_NativeArguments args) {
+  SSLCertContext* context = GetSecurityContext(args);
+  const char* password = GetPasswordArgument(args, 2);
+
+  OSStatus status;
+  SecKeyRef key = NULL;
+  SecKeychainRef keychain = NULL;
+  {
+    ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+    status = ExtractSecItems(
+        buffer.get(), buffer.length(), password, NULL, &key, &keychain);
+  }
+
+  // Set the context fields. If there's a failure, release the items.
+  bool set_failure = false;
+  if ((key != NULL) && !context->set_private_key(key)) {
+    CFRelease(key);
+    SecKeychainDelete(keychain);
+    CFRelease(keychain);
+    set_failure = true;
+  }
+  if (!set_failure && (keychain != NULL) && !context->set_keychain(keychain)) {
+    SecKeychainDelete(keychain);
+    CFRelease(keychain);
+  }
+
+  if (set_failure) {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "usePrivateKeyBytes has already been called on the given context."));
+  }
+  CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes");
+}
+
+
+void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)(
+    Dart_NativeArguments args) {
+  SSLCertContext* context = GetSecurityContext(args);
+  const char* password = GetPasswordArgument(args, 2);
+
+  OSStatus status;
+  CFArrayRef certs = NULL;
+  {
+    ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+    status = ExtractSecItems(
+        buffer.get(), buffer.length(), password, &certs, NULL, NULL);
+  }
+
+  // Set the field in the context. If there's a failure, release the certs,
+  // and throw an exception.
+  if ((certs != NULL) && !context->set_trusted_certs(certs)) {
+    CFRelease(certs);
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "setTrustedCertificatesBytes has already been called "
+        "on the given context."));
+  }
+
+  CheckStatus(status, "TlsException", "Failure in setTrustedCertificatesBytes");
+}
+
+
+void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) {
+  Dart_SetReturnValue(args, Dart_NewBoolean(false));
+}
+
+
+void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)(
+    Dart_NativeArguments args) {
+  SSLCertContext* context = GetSecurityContext(args);
+  context->set_trust_builtin(true);
+}
+
+
+void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)(
+    Dart_NativeArguments args) {
+  SSLCertContext* context = GetSecurityContext(args);
+
+  const char* password = GetPasswordArgument(args, 2);
+  OSStatus status;
+  CFArrayRef certs = NULL;
+  {
+    ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+    status = ExtractSecItems(
+        buffer.get(), buffer.length(), password, &certs, NULL, NULL);
+  }
+
+  // Set the field in the context. If there's a failure, release the certs,
+  // and throw an exception.
+  if ((certs != NULL) && !context->set_cert_chain(certs)) {
+    CFRelease(certs);
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "useCertificateChainBytes has already been called "
+        "on the given context."));
+  }
+
+  CheckStatus(status, "TlsException", "Failure in useCertificateChainBytes");
+}
+
+
+void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)(
+    Dart_NativeArguments args) {
+  SSLCertContext* context = GetSecurityContext(args);
+  const char* password = GetPasswordArgument(args, 2);
+
+  OSStatus status;
+  CFArrayRef certs = NULL;
+  {
+    ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+    status = ExtractSecItems(
+        buffer.get(), buffer.length(), password, &certs, NULL, NULL);
+  }
+
+  // Set the field in the context. If there's a failure, release the certs,
+  // and throw an exception.
+  if ((certs != NULL) && !context->set_cert_authorities(certs)) {
+    CFRelease(certs);
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "setClientAuthoritiesBytes has already been called "
+        "on the given context."));
+  }
+
+  CheckStatus(status, "TlsException", "Failure in setClientAuthoritiesBytes");
+}
+
+
+void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)(
+    Dart_NativeArguments args) {
+  Dart_ThrowException(DartUtils::NewDartUnsupportedError(
+      "ALPN is not supported on this platform"));
+}
+
+
+static char* GetNameFromCert(SecCertificateRef certificate,
+                             CFTypeRef field,
+                             CFStringRef name) {
+  char* issuer_name = NULL;
+
+  CFTypeRef keys[] = { field };
+  CFArrayRef key_array = CFArrayCreate(NULL, keys, 1, &kCFTypeArrayCallBacks);
+  CFErrorRef error = NULL;
+  CFDictionaryRef cert_dict =
+      SecCertificateCopyValues(certificate, key_array, &error);
+  if (cert_dict == NULL) {
+    CFRelease(key_array);
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "X509.issuer failed to copy issuer field out of certificate"));
+  }
+
+  CFTypeRef item = CFDictionaryGetValue(cert_dict, keys[0]);
+  ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID());
+  CFDictionaryRef val_dict = reinterpret_cast<CFDictionaryRef>(item);
+
+  item = CFDictionaryGetValue(val_dict, kSecPropertyKeyValue);
+  ASSERT(CFGetTypeID(item) == CFArrayGetTypeID());
+  CFArrayRef val_array = reinterpret_cast<CFArrayRef>(item);
+
+  for (intptr_t i = 0; i < CFArrayGetCount(val_array); i++) {
+    item = CFArrayGetValueAtIndex(val_array, i);
+    ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID());
+    CFDictionaryRef val_dict2 = reinterpret_cast<CFDictionaryRef>(item);
+
+    item = CFDictionaryGetValue(val_dict2, kSecPropertyKeyLabel);
+    ASSERT(CFGetTypeID(item) == CFStringGetTypeID());
+    CFStringRef label = reinterpret_cast<CFStringRef>(item);
+
+    if (CFStringCompare(label, name, 0) == kCFCompareEqualTo) {
+      item = CFDictionaryGetValue(val_dict2, kSecPropertyKeyValue);
+      ASSERT(CFGetTypeID(item) == CFStringGetTypeID());
+      CFStringRef value = reinterpret_cast<CFStringRef>(item);
+      issuer_name = CFStringRefToCString(value);
+      break;
+    }
+  }
+
+  CFRelease(cert_dict);
+  CFRelease(key_array);
+  return issuer_name;
+}
+
+
+void FUNCTION_NAME(X509_Subject)(Dart_NativeArguments args) {
+  SecCertificateRef certificate = GetX509Certificate(args);
+  char* subject_name = GetNameFromCert(
+      certificate,
+      kSecOIDX509V1SubjectName,
+      reinterpret_cast<CFStringRef>(kSecOIDCommonName));
+  if (subject_name == NULL) {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "X509.subject failed to find issuer's common name."));
+  } else {
+    Dart_SetReturnValue(args, Dart_NewStringFromCString(subject_name));
+  }
+}
+
+
+void FUNCTION_NAME(X509_Issuer)(Dart_NativeArguments args) {
+  SecCertificateRef certificate = GetX509Certificate(args);
+  char* issuer_name = GetNameFromCert(
+      certificate,
+      kSecOIDX509V1IssuerName,
+      reinterpret_cast<CFStringRef>(kSecOIDCommonName));
+  if (issuer_name == NULL) {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "X509.issuer failed to find issuer's common name."));
+  } else {
+    Dart_SetReturnValue(args, Dart_NewStringFromCString(issuer_name));
+  }
+}
+
+
+// Returns the number of seconds since the epoch from 'field'.
+static int64_t GetTimeFromCert(SecCertificateRef certificate, CFTypeRef field) {
+  CFTypeRef keys[] = { field };
+  CFArrayRef key_array = CFArrayCreate(NULL, keys, 1, &kCFTypeArrayCallBacks);
+  CFErrorRef error = NULL;
+  CFDictionaryRef cert_dict =
+      SecCertificateCopyValues(certificate, key_array, &error);
+  if (cert_dict == NULL) {
+    CFRelease(key_array);
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "X509.startValidity: failed to copy issuer field out of certificate"));
+  }
+
+  CFTypeRef item = CFDictionaryGetValue(cert_dict, keys[0]);
+  ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID());
+  CFDictionaryRef val_dict = reinterpret_cast<CFDictionaryRef>(item);
+
+  item = CFDictionaryGetValue(val_dict, kSecPropertyKeyValue);
+  ASSERT(CFGetTypeID(item) == CFNumberGetTypeID());
+  CFNumberRef date_number = reinterpret_cast<CFNumberRef>(item);
+
+  CFAbsoluteTime date_abs_time;
+  CFNumberGetValue(date_number, kCFNumberDoubleType, &date_abs_time);
+  CFAbsoluteTime seconds_since_epoch =
+      date_abs_time + kCFAbsoluteTimeIntervalSince1970;
+  return static_cast<int64_t>(seconds_since_epoch) * 1000LL;
+}
+
+
+void FUNCTION_NAME(X509_StartValidity)(Dart_NativeArguments args) {
+  SecCertificateRef certificate = GetX509Certificate(args);
+  int64_t seconds_since_epoch = GetTimeFromCert(certificate,
+                                                kSecOIDX509V1ValidityNotBefore);
+  Dart_SetReturnValue(args,
+      Dart_NewInteger(static_cast<int64_t>(seconds_since_epoch) * 1000LL));
+}
+
+
+void FUNCTION_NAME(X509_EndValidity)(Dart_NativeArguments args) {
+  SecCertificateRef certificate = GetX509Certificate(args);
+  int64_t seconds_since_epoch = GetTimeFromCert(certificate,
+                                                kSecOIDX509V1ValidityNotAfter);
+  Dart_SetReturnValue(args,
+      Dart_NewInteger(static_cast<int64_t>(seconds_since_epoch) * 1000LL));
+}
+
+
+// Pushes data through the SSL filter, reading and writing from circular
+// buffers shared with Dart. Called from the IOService thread.
+//
+// The Dart _SecureFilterImpl class contains 4 ExternalByteArrays used to
+// pass encrypted and plaintext data to and from the C++ SSLFilter object.
+//
+// ProcessFilter is called with a CObject array containing the pointer to
+// the SSLFilter, encoded as an int, and the start and end positions of the
+// valid data in the four circular buffers.  The function only reads from
+// the valid data area of the input buffers, and only writes to the free
+// area of the output buffers.  The function returns the new start and end
+// positions in the buffers, but it only updates start for input buffers, and
+// end for output buffers.  Therefore, the Dart thread can simultaneously
+// write to the free space and end pointer of input buffers, and read from
+// the data space of output buffers, and modify the start pointer.
+//
+// When ProcessFilter returns, the Dart thread is responsible for combining
+// the updated pointers from Dart and C++, to make the new valid state of
+// the circular buffer.
+CObject* SSLFilter::ProcessFilterRequest(const CObjectArray& request) {
+  CObjectIntptr filter_object(request[0]);
+  SSLFilter* filter = reinterpret_cast<SSLFilter*>(filter_object.Value());
+  bool in_handshake = CObjectBool(request[1]).Value();
+  intptr_t starts[SSLFilter::kNumBuffers];
+  intptr_t ends[SSLFilter::kNumBuffers];
+  for (intptr_t i = 0; i < SSLFilter::kNumBuffers; ++i) {
+    starts[i] = CObjectInt32(request[2 * i + 2]).Value();
+    ends[i] = CObjectInt32(request[2 * i + 3]).Value();
+  }
+
+  OSStatus status = filter->ProcessAllBuffers(starts, ends, in_handshake);
+  if (status == noErr) {
+    CObjectArray* result = new CObjectArray(
+        CObject::NewArray(SSLFilter::kNumBuffers * 2));
+    for (intptr_t i = 0; i < SSLFilter::kNumBuffers; ++i) {
+      result->SetAt(2 * i, new CObjectInt32(CObject::NewInt32(starts[i])));
+      result->SetAt(2 * i + 1, new CObjectInt32(CObject::NewInt32(ends[i])));
+    }
+    return result;
+  } else {
+    TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE);
+    CFStringRef error_string = SecCopyErrorMessageString(status, NULL);
+    if (error_string == NULL) {
+      status_message.Printf("OSStatus = %ld: https://www.osstatus.com",
+          static_cast<intptr_t>(status));
+    } else {
+      char* error = CFStringRefToCString(error_string);
+      status_message.Printf("OSStatus = %ld: %s",
+          static_cast<intptr_t>(status), error);
+      CFRelease(error_string);
+    }
+    CObjectArray* result = new CObjectArray(CObject::NewArray(2));
+    result->SetAt(0, new CObjectInt32(CObject::NewInt32(status)));
+    result->SetAt(1, new CObjectString(CObject::NewString(
+        status_message.buf())));
+    return result;
+  }
+}
+
+
+// Usually buffer_starts_ and buffer_ends_ are populated by ProcessAllBuffers,
+// called from ProcessFilterRequest, called from the IOService thread.
+// However, the first call to SSLHandshake comes from the Dart thread, and so
+// doesn't go through there. This results in calls to SSLReadCallback and
+// SSLWriteCallback in which buffer_starts_ and buffer_ends_ haven't been set
+// up. In that case, since we're coming from Dart anyway, we can access the
+// fieds directly from the Dart objects.
+intptr_t SSLFilter::GetBufferStart(intptr_t idx) const {
+  if (buffer_starts_[idx] != NULL) {
+    return *buffer_starts_[idx];
+  }
+  Dart_Handle buffer_handle =
+      ThrowIfError(Dart_HandleFromPersistent(dart_buffer_objects_[idx]));
+  Dart_Handle start_handle =
+      ThrowIfError(Dart_GetField(buffer_handle, DartUtils::NewString("start")));
+  int64_t start = DartUtils::GetIntegerValue(start_handle);
+  return static_cast<intptr_t>(start);
+}
+
+
+intptr_t SSLFilter::GetBufferEnd(intptr_t idx) const {
+  if (buffer_ends_[idx] != NULL) {
+    return *buffer_ends_[idx];
+  }
+  Dart_Handle buffer_handle =
+      ThrowIfError(Dart_HandleFromPersistent(dart_buffer_objects_[idx]));
+  Dart_Handle end_handle =
+      ThrowIfError(Dart_GetField(buffer_handle, DartUtils::NewString("end")));
+  int64_t end = DartUtils::GetIntegerValue(end_handle);
+  return static_cast<intptr_t>(end);
+}
+
+
+void SSLFilter::SetBufferStart(intptr_t idx, intptr_t value) {
+  if (buffer_starts_[idx] != NULL) {
+    *buffer_starts_[idx] = value;
+    return;
+  }
+  Dart_Handle buffer_handle =
+      ThrowIfError(Dart_HandleFromPersistent(dart_buffer_objects_[idx]));
+  ThrowIfError(DartUtils::SetIntegerField(
+      buffer_handle, "start", static_cast<int64_t>(value)));
+}
+
+
+void SSLFilter::SetBufferEnd(intptr_t idx, intptr_t value) {
+  if (buffer_ends_[idx] != NULL) {
+    *buffer_ends_[idx] = value;
+    return;
+  }
+  Dart_Handle buffer_handle =
+      ThrowIfError(Dart_HandleFromPersistent(dart_buffer_objects_[idx]));
+  ThrowIfError(DartUtils::SetIntegerField(
+      buffer_handle, "end", static_cast<int64_t>(value)));
+}
+
+
+OSStatus SSLFilter::ProcessAllBuffers(intptr_t starts[kNumBuffers],
+                                      intptr_t ends[kNumBuffers],
+                                      bool in_handshake) {
+  for (intptr_t i = 0; i < kNumBuffers; ++i) {
+    buffer_starts_[i] = &starts[i];
+    buffer_ends_[i] = &ends[i];
+  }
+
+  if (in_handshake) {
+    OSStatus status = Handshake();
+    if (status != noErr) {
+      return status;
+    }
+  } else {
+    for (intptr_t i = 0; i < kNumBuffers; ++i) {
+      intptr_t start = starts[i];
+      intptr_t end = ends[i];
+      intptr_t size =
+          isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
+      if (start < 0 || end < 0 || start >= size || end >= size) {
+        FATAL("Out-of-bounds internal buffer access in dart:io SecureSocket");
+      }
+      switch (i) {
+        case kReadPlaintext:
+          // Write data to the circular buffer's free space.  If the buffer
+          // is full, neither if statement is executed and nothing happens.
+          if (start <= end) {
+            // If the free space may be split into two segments,
+            // then the first is [end, size), unless start == 0.
+            // Then, since the last free byte is at position start - 2,
+            // the interval is [end, size - 1).
+            intptr_t buffer_end = (start == 0) ? size - 1 : size;
+            intptr_t bytes = 0;
+            OSStatus status =
+                ProcessReadPlaintextBuffer(end, buffer_end, &bytes);
+            if ((status != noErr) && (status != errSSLWouldBlock)) {
+              return status;
+            }
+            end += bytes;
+            ASSERT(end <= size);
+            if (end == size) {
+              end = 0;
+            }
+          }
+          if (start > end + 1) {
+            intptr_t bytes = 0;
+            OSStatus status =
+                ProcessReadPlaintextBuffer(end, start - 1, &bytes);
+            if ((status != noErr) && (status != errSSLWouldBlock)) {
+              return status;
+            }
+            end += bytes;
+            ASSERT(end < start);
+          }
+          ends[i] = end;
+          break;
+        case kWritePlaintext:
+          // Read/Write data from circular buffer.  If the buffer is empty,
+          // neither if statement's condition is true.
+          if (end < start) {
+            // Data may be split into two segments.  In this case,
+            // the first is [start, size).
+            intptr_t bytes = 0;
+            OSStatus status = ProcessWritePlaintextBuffer(start, size, &bytes);
+            if ((status != noErr) && (status != errSSLWouldBlock)) {
+              return status;
+            }
+            start += bytes;
+            ASSERT(start <= size);
+            if (start == size) {
+              start = 0;
+            }
+          }
+          if (start < end) {
+            intptr_t bytes = 0;
+            OSStatus status = ProcessWritePlaintextBuffer(start, end, &bytes);
+            if ((status != noErr) && (status != errSSLWouldBlock)) {
+              return status;
+            }
+            start += bytes;
+            ASSERT(start <= end);
+          }
+          starts[i] = start;
+          break;
+        case kReadEncrypted:
+        case kWriteEncrypted:
+          // These buffers are advanced through SSLReadCallback and
+          // SSLWriteCallback, which are called from SSLRead, SSLWrite, and
+          // SSLHandshake.
+          break;
+        default:
+          UNREACHABLE();
+      }
+    }
+  }
+
+  for (intptr_t i = 0; i < kNumBuffers; ++i) {
+    buffer_starts_[i] = NULL;
+    buffer_ends_[i] = NULL;
+  }
+  return noErr;
+}
+
+
+Dart_Handle SSLFilter::Init(Dart_Handle dart_this) {
+  ASSERT(string_start_ == NULL);
+  string_start_ = Dart_NewPersistentHandle(DartUtils::NewString("start"));
+  ASSERT(string_start_ != NULL);
+  ASSERT(string_length_ == NULL);
+  string_length_ = Dart_NewPersistentHandle(DartUtils::NewString("length"));
+  ASSERT(string_length_ != NULL);
+  ASSERT(bad_certificate_callback_ == NULL);
+  bad_certificate_callback_ = Dart_NewPersistentHandle(Dart_Null());
+  ASSERT(bad_certificate_callback_ != NULL);
+
+  // Caller handles cleanup on an error.
+  return InitializeBuffers(dart_this);
+}
+
+
+Dart_Handle SSLFilter::InitializeBuffers(Dart_Handle dart_this) {
+  // Create SSLFilter buffers as ExternalUint8Array objects.
+  Dart_Handle buffers_string = DartUtils::NewString("buffers");
+  RETURN_IF_ERROR(buffers_string);
+  Dart_Handle dart_buffers_object = Dart_GetField(dart_this, buffers_string);
+  RETURN_IF_ERROR(dart_buffers_object);
+  Dart_Handle secure_filter_impl_type = Dart_InstanceGetType(dart_this);
+  RETURN_IF_ERROR(secure_filter_impl_type);
+  Dart_Handle size_string = DartUtils::NewString("SIZE");
+  RETURN_IF_ERROR(size_string);
+  Dart_Handle dart_buffer_size = Dart_GetField(
+      secure_filter_impl_type, size_string);
+  RETURN_IF_ERROR(dart_buffer_size);
+
+  int64_t buffer_size = 0;
+  Dart_Handle err = Dart_IntegerToInt64(dart_buffer_size, &buffer_size);
+  RETURN_IF_ERROR(err);
+
+  Dart_Handle encrypted_size_string = DartUtils::NewString("ENCRYPTED_SIZE");
+  RETURN_IF_ERROR(encrypted_size_string);
+
+  Dart_Handle dart_encrypted_buffer_size = Dart_GetField(
+      secure_filter_impl_type, encrypted_size_string);
+  RETURN_IF_ERROR(dart_encrypted_buffer_size);
+
+  int64_t encrypted_buffer_size = 0;
+  err = Dart_IntegerToInt64(dart_encrypted_buffer_size, &encrypted_buffer_size);
+  RETURN_IF_ERROR(err);
+
+  if (buffer_size <= 0 || buffer_size > 1 * MB) {
+    FATAL("Invalid buffer size in _ExternalBuffer");
+  }
+  if (encrypted_buffer_size <= 0 || encrypted_buffer_size > 1 * MB) {
+    FATAL("Invalid encrypted buffer size in _ExternalBuffer");
+  }
+  buffer_size_ = static_cast<intptr_t>(buffer_size);
+  encrypted_buffer_size_ = static_cast<intptr_t>(encrypted_buffer_size);
+
+  Dart_Handle data_identifier = DartUtils::NewString("data");
+  RETURN_IF_ERROR(data_identifier);
+
+  for (int i = 0; i < kNumBuffers; i++) {
+    int size = isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
+    buffers_[i] = new uint8_t[size];
+    ASSERT(buffers_[i] != NULL);
+    buffer_starts_[i] = NULL;
+    buffer_ends_[i] = NULL;
+    dart_buffer_objects_[i] = NULL;
+  }
+
+  Dart_Handle result = Dart_Null();
+  for (int i = 0; i < kNumBuffers; ++i) {
+    int size = isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
+    result = Dart_ListGetAt(dart_buffers_object, i);
+    if (Dart_IsError(result)) {
+      break;
+    }
+
+    dart_buffer_objects_[i] = Dart_NewPersistentHandle(result);
+    ASSERT(dart_buffer_objects_[i] != NULL);
+    Dart_Handle data =
+        Dart_NewExternalTypedData(Dart_TypedData_kUint8, buffers_[i], size);
+    if (Dart_IsError(data)) {
+      result = data;
+      break;
+    }
+    result = Dart_HandleFromPersistent(dart_buffer_objects_[i]);
+    if (Dart_IsError(result)) {
+      break;
+    }
+    result = Dart_SetField(result, data_identifier, data);
+    if (Dart_IsError(result)) {
+      break;
+    }
+  }
+
+  // Caller handles cleanup on an error.
+  return result;
+}
+
+
+void SSLFilter::RegisterHandshakeCompleteCallback(Dart_Handle complete) {
+  ASSERT(NULL == handshake_complete_);
+  handshake_complete_ = Dart_NewPersistentHandle(complete);
+  ASSERT(handshake_complete_ != NULL);
+}
+
+
+void SSLFilter::RegisterBadCertificateCallback(Dart_Handle callback) {
+  ASSERT(bad_certificate_callback_ != NULL);
+  Dart_DeletePersistentHandle(bad_certificate_callback_);
+  bad_certificate_callback_ = Dart_NewPersistentHandle(callback);
+  ASSERT(bad_certificate_callback_ != NULL);
+}
+
+
+Dart_Handle SSLFilter::PeerCertificate() {
+  if (peer_certs_ == NULL) {
+    return Dart_Null();
+  }
+
+  CFTypeRef item = CFArrayGetValueAtIndex(peer_certs_, 0);
+  ASSERT(CFGetTypeID(item) == SecCertificateGetTypeID());
+  SecCertificateRef cert =
+      reinterpret_cast<SecCertificateRef>(const_cast<void*>(item));
+  if (cert == NULL) {
+    return Dart_Null();
+  }
+
+  return WrappedX509Certificate(cert);
+}
+
+
+void SSLFilter::Connect(Dart_Handle dart_this,
+                        const char* hostname,
+                        SSLCertContext* context,
+                        bool is_server,
+                        bool request_client_certificate,
+                        bool require_client_certificate) {
+  if (in_handshake_) {
+    FATAL("Connect called twice on the same _SecureFilter.");
+  }
+
+  // Create the underlying context
+  SSLContextRef ssl_context = SSLCreateContext(
+      NULL, is_server ? kSSLServerSide : kSSLClientSide, kSSLStreamType);
+
+  // Configure the context.
+  OSStatus status;
+  status = SSLSetPeerDomainName(ssl_context, hostname, strlen(hostname));
+  CheckStatus(status,
+      "TlsException",
+      "Failed to set peer domain name");
+
+  status = SSLSetIOFuncs(
+      ssl_context, SSLFilter::SSLReadCallback, SSLFilter::SSLWriteCallback);
+  CheckStatus(status,
+      "TlsException",
+      "Failed to set IO Callbacks");
+
+  status = SSLSetConnection(
+      ssl_context, reinterpret_cast<SSLConnectionRef>(this));
+  CheckStatus(status,
+      "TlsException",
+      "Failed to set connection object");
+
+  // Always evaluate the certs manually so that we can cache the peer
+  // certificates in the context for calls to peerCertificate.
+  status = SSLSetSessionOption(
+      ssl_context, kSSLSessionOptionBreakOnServerAuth, true);
+  CheckStatus(status,
+      "TlsException",
+      "Failed to set BreakOnServerAuth option");
+
+  status = SSLSetProtocolVersionMin(ssl_context, kTLSProtocol1);
+  CheckStatus(status,
+      "TlsException",
+      "Failed to set minimum protocol version to kTLSProtocol1");
+
+  // If the context has a private key and certificate chain, combine the
+  // private key and first certificate into a SecIdentityRef, and place that
+  // and the remaining certs in an array to pass to SSLSetCertificate().
+  if ((context->private_key() != NULL) && (context->cert_chain() != NULL)) {
+    CFIndex chain_length = CFArrayGetCount(context->cert_chain());
+    CFMutableArrayRef certs =
+        CFArrayCreateMutable(NULL, chain_length, &kCFTypeArrayCallBacks);
+    CFTypeRef item = CFArrayGetValueAtIndex(context->cert_chain(), 0);
+    ASSERT(CFGetTypeID(item) == SecCertificateGetTypeID());
+    SecCertificateRef first_cert =
+        reinterpret_cast<SecCertificateRef>(const_cast<void*>(item));
+    SecIdentityRef identity =
+        SecIdentityCreate(NULL, first_cert, context->private_key());
+    CFArrayAppendValue(certs, identity);
+    for (CFIndex i = 0; i < chain_length; i++) {
+      CFArrayAppendValue(certs,
+                         CFArrayGetValueAtIndex(context->cert_chain(), i));
+    }
+    CFRelease(identity);
+    status = SSLSetCertificate(ssl_context, certs);
+    CFRelease(certs);
+    CheckStatus(status, "TlsException", "SSLSetCertificate failed");
+  }
+
+  if (context->cert_authorities() != NULL) {
+    status = SSLSetCertificateAuthorities(
+        ssl_context, context->cert_authorities(), true);
+    CheckStatus(status,
+        "TlsException",
+        "Failed to set certificate authorities");
+  }
+
+  if (is_server) {
+    SSLAuthenticate auth =
+        require_client_certificate
+        ? kAlwaysAuthenticate
+        : (request_client_certificate ? kTryAuthenticate : kNeverAuthenticate);
+    status = SSLSetClientSideAuthenticate(ssl_context, auth);
+    CheckStatus(status,
+        "TlsException",
+        "Failed to set client authentication mode");
+
+    // If we're at least trying client authentication, then break handshake
+    // for client authentication.
+    if (auth != kNeverAuthenticate) {
+      status = SSLSetSessionOption(
+          ssl_context, kSSLSessionOptionBreakOnClientAuth, true);
+      CheckStatus(status,
+          "TlsException",
+          "Failed to set client authentication mode");
+    }
+  }
+
+  // Add the contexts to our wrapper.
+  cert_context_ = context;
+  ssl_context_ = ssl_context;
+  is_server_ = is_server;
+
+  // Kick-off the handshake. Expect the handshake to need more data.
+  // SSLHandshake calls our SSLReadCallback and SSLWriteCallback.
+  status = SSLHandshake(ssl_context);
+  ASSERT(status != noErr);
+  if (status == errSSLWouldBlock) {
+    status = noErr;
+    in_handshake_ = true;
+  }
+  CheckStatus(status,
+     "HandshakeException",
+      is_server_ ? "Handshake error in server" : "Handshake error in client");
+}
+
+
+OSStatus SSLFilter::EvaluatePeerTrust() {
+  OSStatus status = noErr;
+
+  if (SSL_LOG_STATUS) {
+    Log::Print("Handshake evaluating trust.\n");
+  }
+  SecTrustRef peer_trust = NULL;
+  status = SSLCopyPeerTrust(ssl_context_, &peer_trust);
+  if (status != noErr) {
+    if (is_server_ && (status == errSSLBadCert)) {
+      // A client certificate was requested, but not required, and wasn't sent.
+      return noErr;
+    }
+    if (SSL_LOG_STATUS) {
+      Log::Print("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());
+  } else {
+    trusted_certs = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
+  }
+
+  status = SecTrustSetAnchorCertificates(peer_trust, trusted_certs);
+  if (status != noErr) {
+    if (SSL_LOG_STATUS) {
+      Log::Print("Handshake error from SecTrustSetAnchorCertificates: %ld\n",
+          static_cast<intptr_t>(status));
+    }
+    CFRelease(trusted_certs);
+    CFRelease(peer_trust);
+    return status;
+  }
+
+  if (SSL_LOG_STATUS) {
+    Log::Print("Handshake %s built in root certs\n",
+        cert_context_->trust_builtin() ? "trusting" : "not trusting");
+  }
+
+  status = SecTrustSetAnchorCertificatesOnly(
+      peer_trust, !cert_context_->trust_builtin());
+  if (status != noErr) {
+    CFRelease(trusted_certs);
+    CFRelease(peer_trust);
+    return status;
+  }
+
+  SecTrustResultType trust_result;
+  status = SecTrustEvaluate(peer_trust, &trust_result);
+  if (status != noErr) {
+    CFRelease(trusted_certs);
+    CFRelease(peer_trust);
+    return status;
+  }
+
+  // Grab the peer's certificate chain.
+  CFIndex peer_chain_length = SecTrustGetCertificateCount(peer_trust);
+  CFMutableArrayRef peer_certs =
+      CFArrayCreateMutable(NULL, peer_chain_length, &kCFTypeArrayCallBacks);
+  for (CFIndex i = 0; i < peer_chain_length; ++i) {
+    CFArrayAppendValue(peer_certs,
+                       SecTrustGetCertificateAtIndex(peer_trust, i));
+  }
+  peer_certs_ = peer_certs;
+
+  CFRelease(trusted_certs);
+  CFRelease(peer_trust);
+
+  if ((trust_result == kSecTrustResultProceed) ||
+      (trust_result == kSecTrustResultUnspecified)) {
+    // Trusted.
+    return noErr;
+  } else {
+    if (SSL_LOG_STATUS) {
+      Log::Print("Trust eval failed: trust_restul = %d\n", trust_result);
+    }
+    bad_cert_ = true;
+    return errSSLBadCert;
+  }
+}
+
+
+OSStatus SSLFilter::Handshake() {
+  ASSERT(cert_context_ != NULL);
+  ASSERT(ssl_context_ != NULL);
+  // Try and push handshake along.
+  if (SSL_LOG_STATUS) {
+    Log::Print("Doing SSLHandshake\n");
+  }
+  OSStatus status = SSLHandshake(ssl_context_);
+  if (SSL_LOG_STATUS) {
+    Log::Print("SSLHandshake returned %ld\n", static_cast<intptr_t>(status));
+  }
+
+  if ((status == errSSLServerAuthCompleted) ||
+      (status == errSSLClientAuthCompleted)) {
+    status = EvaluatePeerTrust();
+    if (status == errSSLBadCert) {
+      // Need to invoke the bad certificate callback.
+      return noErr;
+    } else if (status != noErr) {
+      return status;
+    }
+    // When trust evaluation succeeds, we can call SSLHandshake again
+    // immediately.
+    status = SSLHandshake(ssl_context_);
+  }
+
+  if (status == errSSLWouldBlock) {
+    in_handshake_ = true;
+    return noErr;
+  }
+
+  // Handshake succeeded.
+  if ((in_handshake_) && (status == noErr)) {
+    if (SSL_LOG_STATUS) {
+      Log::Print("Finished with the Handshake\n");
+    }
+    connected_ = true;
+  }
+  return status;
+}
+
+
+// Returns false if Handshake should fail, and true if Handshake should
+// proceed.
+Dart_Handle SSLFilter::InvokeBadCertCallback(SecCertificateRef peer_cert) {
+  Dart_Handle callback = bad_certificate_callback_;
+  if (Dart_IsNull(callback)) {
+    return callback;
+  }
+  Dart_Handle args[1];
+  args[0] = WrappedX509Certificate(peer_cert);
+  if (Dart_IsError(args[0])) {
+    return args[0];
+  }
+  Dart_Handle result = Dart_InvokeClosure(callback, 1, args);
+  if (!Dart_IsError(result) && !Dart_IsBoolean(result)) {
+    result = Dart_NewUnhandledExceptionError(DartUtils::NewDartIOException(
+        "HandshakeException",
+        "BadCertificateCallback returned a value that was not a boolean",
+        Dart_Null()));
+  }
+  return result;
+}
+
+
+OSStatus SSLFilter::CheckHandshake() {
+  if (bad_cert_ && in_handshake_) {
+    if (SSL_LOG_STATUS) {
+      Log::Print("Invoking bad certificate callback\n");
+    }
+    ASSERT(peer_certs_ != NULL);
+    CFIndex peer_certs_len = CFArrayGetCount(peer_certs_);
+    ASSERT(peer_certs_len > 0);
+    CFTypeRef item = CFArrayGetValueAtIndex(peer_certs_, peer_certs_len - 1);
+    ASSERT(item != NULL);
+    ASSERT(CFGetTypeID(item) == SecCertificateGetTypeID());
+    SecCertificateRef peer_cert =
+        reinterpret_cast<SecCertificateRef>(const_cast<void*>(item));
+    Dart_Handle result = InvokeBadCertCallback(peer_cert);
+    ThrowIfError(result);
+    if (Dart_IsNull(result)) {
+      return errSSLBadCert;
+    } else {
+      bool good_cert = DartUtils::GetBooleanValue(result);
+      bad_cert_ = !good_cert;
+      return good_cert ? noErr : errSSLBadCert;
+    }
+  }
+
+  if (connected_ && in_handshake_) {
+    if (SSL_LOG_STATUS) {
+      Log::Print("Invoking handshake complete callback\n");
+    }
+    ThrowIfError(Dart_InvokeClosure(
+        Dart_HandleFromPersistent(handshake_complete_), 0, NULL));
+    in_handshake_ = false;
+  }
+  return noErr;
+}
+
+
+void SSLFilter::Renegotiate(bool use_session_cache,
+                            bool request_client_certificate,
+                            bool require_client_certificate) {
+  // The SSL_REQUIRE_CERTIFICATE option only takes effect if the
+  // SSL_REQUEST_CERTIFICATE option is also set, so set it.
+  request_client_certificate =
+      request_client_certificate || require_client_certificate;
+  // TODO(24070, 24069): Implement setting the client certificate parameters,
+  //   and triggering rehandshake.
+}
+
+
+SSLFilter::~SSLFilter() {
+  // cert_context_ deleted by finalizer. Don't delete here.
+  cert_context_ = NULL;
+  if (ssl_context_ != NULL) {
+    CFRelease(ssl_context_);
+    ssl_context_ = NULL;
+  }
+  if (peer_certs_ != NULL) {
+    CFRelease(peer_certs_);
+    peer_certs_ = NULL;
+  }
+  if (hostname_ != NULL) {
+    free(hostname_);
+    hostname_ = NULL;
+  }
+  for (int i = 0; i < kNumBuffers; ++i) {
+    if (buffers_[i] != NULL) {
+      delete[] buffers_[i];
+      buffers_[i] = NULL;
+    }
+  }
+}
+
+
+void SSLFilter::Destroy() {
+  if (ssl_context_ != NULL) {
+    SSLClose(ssl_context_);
+  }
+  for (int i = 0; i < kNumBuffers; ++i) {
+    if (dart_buffer_objects_[i] != NULL) {
+      Dart_DeletePersistentHandle(dart_buffer_objects_[i]);
+      dart_buffer_objects_[i] = NULL;
+    }
+  }
+  if (string_start_ != NULL) {
+    Dart_DeletePersistentHandle(string_start_);
+    string_start_ = NULL;
+  }
+  if (string_length_ != NULL) {
+    Dart_DeletePersistentHandle(string_length_);
+    string_length_ = NULL;
+  }
+  if (handshake_complete_ != NULL) {
+    Dart_DeletePersistentHandle(handshake_complete_);
+    handshake_complete_ = NULL;
+  }
+  if (bad_certificate_callback_ != NULL) {
+    Dart_DeletePersistentHandle(bad_certificate_callback_);
+    bad_certificate_callback_ = NULL;
+  }
+}
+
+
+static intptr_t AvailableToRead(intptr_t start, intptr_t end, intptr_t size) {
+  intptr_t data_available = 0;
+  if (end < start) {
+    // Data may be split into two segments.  In this case,
+    // the first is [start, size).
+    intptr_t buffer_end = (start == 0) ? size - 1 : size;
+    intptr_t available = buffer_end - start;
+    start += available;
+    data_available += available;
+    ASSERT(start <= size);
+    if (start == size) {
+      start = 0;
+    }
+  }
+  if (start < end) {
+    intptr_t available = end - start;
+    start += available;
+    data_available += available;
+    ASSERT(start <= end);
+  }
+  return data_available;
+}
+
+
+OSStatus SSLFilter::SSLReadCallback(SSLConnectionRef connection,
+                                    void* data, size_t* data_requested) {
+  // Copy at most `data_requested` bytes from `buffers_[kReadEncrypted]` into
+  // `data`
+  ASSERT(connection != NULL);
+  ASSERT(data != NULL);
+  ASSERT(data_requested != NULL);
+
+  SSLFilter* filter =
+      const_cast<SSLFilter*>(reinterpret_cast<const SSLFilter*>(connection));
+  uint8_t* datap = reinterpret_cast<uint8_t*>(data);
+  uint8_t* buffer = filter->buffers_[kReadEncrypted];
+  intptr_t start = filter->GetBufferStart(kReadEncrypted);
+  intptr_t end = filter->GetBufferEnd(kReadEncrypted);
+  intptr_t size = filter->encrypted_buffer_size_;
+  intptr_t requested = static_cast<intptr_t>(*data_requested);
+  intptr_t data_read = 0;
+
+  if (AvailableToRead(start, end, size) < requested) {
+    *data_requested = 0;
+    return errSSLWouldBlock;
+  }
+
+  if (end < start) {
+    // Data may be split into two segments.  In this case,
+    // the first is [start, size).
+    intptr_t buffer_end = (start == 0) ? size - 1 : size;
+    intptr_t available = buffer_end - start;
+    intptr_t bytes = requested < available ? requested : available;
+    memmove(datap, &buffer[start], bytes);
+    start += bytes;
+    datap += bytes;
+    data_read += bytes;
+    requested -= bytes;
+    ASSERT(start <= size);
+    if (start == size) {
+      start = 0;
+    }
+  }
+  if ((requested > 0) && (start < end)) {
+    intptr_t available = end - start;
+    intptr_t bytes = requested < available ? requested : available;
+    memmove(datap, &buffer[start], bytes);
+    start += bytes;
+    datap += bytes;
+    data_read += bytes;
+    requested -= bytes;
+    ASSERT(start <= end);
+  }
+
+  if (SSL_LOG_DATA) {
+    Log::Print("SSLReadCallback: requested: %ld, read %ld bytes\n",
+        *data_requested, data_read);
+  }
+
+  filter->SetBufferStart(kReadEncrypted, start);
+  *data_requested = data_read;
+  return noErr;
+}
+
+
+// Read decrypted data from the filter to the circular buffer.
+OSStatus SSLFilter::ProcessReadPlaintextBuffer(intptr_t start,
+                                               intptr_t end,
+                                               intptr_t* bytes_processed) {
+  ASSERT(bytes_processed != NULL);
+  intptr_t length = end - start;
+  OSStatus status = noErr;
+  size_t bytes = 0;
+  if (length > 0) {
+    status = SSLRead(
+        ssl_context_,
+        reinterpret_cast<void*>((buffers_[kReadPlaintext] + start)),
+        length,
+        &bytes);
+    if ((status != noErr) && (status != errSSLWouldBlock)) {
+      *bytes_processed = 0;
+      return status;
+    }
+  }
+  if (SSL_LOG_DATA) {
+    Log::Print("ProcessReadPlaintextBuffer: requested: %ld, read %ld bytes\n",
+        length, bytes);
+  }
+  *bytes_processed = static_cast<intptr_t>(bytes);
+  return status;
+}
+
+
+intptr_t SpaceToWrite(intptr_t start, intptr_t end, intptr_t size) {
+  intptr_t writable_space = 0;
+
+  // is full, neither if statement is executed and nothing happens.
+  if (start <= end) {
+    // If the free space may be split into two segments,
+    // then the first is [end, size), unless start == 0.
+    // Then, since the last free byte is at position start - 2,
+    // the interval is [end, size - 1).
+    intptr_t buffer_end = (start == 0) ? size - 1 : size;
+    intptr_t available = buffer_end - end;
+    end += available;
+    writable_space += available;
+    ASSERT(end <= size);
+    if (end == size) {
+      end = 0;
+    }
+  }
+  if (start > end + 1) {
+    intptr_t available = (start - 1) - end;
+    end += available;
+    writable_space += available;
+    ASSERT(end < start);
+  }
+
+  return writable_space;
+}
+
+
+OSStatus SSLFilter::SSLWriteCallback(SSLConnectionRef connection,
+                                     const void* data, size_t* data_provided) {
+  // Copy at most `data_provided` bytes from data into
+  // `buffers_[kWriteEncrypted]`.
+  ASSERT(connection != NULL);
+  ASSERT(data != NULL);
+  ASSERT(data_provided != NULL);
+
+  SSLFilter* filter =
+    const_cast<SSLFilter*>(reinterpret_cast<const SSLFilter*>(connection));
+  const uint8_t* datap = reinterpret_cast<const uint8_t*>(data);
+  uint8_t* buffer = filter->buffers_[kWriteEncrypted];
+  intptr_t start = filter->GetBufferStart(kWriteEncrypted);
+  intptr_t end = filter->GetBufferEnd(kWriteEncrypted);
+  intptr_t size = filter->encrypted_buffer_size_;
+  intptr_t provided = static_cast<intptr_t>(*data_provided);
+  intptr_t data_written = 0;
+
+  if (SpaceToWrite(start, end, size) < provided) {
+    *data_provided = 0;
+    return errSSLWouldBlock;
+  }
+
+  // is full, neither if statement is executed and nothing happens.
+  if (start <= end) {
+    // If the free space may be split into two segments,
+    // then the first is [end, size), unless start == 0.
+    // Then, since the last free byte is at position start - 2,
+    // the interval is [end, size - 1).
+    intptr_t buffer_end = (start == 0) ? size - 1 : size;
+    intptr_t available = buffer_end - end;
+    intptr_t bytes = provided < available ? provided : available;
+    memmove(&buffer[end], datap, bytes);
+    end += bytes;
+    datap += bytes;
+    data_written += bytes;
+    provided -= bytes;
+    ASSERT(end <= size);
+    if (end == size) {
+      end = 0;
+    }
+  }
+  if ((provided > 0) && (start > end + 1)) {
+    intptr_t available = (start - 1) - end;
+    intptr_t bytes = provided < available ? provided : available;
+    memmove(&buffer[end], datap, bytes);
+    end += bytes;
+    datap += bytes;
+    data_written += bytes;
+    provided -= bytes;
+    ASSERT(end < start);
+  }
+
+  if (SSL_LOG_DATA) {
+    Log::Print("SSLWriteCallback: provided: %ld, written %ld bytes\n",
+        *data_provided, data_written);
+  }
+
+  filter->SetBufferEnd(kWriteEncrypted, end);
+  *data_provided = data_written;
+  return noErr;
+}
+
+
+OSStatus SSLFilter::ProcessWritePlaintextBuffer(intptr_t start,
+                                                intptr_t end,
+                                                intptr_t* bytes_processed) {
+  ASSERT(bytes_processed != NULL);
+  intptr_t length = end - start;
+  OSStatus status = noErr;
+  size_t bytes = 0;
+  if (length > 0) {
+    status = SSLWrite(
+        ssl_context_,
+        reinterpret_cast<void*>(buffers_[kWritePlaintext] + start),
+        length,
+        &bytes);
+    if ((status != noErr) && (status != errSSLWouldBlock)) {
+      *bytes_processed = 0;
+      return status;
+    }
+  }
+  *bytes_processed = static_cast<intptr_t>(bytes);
+  return status;
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_MACOS)
diff --git a/runtime/bin/secure_socket_macos.h b/runtime/bin/secure_socket_macos.h
new file mode 100644
index 0000000..e78321c
--- /dev/null
+++ b/runtime/bin/secure_socket_macos.h
@@ -0,0 +1,149 @@
+// 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_MACOS_H_
+#define BIN_SECURE_SOCKET_MACOS_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/socket.h"
+#include "bin/thread.h"
+#include "bin/utils.h"
+
+namespace dart {
+namespace bin {
+
+// Forward declaration of SSLContext.
+class 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:
+  // These enums must agree with those in sdk/lib/io/secure_socket.dart.
+  enum BufferIndex {
+    kReadPlaintext,
+    kWritePlaintext,
+    kReadEncrypted,
+    kWriteEncrypted,
+    kNumBuffers,
+    kFirstEncrypted = kReadEncrypted
+  };
+
+  SSLFilter()
+      : 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);
+
+  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_MACOS_H_
diff --git a/runtime/bin/secure_socket_patch.dart b/runtime/bin/secure_socket_patch.dart
index 455b132..c47c941 100644
--- a/runtime/bin/secure_socket_patch.dart
+++ b/runtime/bin/secure_socket_patch.dart
@@ -123,6 +123,10 @@
   /* patch */ static SecurityContext get defaultContext {
     return _SecurityContext.defaultContext;
   }
+
+  /* patch */ static bool get alpnSupported {
+    return _SecurityContext.alpnSupported;
+  }
 }
 
 class _SecurityContext
@@ -165,6 +169,8 @@
   void setClientAuthoritiesBytes(List<int> authCertBytes, {String password})
       native "SecurityContext_SetClientAuthoritiesBytes";
 
+  static bool get alpnSupported => _alpnSupported();
+  static bool _alpnSupported() native "SecurityContext_AlpnSupported";
   void setAlpnProtocols(List<String> protocols, bool isServer) {
     Uint8List encodedProtocols =
         SecurityContext._protocolsToLengthEncoding(protocols);
diff --git a/runtime/bin/secure_socket_unsupported.cc b/runtime/bin/secure_socket_unsupported.cc
index 91f4fc7..1cd09d0 100644
--- a/runtime/bin/secure_socket_unsupported.cc
+++ b/runtime/bin/secure_socket_unsupported.cc
@@ -7,7 +7,6 @@
 
 #include "include/dart_api.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -128,6 +127,11 @@
       "Secure Sockets unsupported on this platform"));
 }
 
+void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) {
+  Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Secure Sockets unsupported on this platform"));
+}
+
 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)(
     Dart_NativeArguments args) {
   Dart_ThrowException(DartUtils::NewDartArgumentError(
diff --git a/runtime/bin/snapshot_empty.cc b/runtime/bin/snapshot_empty.cc
index 4fd42b3..bab9212 100644
--- a/runtime/bin/snapshot_empty.cc
+++ b/runtime/bin/snapshot_empty.cc
@@ -13,7 +13,6 @@
 #endif
 #include <stddef.h>
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/snapshot_in.cc b/runtime/bin/snapshot_in.cc
index e2d67e9..769d96c 100644
--- a/runtime/bin/snapshot_in.cc
+++ b/runtime/bin/snapshot_in.cc
@@ -13,7 +13,6 @@
 #endif
 #include <stddef.h>
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc
index 87f39f6..cba96c0 100644
--- a/runtime/bin/socket.cc
+++ b/runtime/bin/socket.cc
@@ -2,12 +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.
 
+#include "bin/dartutils.h"
 #include "bin/io_buffer.h"
 #include "bin/isolate_data.h"
-#include "bin/dartutils.h"
+#include "bin/lockers.h"
 #include "bin/socket.h"
 #include "bin/thread.h"
-#include "bin/lockers.h"
 #include "bin/utils.h"
 
 #include "platform/globals.h"
@@ -60,7 +60,6 @@
     // There is already a socket listening on this port. We need to ensure
     // that if there is one also listening on the same address, it was created
     // with `shared = true`, ...
-
     OSSocket *os_socket = it->second;
     OSSocket *os_socket_same_addr = findOSSocketWithAddress(os_socket, addr);
 
@@ -146,7 +145,7 @@
         current = current->next;
       }
 
-      if (prev == NULL && current->next == NULL) {
+      if ((prev == NULL) && (current->next == NULL)) {
         // Remove last element from the list.
         sockets_by_port_.erase(os_socket->port);
       } else if (prev == NULL) {
@@ -271,7 +270,9 @@
     }
     uint8_t* buffer = NULL;
     Dart_Handle result = IOBuffer::Allocate(length, &buffer);
-    if (Dart_IsError(result)) Dart_PropagateError(result);
+    if (Dart_IsError(result)) {
+      Dart_PropagateError(result);
+    }
     ASSERT(buffer != NULL);
     intptr_t bytes_read = Socket::Read(socket, buffer, length);
     if (bytes_read == length) {
@@ -279,7 +280,9 @@
     } else if (bytes_read > 0) {
       uint8_t* new_buffer = NULL;
       Dart_Handle new_result = IOBuffer::Allocate(bytes_read, &new_buffer);
-      if (Dart_IsError(new_result)) Dart_PropagateError(new_result);
+      if (Dart_IsError(new_result)) {
+        Dart_PropagateError(new_result);
+      }
       ASSERT(new_buffer != NULL);
       memmove(new_buffer, buffer, bytes_read);
       Dart_SetReturnValue(args, new_result);
@@ -326,7 +329,9 @@
   ASSERT(bytes_read > 0);
   uint8_t* data_buffer = NULL;
   Dart_Handle data = IOBuffer::Allocate(bytes_read, &data_buffer);
-  if (Dart_IsError(data)) Dart_PropagateError(data);
+  if (Dart_IsError(data)) {
+    Dart_PropagateError(data);
+  }
   ASSERT(data_buffer != NULL);
   memmove(data_buffer, isolate_data->udp_receive_buffer, bytes_read);
 
@@ -347,14 +352,20 @@
   Dart_Handle dart_args[kNumArgs];
   dart_args[0] = data;
   dart_args[1] = Dart_NewStringFromCString(numeric_address);
-  if (Dart_IsError(dart_args[1])) Dart_PropagateError(dart_args[1]);
+  if (Dart_IsError(dart_args[1])) {
+    Dart_PropagateError(dart_args[1]);
+  }
   dart_args[2] = SocketAddress::ToTypedData(addr);
   dart_args[3] = Dart_NewInteger(port);
-  if (Dart_IsError(dart_args[3])) Dart_PropagateError(dart_args[3]);
+  if (Dart_IsError(dart_args[3])) {
+    Dart_PropagateError(dart_args[3]);
+  }
   // TODO(sgjesse): Cache the _makeDatagram function somewhere.
   Dart_Handle io_lib =
       Dart_LookupLibrary(DartUtils::NewString("dart:io"));
-  if (Dart_IsError(io_lib)) Dart_PropagateError(io_lib);
+  if (Dart_IsError(io_lib)) {
+    Dart_PropagateError(io_lib);
+  }
   Dart_Handle result =
       Dart_Invoke(io_lib,
                   DartUtils::NewString("_makeDatagram"),
@@ -376,7 +387,9 @@
       DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 3));
   bool short_write = false;
   if (short_socket_writes) {
-    if (length > 1) short_write = true;
+    if (length > 1) {
+      short_write = true;
+    }
     length = (length + 1) / 2;
   }
   Dart_TypedData_Type type;
@@ -384,7 +397,9 @@
   intptr_t len;
   Dart_Handle result = Dart_TypedDataAcquireData(
       buffer_obj, &type, reinterpret_cast<void**>(&buffer), &len);
-  if (Dart_IsError(result)) Dart_PropagateError(result);
+  if (Dart_IsError(result)) {
+    Dart_PropagateError(result);
+  }
   ASSERT((offset + length) <= len);
   buffer += offset;
   intptr_t bytes_written = Socket::Write(socket, buffer, length);
@@ -428,7 +443,9 @@
   intptr_t len;
   Dart_Handle result = Dart_TypedDataAcquireData(
       buffer_obj, &type, reinterpret_cast<void**>(&buffer), &len);
-  if (Dart_IsError(result)) Dart_PropagateError(result);
+  if (Dart_IsError(result)) {
+    Dart_PropagateError(result);
+  }
   ASSERT((offset + length) <= len);
   buffer += offset;
   intptr_t bytes_written = Socket::SendTo(socket, buffer, length, addr);
@@ -518,15 +535,13 @@
 
 
 void FUNCTION_NAME(Socket_GetSocketId)(Dart_NativeArguments args) {
-  intptr_t id =
-      Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0));
+  intptr_t id = Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0));
   Dart_SetReturnValue(args, Dart_NewInteger(id));
 }
 
 
 void FUNCTION_NAME(Socket_SetSocketId)(Dart_NativeArguments args) {
-  intptr_t id =
-      DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 1));
+  intptr_t id = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 1));
   Socket::SetSocketIdNativeField(Dart_GetNativeArgument(args, 0), id);
 }
 
@@ -569,7 +584,7 @@
 
 
 CObject* Socket::LookupRequest(const CObjectArray& request) {
-  if (request.Length() == 2 &&
+  if ((request.Length() == 2) &&
       request[0]->IsString() &&
       request[1]->IsInt32()) {
     CObjectString host(request[0]);
@@ -613,7 +628,7 @@
 
 
 CObject* Socket::ReverseLookupRequest(const CObjectArray& request) {
-  if (request.Length() == 1 &&
+  if ((request.Length() == 1) &&
       request[0]->IsTypedData()) {
     CObjectUint8Array addr_object(request[0]);
     RawAddr addr;
@@ -648,7 +663,7 @@
 
 
 CObject* Socket::ListInterfacesRequest(const CObjectArray& request) {
-  if (request.Length() == 1 &&
+  if ((request.Length() == 1) &&
       request[0]->IsInt32()) {
     CObjectInt32 type(request[0]);
     CObject* result = NULL;
@@ -841,7 +856,9 @@
 void Socket::SetSocketIdNativeField(Dart_Handle socket, intptr_t id) {
   Dart_Handle err =
       Dart_SetNativeInstanceField(socket, kSocketIdNativeField, id);
-  if (Dart_IsError(err)) Dart_PropagateError(err);
+  if (Dart_IsError(err)) {
+    Dart_PropagateError(err);
+  }
 }
 
 
@@ -849,7 +866,9 @@
   intptr_t socket = 0;
   Dart_Handle err =
       Dart_GetNativeInstanceField(socket_obj, kSocketIdNativeField, &socket);
-  if (Dart_IsError(err)) Dart_PropagateError(err);
+  if (Dart_IsError(err)) {
+    Dart_PropagateError(err);
+  }
   return socket;
 }
 
diff --git a/runtime/bin/socket.h b/runtime/bin/socket.h
index 559305c..b058a51 100644
--- a/runtime/bin/socket.h
+++ b/runtime/bin/socket.h
@@ -26,7 +26,6 @@
 #include "bin/thread.h"
 #include "bin/utils.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -59,7 +58,9 @@
   ~SocketAddress() {}
 
   int GetType() {
-    if (addr_.ss.ss_family == AF_INET6) return TYPE_IPV6;
+    if (addr_.ss.ss_family == AF_INET6) {
+      return TYPE_IPV6;
+    }
     return TYPE_IPV4;
   }
 
@@ -67,23 +68,27 @@
   const RawAddr& addr() const { return addr_; }
 
   static intptr_t GetAddrLength(const RawAddr& addr) {
-    ASSERT(addr.ss.ss_family == AF_INET || addr.ss.ss_family == AF_INET6);
-    return addr.ss.ss_family == AF_INET6 ?
+    ASSERT((addr.ss.ss_family == AF_INET) || (addr.ss.ss_family == AF_INET6));
+    return (addr.ss.ss_family == AF_INET6) ?
         sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
   }
 
   static intptr_t GetInAddrLength(const RawAddr& addr) {
-    ASSERT(addr.ss.ss_family == AF_INET || addr.ss.ss_family == AF_INET6);
-    return addr.ss.ss_family == AF_INET6 ?
+    ASSERT((addr.ss.ss_family == AF_INET) || (addr.ss.ss_family == AF_INET6));
+    return (addr.ss.ss_family == AF_INET6) ?
         sizeof(struct in6_addr) : sizeof(struct in_addr);
   }
 
   static bool AreAddressesEqual(const RawAddr& a, const RawAddr& b) {
     if (a.ss.ss_family == AF_INET) {
-      if (b.ss.ss_family != AF_INET) return false;
+      if (b.ss.ss_family != AF_INET) {
+        return false;
+      }
       return memcmp(&a.in.sin_addr, &b.in.sin_addr, sizeof(a.in.sin_addr)) == 0;
     } else if (a.ss.ss_family == AF_INET6) {
-      if (b.ss.ss_family != AF_INET6) return false;
+      if (b.ss.ss_family != AF_INET6) {
+        return false;
+      }
       return memcmp(&a.in6.sin6_addr,
                     &b.in6.sin6_addr,
                     sizeof(a.in6.sin6_addr)) == 0;
@@ -99,9 +104,11 @@
     intptr_t len;
     Dart_Handle result = Dart_TypedDataAcquireData(
         obj, &data_type, reinterpret_cast<void**>(&data), &len);
-    if (Dart_IsError(result)) Dart_PropagateError(result);
-    if (data_type != Dart_TypedData_kUint8 ||
-        (len != sizeof(in_addr) && len != sizeof(in6_addr))) {
+    if (Dart_IsError(result)) {
+      Dart_PropagateError(result);
+    }
+    if ((data_type != Dart_TypedData_kUint8) ||
+        ((len != sizeof(in_addr)) && (len != sizeof(in6_addr)))) {
       Dart_PropagateError(
           Dart_NewApiError("Unexpected type for socket address"));
     }
@@ -118,9 +125,13 @@
   }
 
   static int16_t FromType(int type) {
-    if (type == TYPE_ANY) return AF_UNSPEC;
-    if (type == TYPE_IPV4) return AF_INET;
-    ASSERT(type == TYPE_IPV6 && "Invalid type");
+    if (type == TYPE_ANY) {
+      return AF_UNSPEC;
+    }
+    if (type == TYPE_IPV4) {
+      return AF_INET;
+    }
+    ASSERT((type == TYPE_IPV6) && "Invalid type");
     return AF_INET6;
   }
 
@@ -143,7 +154,9 @@
   static Dart_Handle ToTypedData(const RawAddr& addr) {
     int len = GetInAddrLength(addr);
     Dart_Handle result = Dart_NewTypedData(Dart_TypedData_kUint8, len);
-    if (Dart_IsError(result)) Dart_PropagateError(result);
+    if (Dart_IsError(result)) {
+      Dart_PropagateError(result);
+    }
     Dart_Handle err;
     if (addr.addr.sa_family == AF_INET6) {
       err = Dart_ListSetAsBytes(
@@ -153,7 +166,9 @@
       err = Dart_ListSetAsBytes(
           result, 0, reinterpret_cast<const uint8_t*>(&addr.in.sin_addr), len);
     }
-    if (Dart_IsError(err)) Dart_PropagateError(err);
+    if (Dart_IsError(err)) {
+      Dart_PropagateError(err);
+    }
     return result;
   }
 
@@ -178,11 +193,12 @@
   DISALLOW_COPY_AND_ASSIGN(SocketAddress);
 };
 
+
 class InterfaceSocketAddress {
  public:
-  explicit InterfaceSocketAddress(struct sockaddr* sa,
-                                  const char* interface_name,
-                                  intptr_t interface_index)
+  InterfaceSocketAddress(struct sockaddr* sa,
+                         const char* interface_name,
+                         intptr_t interface_index)
       : socket_address_(new SocketAddress(sa)),
         interface_name_(interface_name),
         interface_index_(interface_index) {}
@@ -203,6 +219,7 @@
   DISALLOW_COPY_AND_ASSIGN(InterfaceSocketAddress);
 };
 
+
 template<typename T>
 class AddressList {
  public:
@@ -228,6 +245,7 @@
   DISALLOW_COPY_AND_ASSIGN(AddressList);
 };
 
+
 class Socket {
  public:
   enum SocketRequest {
@@ -340,6 +358,7 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(ServerSocket);
 };
 
+
 class ListeningSocketRegistry {
  private:
   struct OSSocket {
@@ -416,7 +435,6 @@
   DISALLOW_COPY_AND_ASSIGN(ListeningSocketRegistry);
 };
 
-
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/socket_android.cc b/runtime/bin/socket_android.cc
index da234f0..2d43a44 100644
--- a/runtime/bin/socket_android.cc
+++ b/runtime/bin/socket_android.cc
@@ -9,12 +9,12 @@
 #include "bin/socket_android.h"
 
 #include <errno.h>  // NOLINT
+#include <netinet/tcp.h>  // NOLINT
 #include <stdio.h>  // NOLINT
 #include <stdlib.h>  // NOLINT
 #include <string.h>  // NOLINT
 #include <sys/stat.h>  // NOLINT
 #include <unistd.h>  // NOLINT
-#include <netinet/tcp.h>  // NOLINT
 
 #include "bin/fdutils.h"
 #include "bin/file.h"
@@ -36,16 +36,8 @@
 
 bool Socket::FormatNumericAddress(const RawAddr& addr, char* address, int len) {
   socklen_t salen = SocketAddress::GetAddrLength(addr);
-  if (NO_RETRY_EXPECTED(getnameinfo(&addr.addr,
-                                    salen,
-                                    address,
-                                    len,
-                                    NULL,
-                                    0,
-                                    NI_NUMERICHOST)) != 0) {
-    return false;
-  }
-  return true;
+  return (NO_RETRY_EXPECTED(getnameinfo(
+      &addr.addr, salen, address, len, NULL, 0, NI_NUMERICHOST)) == 0);
 }
 
 
@@ -69,7 +61,7 @@
 static intptr_t Connect(intptr_t fd, const RawAddr& addr) {
   intptr_t result = TEMP_FAILURE_RETRY(
       connect(fd, &addr.addr, SocketAddress::GetAddrLength(addr)));
-  if (result == 0 || errno == EINPROGRESS) {
+  if ((result == 0) || (errno == EINPROGRESS)) {
     return fd;
   }
   VOID_TEMP_FAILURE_RETRY(close(fd));
@@ -98,7 +90,7 @@
 
   intptr_t result = TEMP_FAILURE_RETRY(
       bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr)));
-  if (result != 0 && errno != EINPROGRESS) {
+  if ((result != 0) && (errno != EINPROGRESS)) {
     VOID_TEMP_FAILURE_RETRY(close(fd));
     return -1;
   }
@@ -116,7 +108,7 @@
   ASSERT(fd >= 0);
   ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
   ASSERT(EAGAIN == EWOULDBLOCK);
-  if (read_bytes == -1 && errno == EWOULDBLOCK) {
+  if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
     // If the read would block we need to retry and therefore return 0
     // as the number of bytes written.
     read_bytes = 0;
@@ -131,7 +123,7 @@
   socklen_t addr_len = sizeof(addr->ss);
   ssize_t read_bytes = TEMP_FAILURE_RETRY(
       recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len));
-  if (read_bytes == -1 && errno == EWOULDBLOCK) {
+  if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
     // If the read would block we need to retry and therefore return 0
     // as the number of bytes written.
     read_bytes = 0;
@@ -144,7 +136,7 @@
   ASSERT(fd >= 0);
   ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
   ASSERT(EAGAIN == EWOULDBLOCK);
-  if (written_bytes == -1 && errno == EWOULDBLOCK) {
+  if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
     // If the would block we need to retry and therefore return 0 as
     // the number of bytes written.
     written_bytes = 0;
@@ -160,7 +152,7 @@
       sendto(fd, buffer, num_bytes, 0,
              &addr.addr, SocketAddress::GetAddrLength(addr)));
   ASSERT(EAGAIN == EWOULDBLOCK);
-  if (written_bytes == -1 && errno == EWOULDBLOCK) {
+  if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
     // If the would block we need to retry and therefore return 0 as
     // the number of bytes written.
     written_bytes = 0;
@@ -207,10 +199,18 @@
 int Socket::GetType(intptr_t fd) {
   struct stat buf;
   int result = fstat(fd, &buf);
-  if (result == -1) return -1;
-  if (S_ISCHR(buf.st_mode)) return File::kTerminal;
-  if (S_ISFIFO(buf.st_mode)) return File::kPipe;
-  if (S_ISREG(buf.st_mode)) return File::kFile;
+  if (result == -1) {
+    return -1;
+  }
+  if (S_ISCHR(buf.st_mode)) {
+    return File::kTerminal;
+  }
+  if (S_ISFIFO(buf.st_mode)) {
+    return File::kPipe;
+  }
+  if (S_ISREG(buf.st_mode)) {
+    return File::kFile;
+  }
   return File::kOther;
 }
 
@@ -247,12 +247,14 @@
   }
   intptr_t count = 0;
   for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
-    if (c->ai_family == AF_INET || c->ai_family == AF_INET6) count++;
+    if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
+      count++;
+    }
   }
   intptr_t i = 0;
   AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
   for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
-    if (c->ai_family == AF_INET || c->ai_family == AF_INET6) {
+    if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
       addresses->SetAt(i, new SocketAddress(c->ai_addr));
       i++;
     }
@@ -294,7 +296,7 @@
     ASSERT(type == SocketAddress::TYPE_IPV6);
     result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr);
   }
-  return result == 1;
+  return (result == 1);
 }
 
 
@@ -302,7 +304,9 @@
   intptr_t fd;
 
   fd = NO_RETRY_EXPECTED(socket(addr.addr.sa_family, SOCK_DGRAM, IPPROTO_UDP));
-  if (fd < 0) return -1;
+  if (fd < 0) {
+    return -1;
+  }
 
   FDUtils::SetCloseOnExec(fd);
 
@@ -340,7 +344,9 @@
   intptr_t fd;
 
   fd = NO_RETRY_EXPECTED(socket(addr.ss.ss_family, SOCK_STREAM, 0));
-  if (fd < 0) return -1;
+  if (fd < 0) {
+    return -1;
+  }
 
   FDUtils::SetCloseOnExec(fd);
 
@@ -363,7 +369,8 @@
   }
 
   // Test for invalid socket port 65535 (some browsers disallow it).
-  if (SocketAddress::GetAddrPort(addr) == 0 && Socket::GetPort(fd) == 65535) {
+  if ((SocketAddress::GetAddrPort(addr)) == 0 &&
+      (Socket::GetPort(fd) == 65535)) {
     // Don't close the socket until we have created a new socket, ensuring
     // that we do not get the bad port number again.
     intptr_t new_fd = CreateBindListen(addr, backlog, v6_only);
@@ -435,9 +442,9 @@
                                          reinterpret_cast<void *>(&on),
                                          &len));
   if (err == 0) {
-    *enabled = on == 1;
+    *enabled = (on == 1);
   }
-  return err == 0;
+  return (err == 0);
 }
 
 
@@ -521,9 +528,9 @@
                                          reinterpret_cast<char *>(&on),
                                          &len));
   if (err == 0) {
-    *enabled = on == 1;
+    *enabled = (on == 1);
   }
-  return err == 0;
+  return (err == 0);
 }
 
 
@@ -539,7 +546,7 @@
 
 bool Socket::JoinMulticast(
     intptr_t fd, const RawAddr& addr, const RawAddr&, int interfaceIndex) {
-  int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
+  int proto = (addr.addr.sa_family == AF_INET) ? IPPROTO_IP : IPPROTO_IPV6;
   struct group_req mreq;
   mreq.gr_interface = interfaceIndex;
   memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr));
@@ -550,7 +557,7 @@
 
 bool Socket::LeaveMulticast(
     intptr_t fd, const RawAddr& addr, const RawAddr&, int interfaceIndex) {
-  int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
+  int proto = (addr.addr.sa_family == AF_INET) ? IPPROTO_IP : IPPROTO_IPV6;
   struct group_req mreq;
   mreq.gr_interface = interfaceIndex;
   memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr));
diff --git a/runtime/bin/socket_linux.cc b/runtime/bin/socket_linux.cc
index 575da3b..b9068d7 100644
--- a/runtime/bin/socket_linux.cc
+++ b/runtime/bin/socket_linux.cc
@@ -9,14 +9,14 @@
 #include "bin/socket_linux.h"
 
 #include <errno.h>  // NOLINT
+#include <ifaddrs.h>  // NOLINT
+#include <net/if.h>  // NOLINT
+#include <netinet/tcp.h>  // NOLINT
 #include <stdio.h>  // NOLINT
 #include <stdlib.h>  // NOLINT
 #include <string.h>  // NOLINT
 #include <sys/stat.h>  // NOLINT
 #include <unistd.h>  // NOLINT
-#include <net/if.h>  // NOLINT
-#include <netinet/tcp.h>  // NOLINT
-#include <ifaddrs.h>  // NOLINT
 
 #include "bin/fdutils.h"
 #include "bin/file.h"
@@ -39,11 +39,8 @@
 
 bool Socket::FormatNumericAddress(const RawAddr& addr, char* address, int len) {
   socklen_t salen = SocketAddress::GetAddrLength(addr);
-  if (NO_RETRY_EXPECTED(getnameinfo(
-        &addr.addr, salen, address, len, NULL, 0, NI_NUMERICHOST) != 0)) {
-    return false;
-  }
-  return true;
+  return (NO_RETRY_EXPECTED(getnameinfo(
+      &addr.addr, salen, address, len, NULL, 0, NI_NUMERICHOST) == 0));
 }
 
 
@@ -67,7 +64,7 @@
 static intptr_t Connect(intptr_t fd, const RawAddr& addr) {
   intptr_t result = TEMP_FAILURE_RETRY(
       connect(fd, &addr.addr, SocketAddress::GetAddrLength(addr)));
-  if (result == 0 || errno == EINPROGRESS) {
+  if ((result == 0) || (errno == EINPROGRESS)) {
     return fd;
   }
   VOID_TEMP_FAILURE_RETRY(close(fd));
@@ -93,7 +90,7 @@
 
   intptr_t result = TEMP_FAILURE_RETRY(
       bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr)));
-  if (result != 0 && errno != EINPROGRESS) {
+  if ((result != 0) && (errno != EINPROGRESS)) {
     VOID_TEMP_FAILURE_RETRY(close(fd));
     return -1;
   }
@@ -111,7 +108,7 @@
   ASSERT(fd >= 0);
   ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
   ASSERT(EAGAIN == EWOULDBLOCK);
-  if (read_bytes == -1 && errno == EWOULDBLOCK) {
+  if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
     // If the read would block we need to retry and therefore return 0
     // as the number of bytes written.
     read_bytes = 0;
@@ -126,7 +123,7 @@
   socklen_t addr_len = sizeof(addr->ss);
   ssize_t read_bytes = TEMP_FAILURE_RETRY(
       recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len));
-  if (read_bytes == -1 && errno == EWOULDBLOCK) {
+  if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
     // If the read would block we need to retry and therefore return 0
     // as the number of bytes written.
     read_bytes = 0;
@@ -139,7 +136,7 @@
   ASSERT(fd >= 0);
   ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
   ASSERT(EAGAIN == EWOULDBLOCK);
-  if (written_bytes == -1 && errno == EWOULDBLOCK) {
+  if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
     // If the would block we need to retry and therefore return 0 as
     // the number of bytes written.
     written_bytes = 0;
@@ -155,7 +152,7 @@
       sendto(fd, buffer, num_bytes, 0,
              &addr.addr, SocketAddress::GetAddrLength(addr)));
   ASSERT(EAGAIN == EWOULDBLOCK);
-  if (written_bytes == -1 && errno == EWOULDBLOCK) {
+  if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
     // If the would block we need to retry and therefore return 0 as
     // the number of bytes written.
     written_bytes = 0;
@@ -200,10 +197,18 @@
 int Socket::GetType(intptr_t fd) {
   struct stat64 buf;
   int result = TEMP_FAILURE_RETRY(fstat64(fd, &buf));
-  if (result == -1) return -1;
-  if (S_ISCHR(buf.st_mode)) return File::kTerminal;
-  if (S_ISFIFO(buf.st_mode)) return File::kPipe;
-  if (S_ISREG(buf.st_mode)) return File::kFile;
+  if (result == -1) {
+    return -1;
+  }
+  if (S_ISCHR(buf.st_mode)) {
+    return File::kTerminal;
+  }
+  if (S_ISFIFO(buf.st_mode)) {
+    return File::kPipe;
+  }
+  if (S_ISREG(buf.st_mode)) {
+    return File::kFile;
+  }
   return File::kOther;
 }
 
@@ -240,12 +245,14 @@
   }
   intptr_t count = 0;
   for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
-    if (c->ai_family == AF_INET || c->ai_family == AF_INET6) count++;
+    if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
+      count++;
+    }
   }
   intptr_t i = 0;
   AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
   for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
-    if (c->ai_family == AF_INET || c->ai_family == AF_INET6) {
+    if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
       addresses->SetAt(i, new SocketAddress(c->ai_addr));
       i++;
     }
@@ -288,7 +295,7 @@
     result = NO_RETRY_EXPECTED(
         inet_pton(AF_INET6, address, &addr->in6.sin6_addr));
   }
-  return result == 1;
+  return (result == 1);
 }
 
 
@@ -298,7 +305,9 @@
   fd = NO_RETRY_EXPECTED(socket(addr.addr.sa_family,
                          SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
                          IPPROTO_UDP));
-  if (fd < 0) return -1;
+  if (fd < 0) {
+    return -1;
+  }
 
   if (reuseAddress) {
     int optval = 1;
@@ -321,12 +330,9 @@
     return false;
   }
   int family = ifa->ifa_addr->sa_family;
-  if (lookup_family == family) return true;
-  if (lookup_family == AF_UNSPEC &&
-      (family == AF_INET || family == AF_INET6)) {
-    return true;
-  }
-  return false;
+  return ((lookup_family == family) ||
+         (((lookup_family == AF_UNSPEC) &&
+          ((family == AF_INET) || (family == AF_INET6)))));
 }
 
 
@@ -348,7 +354,9 @@
 
   intptr_t count = 0;
   for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
-    if (ShouldIncludeIfaAddrs(ifa, lookup_family)) count++;
+    if (ShouldIncludeIfaAddrs(ifa, lookup_family)) {
+      count++;
+    }
   }
 
   AddressList<InterfaceSocketAddress>* addresses =
@@ -374,7 +382,9 @@
 
   fd = NO_RETRY_EXPECTED(
       socket(addr.ss.ss_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
-  if (fd < 0) return -1;
+  if (fd < 0) {
+    return -1;
+  }
 
   int optval = 1;
   VOID_NO_RETRY_EXPECTED(
@@ -393,7 +403,8 @@
   }
 
   // Test for invalid socket port 65535 (some browsers disallow it).
-  if (SocketAddress::GetAddrPort(addr) == 0 && Socket::GetPort(fd) == 65535) {
+  if ((SocketAddress::GetAddrPort(addr) == 0) &&
+      (Socket::GetPort(fd) == 65535)) {
     // Don't close the socket until we have created a new socket, ensuring
     // that we do not get the bad port number again.
     intptr_t new_fd = CreateBindListen(addr, backlog, v6_only);
@@ -461,9 +472,9 @@
   int err = NO_RETRY_EXPECTED(getsockopt(
       fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<void *>(&on), &len));
   if (err == 0) {
-    *enabled = on == 1;
+    *enabled = (on == 1);
   }
-  return err == 0;
+  return (err == 0);
 }
 
 
@@ -533,9 +544,9 @@
   int err = NO_RETRY_EXPECTED(getsockopt(
       fd, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char *>(&on), &len));
   if (err == 0) {
-    *enabled = on == 1;
+    *enabled = (on == 1);
   }
-  return err == 0;
+  return (err == 0);
 }
 
 
diff --git a/runtime/bin/socket_macos.cc b/runtime/bin/socket_macos.cc
index 22613d5..8306b56 100644
--- a/runtime/bin/socket_macos.cc
+++ b/runtime/bin/socket_macos.cc
@@ -9,14 +9,14 @@
 #include "bin/socket_macos.h"
 
 #include <errno.h>  // NOLINT
+#include <ifaddrs.h>  // NOLINT
+#include <net/if.h>  // NOLINT
+#include <netinet/tcp.h>  // NOLINT
 #include <stdio.h>  // NOLINT
 #include <stdlib.h>  // NOLINT
 #include <string.h>  // NOLINT
 #include <sys/stat.h>  // NOLINT
 #include <unistd.h>  // NOLINT
-#include <net/if.h>  // NOLINT
-#include <netinet/tcp.h>  // NOLINT
-#include <ifaddrs.h>  // NOLINT
 
 #include "bin/fdutils.h"
 #include "bin/file.h"
@@ -38,16 +38,8 @@
 
 bool Socket::FormatNumericAddress(const RawAddr& addr, char* address, int len) {
   socklen_t salen = SocketAddress::GetAddrLength(addr);
-  if (NO_RETRY_EXPECTED(getnameinfo(&addr.addr,
-                                    salen,
-                                    address,
-                                    len,
-                                    NULL,
-                                    0,
-                                    NI_NUMERICHOST)) != 0) {
-    return false;
-  }
-  return true;
+  return (NO_RETRY_EXPECTED(getnameinfo(
+      &addr.addr, salen, address, len, NULL, 0, NI_NUMERICHOST)) == 0);
 }
 
 
@@ -71,7 +63,7 @@
 static intptr_t Connect(intptr_t fd, const RawAddr& addr) {
   intptr_t result = TEMP_FAILURE_RETRY(
       connect(fd, &addr.addr, SocketAddress::GetAddrLength(addr)));
-  if (result == 0 || errno == EINPROGRESS) {
+  if ((result == 0) || (errno == EINPROGRESS)) {
     return fd;
   }
   VOID_TEMP_FAILURE_RETRY(close(fd));
@@ -100,7 +92,7 @@
 
   intptr_t result = TEMP_FAILURE_RETRY(
       bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr)));
-  if (result != 0 && errno != EINPROGRESS) {
+  if ((result != 0) && (errno != EINPROGRESS)) {
     VOID_TEMP_FAILURE_RETRY(close(fd));
     return -1;
   }
@@ -118,7 +110,7 @@
   ASSERT(fd >= 0);
   ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
   ASSERT(EAGAIN == EWOULDBLOCK);
-  if (read_bytes == -1 && errno == EWOULDBLOCK) {
+  if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
     // If the read would block we need to retry and therefore return 0
     // as the number of bytes written.
     read_bytes = 0;
@@ -133,7 +125,7 @@
   socklen_t addr_len = sizeof(addr->ss);
   ssize_t read_bytes = TEMP_FAILURE_RETRY(
       recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len));
-  if (read_bytes == -1 && errno == EWOULDBLOCK) {
+  if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
     // If the read would block we need to retry and therefore return 0
     // as the number of bytes written.
     read_bytes = 0;
@@ -146,7 +138,7 @@
   ASSERT(fd >= 0);
   ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
   ASSERT(EAGAIN == EWOULDBLOCK);
-  if (written_bytes == -1 && errno == EWOULDBLOCK) {
+  if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
     // If the would block we need to retry and therefore return 0 as
     // the number of bytes written.
     written_bytes = 0;
@@ -162,7 +154,7 @@
       sendto(fd, buffer, num_bytes, 0,
              &addr.addr, SocketAddress::GetAddrLength(addr)));
   ASSERT(EAGAIN == EWOULDBLOCK);
-  if (written_bytes == -1 && errno == EWOULDBLOCK) {
+  if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
     // If the would block we need to retry and therefore return 0 as
     // the number of bytes written.
     written_bytes = 0;
@@ -208,10 +200,18 @@
 int Socket::GetType(intptr_t fd) {
   struct stat buf;
   int result = fstat(fd, &buf);
-  if (result == -1) return -1;
-  if (S_ISCHR(buf.st_mode)) return File::kTerminal;
-  if (S_ISFIFO(buf.st_mode)) return File::kPipe;
-  if (S_ISREG(buf.st_mode)) return File::kFile;
+  if (result == -1) {
+    return -1;
+  }
+  if (S_ISCHR(buf.st_mode)) {
+    return File::kTerminal;
+  }
+  if (S_ISFIFO(buf.st_mode)) {
+    return File::kPipe;
+  }
+  if (S_ISREG(buf.st_mode)) {
+    return File::kFile;
+  }
   return File::kOther;
 }
 
@@ -242,12 +242,14 @@
   }
   intptr_t count = 0;
   for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
-    if (c->ai_family == AF_INET || c->ai_family == AF_INET6) count++;
+    if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
+      count++;
+    }
   }
   intptr_t i = 0;
   AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
   for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
-    if (c->ai_family == AF_INET || c->ai_family == AF_INET6) {
+    if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
       addresses->SetAt(i, new SocketAddress(c->ai_addr));
       i++;
     }
@@ -289,7 +291,7 @@
     ASSERT(type == SocketAddress::TYPE_IPV6);
     result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr);
   }
-  return result == 1;
+  return (result == 1);
 }
 
 
@@ -297,7 +299,9 @@
   intptr_t fd;
 
   fd = NO_RETRY_EXPECTED(socket(addr.addr.sa_family, SOCK_DGRAM, IPPROTO_UDP));
-  if (fd < 0) return -1;
+  if (fd < 0) {
+    return -1;
+  }
 
   FDUtils::SetCloseOnExec(fd);
 
@@ -324,12 +328,9 @@
     return false;
   }
   int family = ifa->ifa_addr->sa_family;
-  if (lookup_family == family) return true;
-  if (lookup_family == AF_UNSPEC &&
-      (family == AF_INET || family == AF_INET6)) {
-    return true;
-  }
-  return false;
+  return ((lookup_family == family) ||
+         ((lookup_family == AF_UNSPEC) &&
+          ((family == AF_INET) || (family == AF_INET6))));
 }
 
 
@@ -376,7 +377,9 @@
   intptr_t fd;
 
   fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0));
-  if (fd < 0) return -1;
+  if (fd < 0) {
+    return -1;
+  }
 
   FDUtils::SetCloseOnExec(fd);
 
@@ -397,7 +400,8 @@
   }
 
   // Test for invalid socket port 65535 (some browsers disallow it).
-  if (SocketAddress::GetAddrPort(addr) == 0 && Socket::GetPort(fd) == 65535) {
+  if ((SocketAddress::GetAddrPort(addr) == 0) &&
+      (Socket::GetPort(fd) == 65535)) {
     // Don't close the socket until we have created a new socket, ensuring
     // that we do not get the bad port number again.
     intptr_t new_fd = CreateBindListen(addr, backlog, v6_only);
@@ -459,9 +463,9 @@
                                          reinterpret_cast<void *>(&on),
                                          &len));
   if (err == 0) {
-    *enabled = on == 1;
+    *enabled = (on == 1);
   }
-  return err == 0;
+  return (err == 0);
 }
 
 
@@ -546,9 +550,9 @@
                                          reinterpret_cast<char *>(&on),
                                          &len));
   if (err == 0) {
-    *enabled = on == 1;
+    *enabled = (on == 1);
   }
-  return err == 0;
+  return (err == 0);
 }
 
 
diff --git a/runtime/bin/socket_win.cc b/runtime/bin/socket_win.cc
index 30bdc44..ea306b7 100644
--- a/runtime/bin/socket_win.cc
+++ b/runtime/bin/socket_win.cc
@@ -54,7 +54,9 @@
 
 bool Socket::Initialize() {
   MutexLocker lock(init_mutex);
-  if (socket_initialized) return true;
+  if (socket_initialized) {
+    return true;
+  }
   int err;
   WSADATA winsock_data;
   WORD version_requested = MAKEWORD(2, 2);
@@ -64,7 +66,7 @@
   } else {
     Log::PrintErr("Unable to initialize Winsock: %d\n", WSAGetLastError());
   }
-  return err == 0;
+  return (err == 0);
 }
 
 intptr_t Socket::Available(intptr_t fd) {
@@ -107,9 +109,7 @@
   SocketHandle* socket_handle = reinterpret_cast<SocketHandle*>(fd);
   RawAddr raw;
   socklen_t size = sizeof(raw);
-  if (getsockname(socket_handle->socket(),
-                  &raw.addr,
-                  &size) == SOCKET_ERROR) {
+  if (getsockname(socket_handle->socket(),  &raw.addr, &size) == SOCKET_ERROR) {
     return 0;
   }
   return SocketAddress::GetAddrPort(raw);
@@ -121,9 +121,7 @@
   SocketHandle* socket_handle = reinterpret_cast<SocketHandle*>(fd);
   RawAddr raw;
   socklen_t size = sizeof(raw);
-  if (getpeername(socket_handle->socket(),
-                  &raw.addr,
-                  &size)) {
+  if (getpeername(socket_handle->socket(), &raw.addr, &size)) {
     return NULL;
   }
   *port = SocketAddress::GetAddrPort(raw);
@@ -268,7 +266,9 @@
 
 
 intptr_t Socket::GetStdioHandle(intptr_t num) {
-  if (num != 0) return -1;
+  if (num != 0) {
+    return -1;
+  }
   HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
   if (handle == INVALID_HANDLE_VALUE) {
     return -1;
@@ -320,12 +320,14 @@
   }
   intptr_t count = 0;
   for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
-    if (c->ai_family == AF_INET || c->ai_family == AF_INET6) count++;
+    if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
+      count++;
+    }
   }
   AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
   intptr_t i = 0;
   for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
-    if (c->ai_family == AF_INET || c->ai_family == AF_INET6) {
+    if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
       addresses->SetAt(i, new SocketAddress(c->ai_addr));
       i++;
     }
@@ -393,9 +395,7 @@
     }
   }
 
-  status = bind(s,
-                &addr.addr,
-                SocketAddress::GetAddrLength(addr));
+  status = bind(s, &addr.addr,  SocketAddress::GetAddrLength(addr));
   if (status == SOCKET_ERROR) {
     DWORD rc = WSAGetLastError();
     closesocket(s);
@@ -496,9 +496,7 @@
                sizeof(optval));
   }
 
-  status = bind(s,
-                &addr.addr,
-                SocketAddress::GetAddrLength(addr));
+  status = bind(s, &addr.addr, SocketAddress::GetAddrLength(addr));
   if (status == SOCKET_ERROR) {
     DWORD rc = WSAGetLastError();
     closesocket(s);
@@ -509,8 +507,8 @@
   ListenSocket* listen_socket = new ListenSocket(s);
 
   // Test for invalid socket port 65535 (some browsers disallow it).
-  if (SocketAddress::GetAddrPort(addr) == 0 &&
-      Socket::GetPort(reinterpret_cast<intptr_t>(listen_socket)) == 65535) {
+  if ((SocketAddress::GetAddrPort(addr) == 0) &&
+      (Socket::GetPort(reinterpret_cast<intptr_t>(listen_socket)) == 65535)) {
     // Don't close fd until we have created new. By doing that we ensure another
     // port.
     intptr_t new_s = CreateBindListen(addr, backlog, v6_only);
@@ -571,9 +569,9 @@
                        reinterpret_cast<char *>(&on),
                        &len);
   if (err == 0) {
-    *enabled = on == 1;
+    *enabled = (on == 1);
   }
-  return err == 0;
+  return (err == 0);
 }
 
 
@@ -618,7 +616,6 @@
                     optname,
                     reinterpret_cast<char *>(&on),
                     sizeof(on)) == 0;
-  return false;
 }
 
 
@@ -665,9 +662,9 @@
                        reinterpret_cast<char *>(&on),
                        &len);
   if (err == 0) {
-    *enabled = on == 1;
+    *enabled = (on == 1);
   }
-  return err == 0;
+  return (err == 0);
 }
 
 
diff --git a/runtime/bin/socket_win.h b/runtime/bin/socket_win.h
index 76f33fd..ab32ed3 100644
--- a/runtime/bin/socket_win.h
+++ b/runtime/bin/socket_win.h
@@ -5,9 +5,9 @@
 #ifndef BIN_SOCKET_WIN_H_
 #define BIN_SOCKET_WIN_H_
 
-#include <winsock2.h>
 #include <iphlpapi.h>
-#include <ws2tcpip.h>
 #include <mswsock.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
 
 #endif  // BIN_SOCKET_WIN_H_
diff --git a/runtime/bin/stdio.cc b/runtime/bin/stdio.cc
index c866710..b14fe92 100644
--- a/runtime/bin/stdio.cc
+++ b/runtime/bin/stdio.cc
@@ -2,17 +2,17 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+#include "bin/stdio.h"
+
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
 #include "bin/utils.h"
-#include "bin/stdio.h"
 
 #include "platform/globals.h"
 #include "platform/utils.h"
 
 #include "include/dart_api.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -51,7 +51,7 @@
     return;
   }
   intptr_t fd = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 0));
-  if (fd != 1 && fd != 2) {
+  if ((fd != 1) && (fd != 2)) {
     Dart_SetReturnValue(args, Dart_NewApiError("Terminal fd must be 1 or 2"));
     return;
   }
diff --git a/runtime/bin/stdio.h b/runtime/bin/stdio.h
index 99e2cd5..afe4637 100644
--- a/runtime/bin/stdio.h
+++ b/runtime/bin/stdio.h
@@ -10,7 +10,6 @@
 
 #include "platform/globals.h"
 
-
 namespace dart {
 namespace bin {
 
diff --git a/runtime/bin/stdio_android.cc b/runtime/bin/stdio_android.cc
index a02a8e3..8d2a3c5 100644
--- a/runtime/bin/stdio_android.cc
+++ b/runtime/bin/stdio_android.cc
@@ -5,16 +5,15 @@
 #include "platform/globals.h"
 #if defined(TARGET_OS_ANDROID)
 
+#include "bin/stdio.h"
+
 #include <errno.h>  // NOLINT
 #include <sys/ioctl.h>  // NOLINT
 #include <termios.h>  // NOLINT
 
-#include "bin/stdio.h"
 #include "bin/fdutils.h"
-
 #include "platform/signal_blocker.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -30,7 +29,7 @@
 bool Stdin::GetEchoMode() {
   struct termios term;
   tcgetattr(STDIN_FILENO, &term);
-  return (term.c_lflag & ECHO) != 0;
+  return ((term.c_lflag & ECHO) != 0);
 }
 
 
@@ -38,9 +37,9 @@
   struct termios term;
   tcgetattr(STDIN_FILENO, &term);
   if (enabled) {
-    term.c_lflag |= ECHO|ECHONL;
+    term.c_lflag |= (ECHO | ECHONL);
   } else {
-    term.c_lflag &= ~(ECHO|ECHONL);
+    term.c_lflag &= ~(ECHO | ECHONL);
   }
   tcsetattr(STDIN_FILENO, TCSANOW, &term);
 }
@@ -49,7 +48,7 @@
 bool Stdin::GetLineMode() {
   struct termios term;
   tcgetattr(STDIN_FILENO, &term);
-  return (term.c_lflag & ICANON) != 0;
+  return ((term.c_lflag & ICANON) != 0);
 }
 
 
@@ -67,8 +66,8 @@
 
 bool Stdout::GetTerminalSize(intptr_t fd, int size[2]) {
   struct winsize w;
-  if (NO_RETRY_EXPECTED(ioctl(fd, TIOCGWINSZ, &w) == 0) &&
-      (w.ws_col != 0 || w.ws_row != 0)) {
+  int status = NO_RETRY_EXPECTED(ioctl(fd, TIOCGWINSZ, &w));
+  if ((status == 0) && ((w.ws_col != 0) || (w.ws_row != 0))) {
     size[0] = w.ws_col;
     size[1] = w.ws_row;
     return true;
diff --git a/runtime/bin/stdio_linux.cc b/runtime/bin/stdio_linux.cc
index c01a771..8f51e7e 100644
--- a/runtime/bin/stdio_linux.cc
+++ b/runtime/bin/stdio_linux.cc
@@ -5,16 +5,15 @@
 #include "platform/globals.h"
 #if defined(TARGET_OS_LINUX)
 
+#include "bin/stdio.h"
+
 #include <errno.h>  // NOLINT
 #include <sys/ioctl.h>  // NOLINT
 #include <termios.h>  // NOLINT
 
-#include "bin/stdio.h"
 #include "bin/fdutils.h"
-
 #include "platform/signal_blocker.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -30,7 +29,7 @@
 bool Stdin::GetEchoMode() {
   struct termios term;
   VOID_NO_RETRY_EXPECTED(tcgetattr(STDIN_FILENO, &term));
-  return (term.c_lflag & ECHO) != 0;
+  return ((term.c_lflag & ECHO) != 0);
 }
 
 
@@ -38,9 +37,9 @@
   struct termios term;
   VOID_NO_RETRY_EXPECTED(tcgetattr(STDIN_FILENO, &term));
   if (enabled) {
-    term.c_lflag |= ECHO|ECHONL;
+    term.c_lflag |= (ECHO | ECHONL);
   } else {
-    term.c_lflag &= ~(ECHO|ECHONL);
+    term.c_lflag &= ~(ECHO | ECHONL);
   }
   VOID_NO_RETRY_EXPECTED(tcsetattr(STDIN_FILENO, TCSANOW, &term));
 }
@@ -49,7 +48,7 @@
 bool Stdin::GetLineMode() {
   struct termios term;
   VOID_NO_RETRY_EXPECTED(tcgetattr(STDIN_FILENO, &term));
-  return (term.c_lflag & ICANON) != 0;
+  return ((term.c_lflag & ICANON) != 0);
 }
 
 
@@ -67,8 +66,8 @@
 
 bool Stdout::GetTerminalSize(intptr_t fd, int size[2]) {
   struct winsize w;
-  if (NO_RETRY_EXPECTED(ioctl(fd, TIOCGWINSZ, &w)) == 0 &&
-      (w.ws_col != 0 || w.ws_row != 0)) {
+  int status = NO_RETRY_EXPECTED(ioctl(fd, TIOCGWINSZ, &w));
+  if ((status == 0) && ((w.ws_col != 0) || (w.ws_row != 0))) {
     size[0] = w.ws_col;
     size[1] = w.ws_row;
     return true;
diff --git a/runtime/bin/stdio_macos.cc b/runtime/bin/stdio_macos.cc
index 24f0414..7dc1141 100644
--- a/runtime/bin/stdio_macos.cc
+++ b/runtime/bin/stdio_macos.cc
@@ -5,16 +5,15 @@
 #include "platform/globals.h"
 #if defined(TARGET_OS_MACOS)
 
+#include "bin/stdio.h"
+
 #include <errno.h>  // NOLINT
 #include <sys/ioctl.h>  // NOLINT
 #include <termios.h>  // NOLINT
 
-#include "bin/stdio.h"
 #include "bin/fdutils.h"
-
 #include "platform/signal_blocker.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -30,7 +29,7 @@
 bool Stdin::GetEchoMode() {
   struct termios term;
   tcgetattr(STDIN_FILENO, &term);
-  return (term.c_lflag & ECHO) != 0;
+  return ((term.c_lflag & ECHO) != 0);
 }
 
 
@@ -38,9 +37,9 @@
   struct termios term;
   tcgetattr(STDIN_FILENO, &term);
   if (enabled) {
-    term.c_lflag |= ECHO|ECHONL;
+    term.c_lflag |= (ECHO | ECHONL);
   } else {
-    term.c_lflag &= ~(ECHO|ECHONL);
+    term.c_lflag &= ~(ECHO | ECHONL);
   }
   tcsetattr(STDIN_FILENO, TCSANOW, &term);
 }
@@ -49,7 +48,7 @@
 bool Stdin::GetLineMode() {
   struct termios term;
   tcgetattr(STDIN_FILENO, &term);
-  return (term.c_lflag & ICANON) != 0;
+  return ((term.c_lflag & ICANON) != 0);
 }
 
 
@@ -67,8 +66,8 @@
 
 bool Stdout::GetTerminalSize(intptr_t fd, int size[2]) {
   struct winsize w;
-  if (NO_RETRY_EXPECTED(ioctl(fd, TIOCGWINSZ, &w) == 0) &&
-      (w.ws_col != 0 || w.ws_row != 0)) {
+  int status = NO_RETRY_EXPECTED(ioctl(fd, TIOCGWINSZ, &w));
+  if ((status == 0) && ((w.ws_col != 0) || (w.ws_row != 0))) {
     size[0] = w.ws_col;
     size[1] = w.ws_row;
     return true;
diff --git a/runtime/bin/stdio_win.cc b/runtime/bin/stdio_win.cc
index ec479c0..1cb6a527 100644
--- a/runtime/bin/stdio_win.cc
+++ b/runtime/bin/stdio_win.cc
@@ -7,7 +7,6 @@
 
 #include "bin/stdio.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -16,7 +15,7 @@
   uint8_t buffer[1];
   DWORD read = 0;
   int c = -1;
-  if (ReadFile(h, buffer, 1, &read, NULL) && read == 1) {
+  if (ReadFile(h, buffer, 1, &read, NULL) && (read == 1)) {
     c = buffer[0];
   }
   return c;
@@ -26,15 +25,19 @@
 bool Stdin::GetEchoMode() {
   HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
   DWORD mode;
-  if (!GetConsoleMode(h, &mode)) return false;
-  return (mode & ENABLE_ECHO_INPUT) != 0;
+  if (!GetConsoleMode(h, &mode)) {
+    return false;
+  }
+  return ((mode & ENABLE_ECHO_INPUT) != 0);
 }
 
 
 void Stdin::SetEchoMode(bool enabled) {
   HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
   DWORD mode;
-  if (!GetConsoleMode(h, &mode)) return;
+  if (!GetConsoleMode(h, &mode)) {
+    return;
+  }
   if (enabled) {
     mode |= ENABLE_ECHO_INPUT;
   } else {
@@ -47,7 +50,9 @@
 bool Stdin::GetLineMode() {
   HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
   DWORD mode;
-  if (!GetConsoleMode(h, &mode)) return false;
+  if (!GetConsoleMode(h, &mode)) {
+    return false;
+  }
   return (mode & ENABLE_LINE_INPUT) != 0;
 }
 
@@ -55,7 +60,9 @@
 void Stdin::SetLineMode(bool enabled) {
   HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
   DWORD mode;
-  if (!GetConsoleMode(h, &mode)) return;
+  if (!GetConsoleMode(h, &mode)) {
+    return;
+  }
   if (enabled) {
     mode |= ENABLE_LINE_INPUT;
   } else {
@@ -73,7 +80,9 @@
     h = GetStdHandle(STD_ERROR_HANDLE);
   }
   CONSOLE_SCREEN_BUFFER_INFO info;
-  if (!GetConsoleScreenBufferInfo(h, &info)) return false;
+  if (!GetConsoleScreenBufferInfo(h, &info)) {
+    return false;
+  }
   size[0] = info.srWindow.Right - info.srWindow.Left + 1;
   size[1] = info.srWindow.Bottom - info.srWindow.Top + 1;
   return true;
diff --git a/runtime/bin/thread.h b/runtime/bin/thread.h
index d4a67bc..d95675d 100644
--- a/runtime/bin/thread.h
+++ b/runtime/bin/thread.h
@@ -57,6 +57,10 @@
   static void GetThreadCpuUsage(ThreadId thread_id, int64_t* cpu_usage);
 
   static void InitOnce();
+
+ private:
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Thread);
 };
 
 
@@ -105,7 +109,6 @@
   DISALLOW_COPY_AND_ASSIGN(Monitor);
 };
 
-
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/thread_android.cc b/runtime/bin/thread_android.cc
index f84a988..4f5c547 100644
--- a/runtime/bin/thread_android.cc
+++ b/runtime/bin/thread_android.cc
@@ -6,6 +6,7 @@
 #if defined(TARGET_OS_ANDROID)
 
 #include "bin/thread.h"
+#include "bin/thread_android.h"
 
 #include <errno.h>  // NOLINT
 #include <sys/time.h>  // NOLINT
@@ -37,7 +38,9 @@
   }
 #else
 #define RETURN_ON_PTHREAD_FAILURE(result) \
-  if (result != 0) return result;
+  if (result != 0) { \
+    return result; \
+  }
 #endif
 
 
@@ -164,7 +167,7 @@
 
 
 bool Thread::Compare(ThreadId a, ThreadId b) {
-  return a == b;
+  return (a == b);
 }
 
 
diff --git a/runtime/bin/thread_linux.cc b/runtime/bin/thread_linux.cc
index 1e01a77..7a2a92a 100644
--- a/runtime/bin/thread_linux.cc
+++ b/runtime/bin/thread_linux.cc
@@ -6,6 +6,7 @@
 #if defined(TARGET_OS_LINUX)
 
 #include "bin/thread.h"
+#include "bin/thread_linux.h"
 
 #include <errno.h>  // NOLINT
 #include <sys/resource.h>  // NOLINT
@@ -38,7 +39,9 @@
   }
 #else
 #define RETURN_ON_PTHREAD_FAILURE(result) \
-  if (result != 0) return result;
+  if (result != 0) { \
+    return result; \
+  }
 #endif
 
 
@@ -165,7 +168,7 @@
 
 
 bool Thread::Compare(ThreadId a, ThreadId b) {
-  return pthread_equal(a, b) != 0;
+  return (pthread_equal(a, b) != 0);
 }
 
 
diff --git a/runtime/bin/thread_macos.cc b/runtime/bin/thread_macos.cc
index 28c747d..8286835 100644
--- a/runtime/bin/thread_macos.cc
+++ b/runtime/bin/thread_macos.cc
@@ -6,17 +6,18 @@
 #if defined(TARGET_OS_MACOS)
 
 #include "bin/thread.h"
+#include "bin/thread_macos.h"
 
-#include <sys/errno.h>  // NOLINT
-#include <sys/types.h>  // NOLINT
-#include <sys/sysctl.h>  // NOLINT
-#include <mach/mach_init.h>  // NOLINT
 #include <mach/mach_host.h>  // NOLINT
+#include <mach/mach_init.h>  // NOLINT
 #include <mach/mach_port.h>  // NOLINT
 #include <mach/mach_traps.h>  // NOLINT
 #include <mach/task_info.h>  // NOLINT
-#include <mach/thread_info.h>  // NOLINT
 #include <mach/thread_act.h>  // NOLINT
+#include <mach/thread_info.h>  // NOLINT
+#include <sys/errno.h>  // NOLINT
+#include <sys/sysctl.h>  // NOLINT
+#include <sys/types.h>  // NOLINT
 
 #include "platform/assert.h"
 #include "platform/utils.h"
@@ -45,7 +46,9 @@
   }
 #else
 #define RETURN_ON_PTHREAD_FAILURE(result) \
-  if (result != 0) return result;
+  if (result != 0) { \
+    return result; \
+  }
 #endif
 
 
@@ -157,7 +160,7 @@
 
 
 bool Thread::Compare(ThreadId a, ThreadId b) {
-  return pthread_equal(a, b) != 0;
+  return (pthread_equal(a, b) != 0);
 }
 
 
diff --git a/runtime/bin/thread_win.cc b/runtime/bin/thread_win.cc
index 44941bb..db41196 100644
--- a/runtime/bin/thread_win.cc
+++ b/runtime/bin/thread_win.cc
@@ -6,6 +6,7 @@
 #if defined(TARGET_OS_WINDOWS)
 
 #include "bin/thread.h"
+#include "bin/thread_win.h"
 
 #include <process.h>  // NOLINT
 
@@ -57,7 +58,7 @@
   uint32_t tid;
   uintptr_t thread = _beginthreadex(NULL, Thread::GetMaxStackSize(),
                                     ThreadEntry, start_data, 0, &tid);
-  if (thread == -1L || thread == 0) {
+  if ((thread == -1L) || (thread == 0)) {
 #ifdef DEBUG
     fprintf(stderr, "_beginthreadex error: %d (%s)\n", errno, strerror(errno));
 #endif
@@ -130,7 +131,7 @@
 
 
 bool Thread::Compare(ThreadId a, ThreadId b) {
-  return a == b;
+  return (a == b);
 }
 
 
@@ -209,7 +210,7 @@
   if (result == WAIT_OBJECT_0) {
     return true;
   }
-  if (result == WAIT_ABANDONED || result == WAIT_FAILED) {
+  if ((result == WAIT_ABANDONED) || (result == WAIT_FAILED)) {
     FATAL1("Mutex try lock failed %d", GetLastError());
   }
   ASSERT(result == WAIT_TIMEOUT);
@@ -273,7 +274,8 @@
   EnterCriticalSection(&waiters_cs_);
   if (waiters_tail_ == NULL) {
     ASSERT(waiters_head_ == NULL);
-    waiters_head_ = waiters_tail_ = wait_data;
+    waiters_head_ = wait_data;
+    waiters_tail_ = wait_data;
   } else {
     waiters_tail_->next_ = wait_data;
     waiters_tail_ = wait_data;
@@ -291,7 +293,8 @@
   while (current != NULL) {
     if (current == wait_data) {
       if (waiters_head_ == waiters_tail_) {
-        waiters_head_ = waiters_tail_ = NULL;
+        waiters_head_ = NULL;
+        waiters_tail_ = NULL;
       } else if (current == waiters_head_) {
         waiters_head_ = waiters_head_->next_;
       } else if (current == waiters_tail_) {
@@ -319,7 +322,8 @@
   if (first != NULL) {
     // Remove from list.
     if (waiters_head_ == waiters_tail_) {
-      waiters_tail_ = waiters_head_ = NULL;
+      waiters_tail_ = NULL;
+      waiters_head_ = NULL;
     } else {
       waiters_head_ = waiters_head_->next_;
     }
@@ -340,7 +344,8 @@
   // Extract list to signal.
   MonitorWaitData* current = waiters_head_;
   // Clear list.
-  waiters_head_ = waiters_tail_ = NULL;
+  waiters_head_ = NULL;
+  waiters_tail_ = NULL;
   // Iterate and signal all events.
   while (current != NULL) {
     // Copy next.
diff --git a/runtime/bin/utils.h b/runtime/bin/utils.h
index cbc2bab..ab02ebe 100644
--- a/runtime/bin/utils.h
+++ b/runtime/bin/utils.h
@@ -83,6 +83,10 @@
   static char* Utf8ToConsoleString(char* utf8,
                                    intptr_t len = -1,
                                    intptr_t* result_len = NULL);
+
+ private:
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(StringUtils);
 };
 
 
@@ -94,14 +98,23 @@
   // Returns true if the arguments are converted. In that case
   // each of the arguments need to be deallocated using free.
   static bool GetUtf8Argv(int argc, char** argv);
+
+ private:
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ShellUtils);
 };
 
+
 class TimerUtils {
  public:
   static void InitOnce();
   static int64_t GetCurrentMonotonicMicros();
   static int64_t GetCurrentMonotonicMillis();
   static void Sleep(int64_t millis);
+
+ private:
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(TimerUtils);
 };
 
 }  // namespace bin
diff --git a/runtime/bin/utils_android.cc b/runtime/bin/utils_android.cc
index e36ac11..c7a4d63 100644
--- a/runtime/bin/utils_android.cc
+++ b/runtime/bin/utils_android.cc
@@ -14,7 +14,6 @@
 #include "platform/assert.h"
 #include "platform/utils.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -43,41 +42,49 @@
   }
 }
 
+
 const char* StringUtils::ConsoleStringToUtf8(
     const char* str, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
+
 const char* StringUtils::Utf8ToConsoleString(
     const char* utf8, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
+
 char* StringUtils::ConsoleStringToUtf8(
     char* str, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
+
 char* StringUtils::Utf8ToConsoleString(
     char* utf8, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
+
 bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
   return false;
 }
 
+
 void TimerUtils::InitOnce() {
 }
 
+
 int64_t TimerUtils::GetCurrentMonotonicMillis() {
   return GetCurrentMonotonicMicros() / 1000;
 }
 
+
 int64_t TimerUtils::GetCurrentMonotonicMicros() {
   struct timespec ts;
   if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
@@ -91,6 +98,7 @@
   return result;
 }
 
+
 void TimerUtils::Sleep(int64_t millis) {
   struct timespec req;  // requested.
   struct timespec rem;  // remainder.
diff --git a/runtime/bin/utils_linux.cc b/runtime/bin/utils_linux.cc
index ea6ef8c..2029071 100644
--- a/runtime/bin/utils_linux.cc
+++ b/runtime/bin/utils_linux.cc
@@ -14,7 +14,6 @@
 #include "platform/assert.h"
 #include "platform/utils.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -41,41 +40,49 @@
   }
 }
 
+
 const char* StringUtils::ConsoleStringToUtf8(
     const char* str, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
+
 const char* StringUtils::Utf8ToConsoleString(
     const char* utf8, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
+
 char* StringUtils::ConsoleStringToUtf8(
     char* str, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
+
 char* StringUtils::Utf8ToConsoleString(
     char* utf8, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
+
 bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
   return false;
 }
 
+
 void TimerUtils::InitOnce() {
 }
 
+
 int64_t TimerUtils::GetCurrentMonotonicMillis() {
   return GetCurrentMonotonicMicros() / 1000;
 }
 
+
 int64_t TimerUtils::GetCurrentMonotonicMicros() {
   struct timespec ts;
   if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
@@ -89,6 +96,7 @@
   return result;
 }
 
+
 void TimerUtils::Sleep(int64_t millis) {
   struct timespec req;  // requested.
   struct timespec rem;  // remainder.
diff --git a/runtime/bin/utils_macos.cc b/runtime/bin/utils_macos.cc
index eea4cb7..136881d 100644
--- a/runtime/bin/utils_macos.cc
+++ b/runtime/bin/utils_macos.cc
@@ -6,22 +6,20 @@
 #if defined(TARGET_OS_MACOS)
 
 #include <errno.h>  // NOLINT
-#include <netdb.h>  // NOLINT
-#include <mach/mach.h>  // NOLINT
 #include <mach/clock.h>  // NOLINT
+#include <mach/mach.h>  // NOLINT
 #include <mach/mach_time.h>  // NOLINT
-#include <sys/time.h>  // NOLINT
-#include <time.h>  // NOLINT
-
+#include <netdb.h>  // NOLINT
 #if TARGET_OS_IOS
 #include <sys/sysctl.h>  // NOLINT
 #endif
+#include <sys/time.h>  // NOLINT
+#include <time.h>  // NOLINT
 
 #include "bin/utils.h"
 #include "platform/assert.h"
 #include "platform/utils.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -50,47 +48,55 @@
   }
 }
 
+
 const char* StringUtils::ConsoleStringToUtf8(
     const char* str, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
+
 const char* StringUtils::Utf8ToConsoleString(
     const char* utf8, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
+
 char* StringUtils::ConsoleStringToUtf8(
     char* str, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
+
 char* StringUtils::Utf8ToConsoleString(
     char* utf8, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
+
 bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
   return false;
 }
 
+
 static mach_timebase_info_data_t timebase_info;
 
+
 void TimerUtils::InitOnce() {
   kern_return_t kr = mach_timebase_info(&timebase_info);
   ASSERT(KERN_SUCCESS == kr);
 }
 
+
 int64_t TimerUtils::GetCurrentMonotonicMillis() {
   return GetCurrentMonotonicMicros() / 1000;
 }
 
-#if TARGET_OS_IOS
 
+#if TARGET_OS_IOS
 static int64_t GetCurrentTimeMicros() {
   // gettimeofday has microsecond resolution.
   struct timeval tv;
@@ -100,9 +106,9 @@
   }
   return (static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec;
 }
-
 #endif  // TARGET_OS_IOS
 
+
 int64_t TimerUtils::GetCurrentMonotonicMicros() {
 #if TARGET_OS_IOS
   // On iOS mach_absolute_time stops while the device is sleeping. Instead use
@@ -129,6 +135,7 @@
 #endif  // TARGET_OS_IOS
 }
 
+
 void TimerUtils::Sleep(int64_t millis) {
   struct timespec req;  // requested.
   struct timespec rem;  // remainder.
diff --git a/runtime/bin/utils_win.cc b/runtime/bin/utils_win.cc
index 227cc24..7e3cfb6 100644
--- a/runtime/bin/utils_win.cc
+++ b/runtime/bin/utils_win.cc
@@ -8,12 +8,11 @@
 #include <errno.h>  // NOLINT
 #include <time.h>  // NOLINT
 
+#include "bin/log.h"
 #include "bin/utils.h"
 #include "bin/utils_win.h"
-#include "bin/log.h"
 #include "platform/assert.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -185,20 +184,22 @@
 }
 
 
+// Although win32 uses 64-bit integers for representing timestamps,
+// these are packed into a FILETIME structure. The FILETIME
+// structure is just a struct representing a 64-bit integer. The
+// TimeStamp union allows access to both a FILETIME and an integer
+// representation of the timestamp. The Windows timestamp is in
+// 100-nanosecond intervals since January 1, 1601.
+union TimeStamp {
+  FILETIME ft_;
+  int64_t t_;
+};
+
+
 static int64_t GetCurrentTimeMicros() {
   static const int64_t kTimeEpoc = 116444736000000000LL;
   static const int64_t kTimeScaler = 10;  // 100 ns to us.
 
-  // Although win32 uses 64-bit integers for representing timestamps,
-  // these are packed into a FILETIME structure. The FILETIME
-  // structure is just a struct representing a 64-bit integer. The
-  // TimeStamp union allows access to both a FILETIME and an integer
-  // representation of the timestamp. The Windows timestamp is in
-  // 100-nanosecond intervals since January 1, 1601.
-  union TimeStamp {
-    FILETIME ft_;
-    int64_t t_;
-  };
   TimeStamp time;
   GetSystemTimeAsFileTime(&time.ft_);
   return (time.t_ - kTimeEpoc) / kTimeScaler;
diff --git a/runtime/bin/utils_win.h b/runtime/bin/utils_win.h
index b8f9fbc..fe0fa5c 100644
--- a/runtime/bin/utils_win.h
+++ b/runtime/bin/utils_win.h
@@ -31,6 +31,10 @@
   static const wchar_t* Utf8ToWide(const char* utf8,
                                    intptr_t len = -1,
                                    intptr_t* result_len = NULL);
+
+ private:
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(StringUtilsWin);
 };
 
 }  // namespace bin
diff --git a/runtime/bin/vmservice_dartium.cc b/runtime/bin/vmservice_dartium.cc
index 2a9fc8f..535fb41 100644
--- a/runtime/bin/vmservice_dartium.cc
+++ b/runtime/bin/vmservice_dartium.cc
@@ -148,6 +148,7 @@
   inflateEnd(&strm);
 }
 
+
 /* DISALLOW_ALLOCATION */
 void VmServiceServer::operator delete(void* pointer)  {
   fprintf(stderr, "unreachable code\n");
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index 08fd57a..2736408 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -120,6 +120,7 @@
   // NO-OP.
 }
 
+
 struct VmServiceIONativeEntry {
   const char* name;
   int num_arguments;
@@ -271,7 +272,7 @@
 
 
 const char* VmService::GetErrorMessage() {
-  return error_msg_ == NULL ? "No error." : error_msg_;
+  return (error_msg_ == NULL) ? "No error." : error_msg_;
 }
 
 
diff --git a/runtime/bin/vmservice_impl.h b/runtime/bin/vmservice_impl.h
index 1780013..f373b4b 100644
--- a/runtime/bin/vmservice_impl.h
+++ b/runtime/bin/vmservice_impl.h
@@ -55,7 +55,6 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(VmService);
 };
 
-
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 77d1289..6665e0a 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -721,6 +721,15 @@
 typedef void (*Dart_IsolateShutdownCallback)(void* callback_data);
 
 /**
+ * A thread death callback function.
+ * This callback, provided by the embedder, is called before a thread in the
+ * vm thread pool exits.
+ * This function could be used to dispose of native resources that
+ * are associated and attached to the thread, in order to avoid leaks.
+ */
+typedef void (*Dart_ThreadExitCallback)();
+
+/**
  * Callbacks provided by the embedder for file operations. If the
  * embedder does not allow file operations these callbacks can be
  * NULL.
@@ -802,6 +811,7 @@
     Dart_IsolateInterruptCallback interrupt,
     Dart_IsolateUnhandledExceptionCallback unhandled_exception,
     Dart_IsolateShutdownCallback shutdown,
+    Dart_ThreadExitCallback thread_exit,
     Dart_FileOpenCallback file_open,
     Dart_FileReadCallback file_read,
     Dart_FileWriteCallback file_write,
diff --git a/runtime/include/dart_tools_api.h b/runtime/include/dart_tools_api.h
index 8b9b013..c880e17 100644
--- a/runtime/include/dart_tools_api.h
+++ b/runtime/include/dart_tools_api.h
@@ -902,37 +902,26 @@
 #define DART_TIMELINE_STREAM_GC (1 << 5)
 /** Timeline stream for isolate events */
 #define DART_TIMELINE_STREAM_ISOLATE (1 << 6)
-
 /** Timeline stream for VM events */
 #define DART_TIMELINE_STREAM_VM (1 << 7)
 
-/** Enable all timeline stream recording for an isolate */
+/** All timeline streams */
 #define DART_TIMELINE_STREAM_ALL (DART_TIMELINE_STREAM_API |                   \
                                   DART_TIMELINE_STREAM_COMPILER |              \
                                   DART_TIMELINE_STREAM_DART |                  \
                                   DART_TIMELINE_STREAM_DEBUGGER |              \
                                   DART_TIMELINE_STREAM_EMBEDDER |              \
                                   DART_TIMELINE_STREAM_GC |                    \
-                                  DART_TIMELINE_STREAM_ISOLATE)
+                                  DART_TIMELINE_STREAM_ISOLATE |               \
+                                  DART_TIMELINE_STREAM_VM)
 
 /** Disable all timeline stream recording */
 #define DART_TIMELINE_STREAM_DISABLE 0
 
-/**
- * Start recording timeline events for the current isolate.
- *
- * \param stream_mask A bitmask of streams that should be recorded.
- *
- * NOTE: Calling with 0 disables recording of all streams.
- */
-DART_EXPORT void Dart_TimelineSetRecordedStreams(int64_t stream_mask);
-
 
 /**
  * Start recording timeline events for the entire VM (including all isolates).
  *
- * NOTE: When enabled, the global flag, will override the per-isolate flag.
- *
  * \param stream_mask A bitmask of streams that should be recorded.
  *
  * NOTE: Calling with 0 disables recording of all streams.
@@ -977,20 +966,6 @@
     intptr_t buffer_length,
     void* stream_callback_data);
 
-
-/**
- * Get the timeline for the current isolate in trace-event format
- *
- * \param consumer A Dart_StreamConsumer.
- * \param user_data User data passed into consumer.
- *
- * NOTE: The trace-event format is documented here: https://goo.gl/hDZw5M
- *
- * \return True if a stream was output.
- */
-DART_EXPORT bool Dart_TimelineGetTrace(Dart_StreamConsumer consumer,
-                                       void* user_data);
-
 /**
  * Get the timeline for entire VM (including all isolates).
  *
@@ -1007,8 +982,34 @@
 DART_EXPORT bool Dart_GlobalTimelineGetTrace(Dart_StreamConsumer consumer,
                                              void* user_data);
 
+typedef enum {
+  Dart_Timeline_Event_Begin,       // Phase = 'B'.
+  Dart_Timeline_Event_End,         // Phase = 'E'.
+  Dart_Timeline_Event_Instant,     // Phase = 'i'.
+  Dart_Timeline_Event_Duration,    // Phase = 'X'.
+} Dart_Timeline_Event_Type;
+
 /**
- * Add a duration timeline event to the embedder stream for the current isolate.
+ * Add a timeline event to the embedder stream.
+ *
+ * \param label The name of the evnet.
+ * \param timestamp0 The first timestamp of the event.
+ * \param timestamp1_or_async_id The second timestamp of the event or
+ *     the async id.
+ * \param argument_count The number of argument names and values.
+ * \param argument_names An array of names of the arguments.
+ * \param argument_values An array of values of the arguments.
+ */
+DART_EXPORT void Dart_TimelineEvent(const char* label,
+                                    int64_t timestamp0,
+                                    int64_t timestamp1_or_async_id,
+                                    Dart_Timeline_Event_Type type,
+                                    intptr_t argument_count,
+                                    const char** argument_names,
+                                    const char** argument_values);
+
+/**
+ * Add a duration timeline event to the embedder stream.
  *
  * \param label The name of the event.
  * \param start_micros The start of the duration (in microseconds)
@@ -1016,112 +1017,81 @@
  *
  * NOTE: All timestamps should be acquired from Dart_TimelineGetMicros.
  */
-DART_EXPORT Dart_Handle Dart_TimelineDuration(const char* label,
-                                              int64_t start_micros,
-                                              int64_t end_micros);
+DART_EXPORT void Dart_TimelineDuration(const char* label,
+                                       int64_t start_micros,
+                                       int64_t end_micros);
 
 
 /**
- * Add an instant timeline event to the embedder stream for the current isolate.
+ * Add an instant timeline event to the embedder stream.
  *
  * \param label The name of event.
  *
  * NOTE: All timestamps should be acquired from Dart_TimelineGetMicros.
  */
-DART_EXPORT Dart_Handle Dart_TimelineInstant(const char* label);
+DART_EXPORT void Dart_TimelineInstant(const char* label);
 
 
 /**
- * Adds an asynchronous begin timeline event to the embedder stream for the
- * current isolate.
+ * Adds an asynchronous begin timeline event to the embedder stream.
  *
  * \param label The name of event.
- *
- * \return Returns an asynchronous id that must be passed to
- * Dart_TimelineAsyncInstant and Dart_TimelineAsyncEnd. If the asynchronous
- * id is less than 0 the event was not added to the timeline and subsequent
- * calls to Dart_TimelineAsyncInstant and Dart_TimelineAsyncEnd will become
- * no-ops.
+ * \param async_id Pointer that receives the asynchronous id for this async
+ *   operation. If it is less than 0 the event was not added to the timeline.
  *
  * NOTE: All timestamps should be acquired from Dart_TimelineGetMicros.
  */
-DART_EXPORT Dart_Handle Dart_TimelineAsyncBegin(const char* label,
-                                                int64_t* async_id);
+DART_EXPORT void Dart_TimelineAsyncBegin(const char* label,
+                                         int64_t* async_id);
 
 
 /**
- * Adds an asynchronous instant timeline event to the embedder stream for the
- * current isolate.
+ * Adds an asynchronous instant timeline event to the embedder stream.
  *
  * \param label The name of event.
- *
- * \return Returns an asynchronous id that must be passed to
- * Dart_TimelineAsyncInstant and Dart_TimelineAsyncEnd.
+ * \param async_id the asynchronous id received by Dart_TimelineAsyncBegin.
  *
  * NOTE: All timestamps should be acquired from Dart_TimelineGetMicros.
  */
-DART_EXPORT Dart_Handle Dart_TimelineAsyncInstant(const char* label,
-                                                  int64_t async_id);
+DART_EXPORT void Dart_TimelineAsyncInstant(const char* label,
+                                           int64_t async_id);
 
 
 /**
- * Adds an asynchronous end timeline event to the embedder stream for the
- * current isolate.
+ * Adds an asynchronous end timeline event to the embedder stream.
  *
  * \param label The name of event.
- *
- * \return Returns an asynchronous id that must be passed to
- * Dart_TimelineAsyncInstant and Dart_TimelineAsyncEnd.
+ * \param async_id the asynchronous id received by Dart_TimelineAsyncBegin.
  *
  * NOTE: All timestamps should be acquired from Dart_TimelineGetMicros.
  */
-DART_EXPORT Dart_Handle Dart_TimelineAsyncEnd(const char* label,
-                                              int64_t async_id);
+DART_EXPORT void Dart_TimelineAsyncEnd(const char* label,
+                                       int64_t async_id);
 
 
 /**
- * Called by the VM to let the embedder know when to start recording into their
- * own timeline implementation. Can be called from any thread.
+ * Called by the VM to let the embedder know when to start recording into the
+ * timeline. Can be called from any thread.
  */
 typedef void (*Dart_EmbedderTimelineStartRecording)();
 
 /**
- * Called by the VM to let the embedder know when to stop recording into their
- * own timeline implementation. Can be called from any thread.
+ * Called by the VM to let the embedder know when to stop recording into the
+ * timeline. Can be called from any thread.
  */
 typedef void (*Dart_EmbedderTimelineStopRecording)();
 
 /**
- * Called by the VM to request data from the embedder's private timeline
- * implementation. Can be called from any thread and must complete
- * synchronously.
- *
- * \param stream_consumer The embedder must only call the stream_consumer with
- *    the Dart_StreamConsumer_kData state. See Dart_StreamConsumer above.
- * \param user_data
- *
- * \return Returns true on success.
- *
- */
-typedef bool (*Dart_EmbedderTimelineGetTimeline)(
-      Dart_StreamConsumer stream_consumer,
-      void* user_data);
-
-
-/**
  * Sets the embedder timeline callbacks. These callbacks are used by the VM
- * to notify the embedder of timeline recording state changes and to request
- * data from the embedder.
+ * to notify the embedder of timeline recording state changes.
  *
  * \param start_recording See Dart_EmbedderTimelineStartRecording.
  * \param stop_recording See Dart_EmbedderTimelineStopRecording.
- * \param get_timeline See Dart_EmbedderTimelineGetTimeline.
  *
  * NOTE: To avoid races, this should be called before Dart_Initialize.
  */
 DART_EXPORT void Dart_SetEmbedderTimelineCallbacks(
     Dart_EmbedderTimelineStartRecording start_recording,
-    Dart_EmbedderTimelineStopRecording stop_recording,
-    Dart_EmbedderTimelineGetTimeline get_timeline);
+    Dart_EmbedderTimelineStopRecording stop_recording);
 
 #endif  // INCLUDE_DART_TOOLS_API_H_
diff --git a/runtime/lib/bool_patch.dart b/runtime/lib/bool_patch.dart
index 8259f2e..274b153 100644
--- a/runtime/lib/bool_patch.dart
+++ b/runtime/lib/bool_patch.dart
@@ -13,4 +13,5 @@
   int get _identityHashCode {
     return this ? 1231 : 1237;
   }
+  int get hashCode => _identityHashCode;
 }
diff --git a/runtime/lib/integers.dart b/runtime/lib/integers.dart
index 9192b28..45500d6 100644
--- a/runtime/lib/integers.dart
+++ b/runtime/lib/integers.dart
@@ -410,9 +410,8 @@
     throw new UnsupportedError(
         "_Smi can only be allocated by the VM");
   }
-  int get _identityHashCode {
-    return this;
-  }
+  int get _identityHashCode => this;
+  int get hashCode => this;
   int operator ~() native "Smi_bitNegate";
   int get bitLength native "Smi_bitLength";
 
@@ -608,9 +607,8 @@
     throw new UnsupportedError(
         "_Mint can only be allocated by the VM");
   }
-  int get _identityHashCode {
-    return this;
-  }
+  int get _identityHashCode => this;
+  int get hashCode => this;
   int operator ~() native "Mint_bitNegate";
   int get bitLength native "Mint_bitLength";
 
diff --git a/runtime/lib/math.cc b/runtime/lib/math.cc
index d383471..8e5e750 100644
--- a/runtime/lib/math.cc
+++ b/runtime/lib/math.cc
@@ -205,7 +205,7 @@
   const intptr_t n = count.Value();
   ASSERT((n > 0) && (n <= 8));
   uint8_t buffer[8];
-  Dart_EntropySource entropy_source = isolate->entropy_source_callback();
+  Dart_EntropySource entropy_source = Dart::entropy_source_callback();
   if ((entropy_source == NULL) || !entropy_source(buffer, n)) {
     const String& error = String::Handle(String::New(
         "No source of cryptographically secure random numbers available."));
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index aaa28e1..d24f75c 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -253,8 +253,8 @@
 
 static RawInstance* CreateFunctionTypeMirror(const AbstractType& type) {
   ASSERT(type.IsFunctionType());
-  const Class& cls = Class::Handle(FunctionType::Cast(type).scope_class());
-  const Function& func = Function::Handle(FunctionType::Cast(type).signature());
+  const Class& cls = Class::Handle(Type::Cast(type).type_class());
+  const Function& func = Function::Handle(Type::Cast(type).signature());
   const Array& args = Array::Handle(Array::New(3));
   args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
   args.SetAt(1, MirrorReference::Handle(MirrorReference::New(func)));
@@ -543,8 +543,7 @@
   ASSERT(type.IsCanonical() || type.IsTypeParameter() || type.IsBoundedType());
 
   if (type.IsFunctionType()) {
-    const Class& scope_class =
-        Class::Handle(FunctionType::Cast(type).scope_class());
+    const Class& scope_class = Class::Handle(Type::Cast(type).type_class());
     if (scope_class.IsTypedefClass()) {
       return CreateTypedefMirror(scope_class,
                                  type, Bool::False(), Object::null_instance());
@@ -826,7 +825,7 @@
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   PROPAGATE_IF_MALFORMED(type);
   ASSERT(type.IsFinalized());
-  ASSERT(type.IsFunctionType() || type.HasResolvedTypeClass());
+  ASSERT(type.HasResolvedTypeClass());
   const Class& cls = Class::Handle(type.type_class());
   ASSERT(!cls.IsNull());
   if (cls.IsDynamicClass() || cls.IsVoidClass() || cls.IsTypedefClass()) {
@@ -1285,8 +1284,9 @@
 }
 
 DEFINE_NATIVE_ENTRY(TypedefMirror_declaration, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(FunctionType, type, arguments->NativeArgAt(0));
-  const Class& cls = Class::Handle(type.scope_class());
+  GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(0));
+  ASSERT(type.IsFunctionType());
+  const Class& cls = Class::Handle(type.type_class());
   ASSERT(cls.IsTypedefClass());
   return CreateTypedefMirror(cls,
                              AbstractType::Handle(cls.DeclarationType()),
@@ -2043,20 +2043,21 @@
 
 
 DEFINE_NATIVE_ENTRY(TypedefMirror_referent, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(FunctionType, type, arguments->NativeArgAt(0));
-  const Class& cls = Class::Handle(type.scope_class());
+  GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(0));
+  ASSERT(type.IsFunctionType());
+  const Class& cls = Class::Handle(type.type_class());
   ASSERT(cls.IsTypedefClass());
   const Function& sig_func = Function::Handle(cls.signature_function());
-  FunctionType& referent_type = FunctionType::Handle(sig_func.SignatureType());
+  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.scope_class());
+  ASSERT(cls.raw() == referent_type.type_class());
   if (!cls.IsGeneric()) {
-    referent_type = FunctionType::New(
+    referent_type = Type::New(
         Class::Handle(Isolate::Current()->object_store()->closure_class()),
         TypeArguments::Handle(referent_type.arguments()),
-        sig_func,
         referent_type.token_pos());
+    referent_type.set_signature(sig_func);
     referent_type ^= ClassFinalizer::FinalizeType(
         cls, referent_type, ClassFinalizer::kCanonicalize);
   }
diff --git a/runtime/lib/regexp.cc b/runtime/lib/regexp.cc
index e3907d3..9e9bcea 100644
--- a/runtime/lib/regexp.cc
+++ b/runtime/lib/regexp.cc
@@ -17,7 +17,7 @@
 DECLARE_FLAG(bool, trace_irregexp);
 
 
-DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_factory, 4) {
+DEFINE_NATIVE_ENTRY(RegExp_factory, 4) {
   ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(String, pattern, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(
@@ -35,37 +35,37 @@
     UNREACHABLE();
   }
 
-  // Create a JSRegExp object containing only the initial parameters.
-  return RegExpEngine::CreateJSRegExp(zone,
-                                      pattern,
-                                      multi_line,
-                                      ignore_case);
+  // Create a RegExp object containing only the initial parameters.
+  return RegExpEngine::CreateRegExp(zone,
+                                    pattern,
+                                    multi_line,
+                                    ignore_case);
 }
 
 
-DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_getPattern, 1) {
-  const JSRegExp& regexp = JSRegExp::CheckedHandle(arguments->NativeArgAt(0));
+DEFINE_NATIVE_ENTRY(RegExp_getPattern, 1) {
+  const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
   return regexp.pattern();
 }
 
 
-DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_getIsMultiLine, 1) {
-  const JSRegExp& regexp = JSRegExp::CheckedHandle(arguments->NativeArgAt(0));
+DEFINE_NATIVE_ENTRY(RegExp_getIsMultiLine, 1) {
+  const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
   return Bool::Get(regexp.is_multi_line()).raw();
 }
 
 
-DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_getIsCaseSensitive, 1) {
-  const JSRegExp& regexp = JSRegExp::CheckedHandle(arguments->NativeArgAt(0));
+DEFINE_NATIVE_ENTRY(RegExp_getIsCaseSensitive, 1) {
+  const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
   return Bool::Get(!regexp.is_ignore_case()).raw();
 }
 
 
-DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_getGroupCount, 1) {
-  const JSRegExp& regexp = JSRegExp::CheckedHandle(arguments->NativeArgAt(0));
+DEFINE_NATIVE_ENTRY(RegExp_getGroupCount, 1) {
+  const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
   if (regexp.is_initialized()) {
     return regexp.num_bracket_expressions();
@@ -81,9 +81,9 @@
 }
 
 
-DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_ExecuteMatch, 3) {
-  // This function is intrinsified. See Intrinsifier::JSRegExp_ExecuteMatch.
-  const JSRegExp& regexp = JSRegExp::CheckedHandle(arguments->NativeArgAt(0));
+DEFINE_NATIVE_ENTRY(RegExp_ExecuteMatch, 3) {
+  // This function is intrinsified. See Intrinsifier::RegExp_ExecuteMatch.
+  const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(String, subject, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_index, arguments->NativeArgAt(2));
diff --git a/runtime/lib/regexp_patch.dart b/runtime/lib/regexp_patch.dart
index 118b875..d8e622a 100644
--- a/runtime/lib/regexp_patch.dart
+++ b/runtime/lib/regexp_patch.dart
@@ -8,19 +8,19 @@
   /* patch */ factory RegExp(String source,
                              {bool multiLine: false,
                               bool caseSensitive: true}) {
-    _JSSyntaxRegExpHashKey key = new _JSSyntaxRegExpHashKey(
+    _RegExpHashKey key = new _RegExpHashKey(
         source, multiLine, caseSensitive);
-    _JSSyntaxRegExpHashValue value = _cache[key];
+    _RegExpHashValue value = _cache[key];
 
     if (value == null) {
       if (_cache.length > _MAX_CACHE_SIZE) {
-        _JSSyntaxRegExpHashKey lastKey = _recentlyUsed.last;
+        _RegExpHashKey lastKey = _recentlyUsed.last;
         lastKey.unlink();
         _cache.remove(lastKey);
       }
 
-      value = new _JSSyntaxRegExpHashValue(
-          new _JSSyntaxRegExp(source,
+      value = new _RegExpHashValue(
+          new _RegExp(source,
                               multiLine: multiLine,
                               caseSensitive: caseSensitive),
           key);
@@ -47,24 +47,24 @@
   // TODO(zerny): Use self-sizing cache similar to _AccessorCache in
   // mirrors_impl.dart.
   static const int _MAX_CACHE_SIZE = 256;
-  static final Map<_JSSyntaxRegExpHashKey, _JSSyntaxRegExpHashValue> _cache =
-      new HashMap<_JSSyntaxRegExpHashKey, _JSSyntaxRegExpHashValue>();
-  static final LinkedList<_JSSyntaxRegExpHashKey> _recentlyUsed =
-      new LinkedList<_JSSyntaxRegExpHashKey>();
+  static final Map<_RegExpHashKey, _RegExpHashValue> _cache =
+      new HashMap<_RegExpHashKey, _RegExpHashValue>();
+  static final LinkedList<_RegExpHashKey> _recentlyUsed =
+      new LinkedList<_RegExpHashKey>();
 }
 
 
 // Represents both a key in the regular expression cache as well as its
 // corresponding entry in the LRU list.
-class _JSSyntaxRegExpHashKey extends LinkedListEntry<_JSSyntaxRegExpHashKey> {
+class _RegExpHashKey extends LinkedListEntry<_RegExpHashKey> {
   final String pattern;
   final bool multiLine;
   final bool caseSensitive;
 
-  _JSSyntaxRegExpHashKey(this.pattern, this.multiLine, this.caseSensitive);
+  _RegExpHashKey(this.pattern, this.multiLine, this.caseSensitive);
 
   int get hashCode => pattern.hashCode;
-  bool operator==(_JSSyntaxRegExpHashKey that) {
+  bool operator==(_RegExpHashKey that) {
     return (this.pattern == that.pattern) &&
            (this.multiLine == that.multiLine) &&
            (this.caseSensitive == that.caseSensitive);
@@ -74,16 +74,16 @@
 
 // Represents a value in the regular expression cache. Contains a pointer
 // back to the key in order to access the corresponding LRU entry.
-class _JSSyntaxRegExpHashValue {
-  final _JSSyntaxRegExp regexp;
-  final _JSSyntaxRegExpHashKey key;
+class _RegExpHashValue {
+  final _RegExp regexp;
+  final _RegExpHashKey key;
 
-  _JSSyntaxRegExpHashValue(this.regexp, this.key);
+  _RegExpHashValue(this.regexp, this.key);
 }
 
 
-class _JSRegExpMatch implements Match {
-  _JSRegExpMatch(this._regexp, this.input, this._match);
+class _RegExpMatch implements Match {
+  _RegExpMatch(this._regexp, this.input, this._match);
 
   int get start => _start(0);
   int get end => _end(0);
@@ -132,11 +132,11 @@
 }
 
 
-class _JSSyntaxRegExp implements RegExp {
-  factory _JSSyntaxRegExp(
+class _RegExp implements RegExp {
+  factory _RegExp(
       String pattern,
       {bool multiLine: false,
-       bool caseSensitive: true}) native "JSSyntaxRegExp_factory";
+       bool caseSensitive: true}) native "RegExp_factory";
 
   Match firstMatch(String str) {
     if (str is! String) throw new ArgumentError(str);
@@ -144,7 +144,7 @@
     if (match == null) {
       return null;
     }
-    return new _JSRegExpMatch(this, str, match);
+    return new _RegExpMatch(this, str, match);
   }
 
   Iterable<Match> allMatches(String string, [int start = 0]) {
@@ -167,7 +167,7 @@
     List<int> list = _ExecuteMatch(string, start);
     if (list == null) return null;
     if (list[0] != start) return null;
-    return new _JSRegExpMatch(this, string, list);
+    return new _RegExpMatch(this, string, list);
   }
 
   bool hasMatch(String str) {
@@ -185,13 +185,13 @@
     return str._substringUnchecked(match[0], match[1]);
   }
 
-  String get pattern native "JSSyntaxRegExp_getPattern";
+  String get pattern native "RegExp_getPattern";
 
-  bool get isMultiLine native "JSSyntaxRegExp_getIsMultiLine";
+  bool get isMultiLine native "RegExp_getIsMultiLine";
 
-  bool get isCaseSensitive native "JSSyntaxRegExp_getIsCaseSensitive";
+  bool get isCaseSensitive native "RegExp_getIsCaseSensitive";
 
-  int get _groupCount native "JSSyntaxRegExp_getGroupCount";
+  int get _groupCount native "RegExp_getGroupCount";
 
   // Byte map of one byte characters with a 0xff if the character is a word
   // character (digit, letter or underscore) and 0x00 otherwise.
@@ -239,11 +239,11 @@
   ];
 
   List _ExecuteMatch(String str, int start_index)
-      native "JSSyntaxRegExp_ExecuteMatch";
+      native "RegExp_ExecuteMatch";
 }
 
 class _AllMatchesIterable extends IterableBase<Match> {
-  final _JSSyntaxRegExp _re;
+  final _RegExp _re;
   final String _str;
   final int _start;
 
@@ -255,7 +255,7 @@
 class _AllMatchesIterator implements Iterator<Match> {
   final String _str;
   int _nextIndex;
-  _JSSyntaxRegExp _re;
+  _RegExp _re;
   Match _current;
 
   _AllMatchesIterator(this._re, this._str, this._nextIndex);
@@ -267,7 +267,7 @@
     if (_nextIndex <= _str.length) {
       var match = _re._ExecuteMatch(_str, _nextIndex);
       if (match != null) {
-        _current = new _JSRegExpMatch(_re, _str, match);
+        _current = new _RegExpMatch(_re, _str, match);
         _nextIndex = _current.end;
         if (_nextIndex == _current.start) {
           // Zero-width match. Advance by one more.
diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart
index eb1a2a2..cdb94be 100644
--- a/runtime/lib/string_patch.dart
+++ b/runtime/lib/string_patch.dart
@@ -801,6 +801,7 @@
 
   // Convert single object to string.
   static String _interpolateSingle(Object o) {
+    if (o is String) return o;
     final s = o.toString();
     if (s is! String) {
       throw new ArgumentError(s);
diff --git a/runtime/lib/timeline.cc b/runtime/lib/timeline.cc
index ddc2f5a..df36a25 100644
--- a/runtime/lib/timeline.cc
+++ b/runtime/lib/timeline.cc
@@ -53,7 +53,7 @@
     return Object::null();
   }
 
-  TimelineEvent* event = isolate->GetDartStream()->StartEvent();
+  TimelineEvent* event = Timeline::GetDartStream()->StartEvent();
   if (event == NULL) {
     // Stream was turned off.
     return Object::null();
@@ -118,7 +118,7 @@
     return Object::null();
   }
 
-  TimelineEvent* event = isolate->GetDartStream()->StartEvent();
+  TimelineEvent* event = Timeline::GetDartStream()->StartEvent();
   if (event == NULL) {
     // Stream was turned off.
     return Object::null();
@@ -163,7 +163,7 @@
     return Object::null();
   }
 
-  TimelineEvent* event = isolate->GetDartStream()->StartEvent();
+  TimelineEvent* event = Timeline::GetDartStream()->StartEvent();
   if (event == NULL) {
     // Stream was turned off.
     return Object::null();
diff --git a/runtime/lib/type_patch.dart b/runtime/lib/type_patch.dart
index 5d0f305..67d7db5 100644
--- a/runtime/lib/type_patch.dart
+++ b/runtime/lib/type_patch.dart
@@ -13,10 +13,6 @@
 class _Type extends _AbstractType {
 }
 
-// Equivalent of RawFunctionType.
-class _FunctionType extends _AbstractType {
-}
-
 // Equivalent of RawTypeRef.
 class _TypeRef extends _AbstractType {
 }
diff --git a/runtime/lib/typed_data.dart b/runtime/lib/typed_data.dart
index 3abb630..c4b532f 100644
--- a/runtime/lib/typed_data.dart
+++ b/runtime/lib/typed_data.dart
@@ -2,233 +2,84 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// patch classes for Int8List ..... Float64List and ByteData implementations.
+library dart.typed_data;
 
 import "dart:_internal";
+import "dart:collection" show ListBase;
 import 'dart:math' show Random;
 
-patch class Int8List {
-  /* patch */ factory Int8List(int length) {
-    return new _Int8Array(length);
-  }
+/**
+ * A typed view of a sequence of bytes.
+ */
+abstract class TypedData {
+  /**
+   * Returns the number of bytes in the representation of each element in this
+   * list.
+   */
+  int get elementSizeInBytes;
 
-  /* patch */ factory Int8List.fromList(List<int> elements) {
-    return new _Int8Array(elements.length)
-        ..setRange(0, elements.length, elements);
-  }
+  /**
+   * Returns the offset in bytes into the underlying byte buffer of this view.
+   */
+  int get offsetInBytes;
+
+  /**
+   * Returns the length of this view, in bytes.
+   */
+  int get lengthInBytes;
+
+  /**
+   * Returns the byte buffer associated with this object.
+   */
+  ByteBuffer get buffer;
 }
 
 
-patch class Uint8List {
-  /* patch */ factory Uint8List(int length) {
-    return new _Uint8Array(length);
-  }
+/**
+ * Describes endianness to be used when accessing or updating a
+ * sequence of bytes.
+ */
+class Endianness {
+  const Endianness._(this._littleEndian);
 
-  /* patch */ factory Uint8List.fromList(List<int> elements) {
-    return new _Uint8Array(elements.length)
-        ..setRange(0, elements.length, elements);
-  }
+  static const Endianness BIG_ENDIAN = const Endianness._(false);
+  static const Endianness LITTLE_ENDIAN = const Endianness._(true);
+  static final Endianness HOST_ENDIAN =
+    (new ByteData.view(new Uint16List.fromList([1]).buffer)).getInt8(0) == 1 ?
+    LITTLE_ENDIAN : BIG_ENDIAN;
+
+  final bool _littleEndian;
 }
 
 
-patch class Uint8ClampedList {
-  /* patch */ factory Uint8ClampedList(int length) {
-    return new _Uint8ClampedArray(length);
-  }
-
-  /* patch */ factory Uint8ClampedList.fromList(List<int> elements) {
-    return new _Uint8ClampedArray(elements.length)
-        ..setRange(0, elements.length, elements);
-  }
-}
-
-
-patch class Int16List {
-  /* patch */ factory Int16List(int length) {
-    return new _Int16Array(length);
-  }
-
-  /* patch */ factory Int16List.fromList(List<int> elements) {
-    return new _Int16Array(elements.length)
-        ..setRange(0, elements.length, elements);
-  }
-}
-
-
-patch class Uint16List {
-  /* patch */ factory Uint16List(int length) {
-    return new _Uint16Array(length);
-  }
-
-  /* patch */ factory Uint16List.fromList(List<int> elements) {
-    return new _Uint16Array(elements.length)
-        ..setRange(0, elements.length, elements);
-  }
-}
-
-
-patch class Int32List {
-  /* patch */ factory Int32List(int length) {
-    return new _Int32Array(length);
-  }
-
-  /* patch */ factory Int32List.fromList(List<int> elements) {
-    return new _Int32Array(elements.length)
-        ..setRange(0, elements.length, elements);
-  }
-}
-
-
-patch class Uint32List {
-  /* patch */ factory Uint32List(int length) {
-    return new _Uint32Array(length);
-  }
-
-  /* patch */ factory Uint32List.fromList(List<int> elements) {
-    return new _Uint32Array(elements.length)
-        ..setRange(0, elements.length, elements);
-  }
-}
-
-
-patch class Int64List {
-  /* patch */ factory Int64List(int length) {
-    return new _Int64Array(length);
-  }
-
-  /* patch */ factory Int64List.fromList(List<int> elements) {
-    return new _Int64Array(elements.length)
-        ..setRange(0, elements.length, elements);
-  }
-}
-
-
-patch class Uint64List {
-  /* patch */ factory Uint64List(int length) {
-    return new _Uint64Array(length);
-  }
-
-  /* patch */ factory Uint64List.fromList(List<int> elements) {
-    return new _Uint64Array(elements.length)
-        ..setRange(0, elements.length, elements);
-  }
-}
-
-
-patch class Float32List {
-  /* patch */ factory Float32List(int length) {
-    return new _Float32Array(length);
-  }
-
-  /* patch */ factory Float32List.fromList(List<double> elements) {
-    return new _Float32Array(elements.length)
-        ..setRange(0, elements.length, elements);
-  }
-}
-
-
-patch class Float64List {
-  /* patch */ factory Float64List(int length) {
-    return new _Float64Array(length);
-  }
-
-  /* patch */ factory Float64List.fromList(List<double> elements) {
-    return new _Float64Array(elements.length)
-        ..setRange(0, elements.length, elements);
-  }
-}
-
-
-patch class Float32x4List {
-  /* patch */ factory Float32x4List(int length) {
-    return new _Float32x4Array(length);
-  }
-
-  /* patch */ factory Float32x4List.fromList(List<Float32x4> elements) {
-    return new _Float32x4Array(elements.length)
-        ..setRange(0, elements.length, elements);
-  }
-}
-
-
-patch class Int32x4List {
-  /* patch */ factory Int32x4List(int length) {
-    return new _Int32x4Array(length);
-  }
-
-  /* patch */ factory Int32x4List.fromList(List<Int32x4> elements) {
-    return new _Int32x4Array(elements.length)
-        ..setRange(0, elements.length, elements);
-  }
-
-}
-
-patch class Float64x2List {
-  /* patch */ factory Float64x2List(int length) {
-    return new _Float64x2Array(length);
-  }
-
-  /* patch */ factory Float64x2List.fromList(List<Float64x2> elements) {
-    return new _Float64x2Array(elements.length)
-        ..setRange(0, elements.length, elements);
-  }
-}
-
-
-patch class Float32x4 {
-  /* patch */ factory Float32x4(double x, double y, double z, double w) {
-    return new _Float32x4(x, y, z, w);
-  }
-  /* patch */ factory Float32x4.splat(double v) {
-    return new _Float32x4.splat(v);
-  }
-  /* patch */ factory Float32x4.zero() {
-    return new _Float32x4.zero();
-  }
-  /* patch */ factory Float32x4.fromInt32x4Bits(Int32x4 x) {
-    return new _Float32x4.fromInt32x4Bits(x);
-  }
-  /* patch */ factory Float32x4.fromFloat64x2(Float64x2 v) {
-    return new _Float32x4.fromFloat64x2(v);
-  }
-}
-
-
-patch class Int32x4 {
-  /* patch */ factory Int32x4(int x, int y, int z, int w) {
-    return new _Int32x4(x, y, z, w);
-  }
-  /* patch */ factory Int32x4.bool(bool x, bool y, bool z, bool w) {
-    return new _Int32x4.bool(x, y, z, w);
-  }
-  /* patch */ factory Int32x4.fromFloat32x4Bits(Float32x4 x) {
-    return new _Int32x4.fromFloat32x4Bits(x);
-  }
-}
-
-
-patch class Float64x2 {
-  /* patch */ factory Float64x2(double x, double y) {
-    return new _Float64x2(x, y);
-  }
-
-  /* patch */ factory Float64x2.splat(double v) {
-    return new _Float64x2.splat(v);
-  }
-
-  /* patch */ factory Float64x2.zero() {
-    return new _Float64x2.zero();
-  }
-
-  /* patch */ factory Float64x2.fromFloat32x4(Float32x4 v) {
-    return new _Float64x2.fromFloat32x4(v);
-  }
-}
-
-
-patch class ByteData {
-  /* patch */ factory ByteData(int length) {
-    var list = new _Uint8Array(length);
+/**
+ * A fixed-length, random-access sequence of bytes that also provides random
+ * and unaligned access to the fixed-width integers and floating point
+ * numbers represented by those bytes.
+ *
+ * `ByteData` may be used to pack and unpack data from external sources
+ * (such as networks or files systems), and to process large quantities
+ * of numerical data more efficiently than would be possible
+ * with ordinary [List] implementations.
+ * `ByteData` can save space, by eliminating the need for object headers,
+ * and time, by eliminating the need for data copies.
+ * Finally, `ByteData` may be used to intentionally reinterpret the bytes
+ * representing one arithmetic type as another.
+ * For example this code fragment determine what 32-bit signed integer
+ * is represented by the bytes of a 32-bit floating point number:
+ *
+ *     var buffer = new Uint8List(8).buffer;
+ *     var bdata = new ByteData.view(buffer);
+ *     bdata.setFloat32(0, 3.04);
+ *     int huh = bdata.getInt32(0);
+ */
+class ByteData implements TypedData {
+  /**
+   * Creates a [ByteData] of the specified length (in elements), all of
+   * whose bytes are initially zero.
+   */
+  factory ByteData(int length) {
+    var list = new Uint8List(length);
     return new _ByteDataView(list, 0, length);
   }
 
@@ -236,6 +87,292 @@
   factory ByteData._view(TypedData typedData, int offsetInBytes, int length) {
     return new _ByteDataView(typedData, offsetInBytes, length);
   }
+
+  /**
+   * Creates an [ByteData] _view_ of the specified region in [buffer].
+   *
+   * Changes in the [ByteData] will be visible in the byte
+   * buffer and vice versa.
+   * If the [offsetInBytes] index of the region is not specified,
+   * it defaults to zero (the first byte in the byte buffer).
+   * If the length is not specified, it defaults to `null`,
+   * which indicates that the view extends to the end of the byte buffer.
+   *
+   * Throws [RangeError] if [offsetInBytes] or [length] are negative, or
+   * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than
+   * the length of [buffer].
+   */
+  factory ByteData.view(ByteBuffer buffer,
+                        [int offsetInBytes = 0, int length]) {
+    return buffer.asByteData(offsetInBytes, length);
+  }
+
+  /**
+   * Returns the (possibly negative) integer represented by the byte at the
+   * specified [byteOffset] in this object, in two's complement binary
+   * representation.
+   *
+   * The return value will be between -128 and 127, inclusive.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * greater than or equal to the length of this object.
+   */
+  int getInt8(int byteOffset);
+
+  /**
+   * Sets the byte at the specified [byteOffset] in this object to the
+   * two's complement binary representation of the specified [value], which
+   * must fit in a single byte.
+   *
+   * In other words, [value] must be between -128 and 127, inclusive.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * greater than or equal to the length of this object.
+   */
+  void setInt8(int byteOffset, int value);
+
+  /**
+   * Returns the positive integer represented by the byte at the specified
+   * [byteOffset] in this object, in unsigned binary form.
+   *
+   * The return value will be between 0 and 255, inclusive.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * greater than or equal to the length of this object.
+   */
+  int getUint8(int byteOffset);
+
+  /**
+   * Sets the byte at the specified [byteOffset] in this object to the
+   * unsigned binary representation of the specified [value], which must fit
+   * in a single byte.
+   *
+   * In other words, [value] must be between 0 and 255, inclusive.
+   *
+   * Throws [RangeError] if [byteOffset] is negative,
+   * or greater than or equal to the length of this object.
+   */
+  void setUint8(int byteOffset, int value);
+
+  /**
+   * Returns the (possibly negative) integer represented by the two bytes at
+   * the specified [byteOffset] in this object, in two's complement binary
+   * form.
+   *
+   * The return value will be between 2<sup>15</sup> and 2<sup>15</sup> - 1,
+   * inclusive.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 2` is greater than the length of this object.
+   */
+  int getInt16(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]);
+
+  /**
+   * Sets the two bytes starting at the specified [byteOffset] in this
+   * object to the two's complement binary representation of the specified
+   * [value], which must fit in two bytes.
+   *
+   * In other words, [value] must lie
+   * between 2<sup>15</sup> and 2<sup>15</sup> - 1, inclusive.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 2` is greater than the length of this object.
+   */
+  void setInt16(int byteOffset,
+                int value,
+                [Endianness endian = Endianness.BIG_ENDIAN]);
+
+  /**
+   * Returns the positive integer represented by the two bytes starting
+   * at the specified [byteOffset] in this object, in unsigned binary
+   * form.
+   *
+   * The return value will be between 0 and  2<sup>16</sup> - 1, inclusive.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 2` is greater than the length of this object.
+   */
+  int getUint16(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]);
+
+  /**
+   * Sets the two bytes starting at the specified [byteOffset] in this object
+   * to the unsigned binary representation of the specified [value],
+   * which must fit in two bytes.
+   *
+   * In other words, [value] must be between
+   * 0 and 2<sup>16</sup> - 1, inclusive.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 2` is greater than the length of this object.
+   */
+  void setUint16(int byteOffset,
+                 int value,
+                 [Endianness endian = Endianness.BIG_ENDIAN]);
+
+  /**
+   * Returns the (possibly negative) integer represented by the four bytes at
+   * the specified [byteOffset] in this object, in two's complement binary
+   * form.
+   *
+   * The return value will be between 2<sup>31</sup> and 2<sup>31</sup> - 1,
+   * inclusive.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 4` is greater than the length of this object.
+   */
+  int getInt32(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]);
+
+  /**
+   * Sets the four bytes starting at the specified [byteOffset] in this
+   * object to the two's complement binary representation of the specified
+   * [value], which must fit in four bytes.
+   *
+   * In other words, [value] must lie
+   * between 2<sup>31</sup> and 2<sup>31</sup> - 1, inclusive.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 4` is greater than the length of this object.
+   */
+  void setInt32(int byteOffset,
+                int value,
+                [Endianness endian = Endianness.BIG_ENDIAN]);
+
+  /**
+   * Returns the positive integer represented by the four bytes starting
+   * at the specified [byteOffset] in this object, in unsigned binary
+   * form.
+   *
+   * The return value will be between 0 and  2<sup>32</sup> - 1, inclusive.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 4` is greater than the length of this object.
+   */
+  int getUint32(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]);
+
+  /**
+   * Sets the four bytes starting at the specified [byteOffset] in this object
+   * to the unsigned binary representation of the specified [value],
+   * which must fit in four bytes.
+   *
+   * In other words, [value] must be between
+   * 0 and 2<sup>32</sup> - 1, inclusive.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 4` is greater than the length of this object.
+   */
+  void setUint32(int byteOffset,
+                 int value,
+                 [Endianness endian = Endianness.BIG_ENDIAN]);
+
+  /**
+   * Returns the (possibly negative) integer represented by the eight bytes at
+   * the specified [byteOffset] in this object, in two's complement binary
+   * form.
+   *
+   * The return value will be between 2<sup>63</sup> and 2<sup>63</sup> - 1,
+   * inclusive.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 8` is greater than the length of this object.
+   */
+  int getInt64(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]);
+
+  /**
+   * Sets the eight bytes starting at the specified [byteOffset] in this
+   * object to the two's complement binary representation of the specified
+   * [value], which must fit in eight bytes.
+   *
+   * In other words, [value] must lie
+   * between 2<sup>63</sup> and 2<sup>63</sup> - 1, inclusive.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 8` is greater than the length of this object.
+   */
+  void setInt64(int byteOffset,
+                int value,
+                [Endianness endian = Endianness.BIG_ENDIAN]);
+
+  /**
+   * Returns the positive integer represented by the eight bytes starting
+   * at the specified [byteOffset] in this object, in unsigned binary
+   * form.
+   *
+   * The return value will be between 0 and  2<sup>64</sup> - 1, inclusive.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 8` is greater than the length of this object.
+   */
+  int getUint64(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]);
+
+  /**
+   * Sets the eight bytes starting at the specified [byteOffset] in this object
+   * to the unsigned binary representation of the specified [value],
+   * which must fit in eight bytes.
+   *
+   * In other words, [value] must be between
+   * 0 and 2<sup>64</sup> - 1, inclusive.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 8` is greater than the length of this object.
+   */
+  void setUint64(int byteOffset,
+                 int value,
+                 [Endianness endian = Endianness.BIG_ENDIAN]);
+
+  /**
+   * Returns the floating point number represented by the four bytes at
+   * the specified [byteOffset] in this object, in IEEE 754
+   * single-precision binary floating-point format (binary32).
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 4` is greater than the length of this object.
+   */
+  double getFloat32(int byteOffset,
+                    [Endianness endian = Endianness.BIG_ENDIAN]);
+
+  /**
+   * Sets the four bytes starting at the specified [byteOffset] in this
+   * object to the IEEE 754 single-precision binary floating-point
+   * (binary32) representation of the specified [value].
+   *
+   * **Note that this method can lose precision.** The input [value] is
+   * a 64-bit floating point value, which will be converted to 32-bit
+   * floating point value by IEEE 754 rounding rules before it is stored.
+   * If [value] cannot be represented exactly as a binary32, it will be
+   * converted to the nearest binary32 value.  If two binary32 values are
+   * equally close, the one whose least significant bit is zero will be used.
+   * Note that finite (but large) values can be converted to infinity, and
+   * small non-zero values can be converted to zero.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 4` is greater than the length of this object.
+   */
+  void setFloat32(int byteOffset,
+                  double value,
+                  [Endianness endian = Endianness.BIG_ENDIAN]);
+
+  /**
+   * Returns the floating point number represented by the eight bytes at
+   * the specified [byteOffset] in this object, in IEEE 754
+   * double-precision binary floating-point format (binary64).
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 8` is greater than the length of this object.
+   */
+  double getFloat64(int byteOffset,
+                    [Endianness endian = Endianness.BIG_ENDIAN]);
+
+  /**
+   * Sets the eight bytes starting at the specified [byteOffset] in this
+   * object to the IEEE 754 double-precision binary floating-point
+   * (binary64) representation of the specified [value].
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 8` is greater than the length of this object.
+   */
+  void setFloat64(int byteOffset,
+                  double value,
+                  [Endianness endian = Endianness.BIG_ENDIAN]);
 }
 
 
@@ -711,18 +848,18 @@
 }
 
 
-class _ByteBuffer implements ByteBuffer {
+class ByteBuffer {
   final _TypedList _data;
 
-  _ByteBuffer(this._data);
+  ByteBuffer(this._data);
 
-  factory _ByteBuffer._New(data) => new _ByteBuffer(data);
+  factory ByteBuffer._New(data) => new ByteBuffer(data);
 
   // Forward calls to _data.
   int get lengthInBytes => _data.lengthInBytes;
   int get hashCode => _data.hashCode;
   bool operator==(Object other) =>
-      (other is _ByteBuffer) && identical(_data, other._data);
+      (other is ByteBuffer) && identical(_data, other._data);
 
   ByteData asByteData([int offsetInBytes = 0, int length]) {
     if (length == null) {
@@ -852,7 +989,7 @@
     return length * elementSizeInBytes;
   }
 
-  ByteBuffer get buffer => new _ByteBuffer(this);
+  ByteBuffer get buffer => new ByteBuffer(this);
 
   // Methods implementing the collection interface.
 
@@ -924,10 +1061,20 @@
 }
 
 
-class _Int8Array extends _TypedList with _IntListMixin implements Int8List {
+class Int8List extends _TypedList with _IntListMixin implements List<int>, TypedData {
   // Factory constructors.
 
-  factory _Int8Array(int length) native "TypedData_Int8Array_new";
+  factory Int8List(int length) native "TypedData_Int8Array_new";
+
+  factory Int8List.fromList(List<int> elements) {
+    return new Int8List(elements.length)
+        ..setRange(0, elements.length, elements);
+  }
+
+  factory Int8List.view(ByteBuffer buffer,
+                        [int offsetInBytes = 0, int length]) {
+    return buffer.asInt8List(offsetInBytes, length);
+  }
 
   // Method(s) implementing List interface.
 
@@ -945,6 +1092,7 @@
     _setInt8(index, _toInt8(value));
   }
 
+  static const int BYTES_PER_ELEMENT = 1;
 
   // Method(s) implementing TypedData interface.
 
@@ -955,16 +1103,26 @@
 
   // Internal utility methods.
 
-  _Int8Array _createList(int length) {
-    return new _Int8Array(length);
+  Int8List _createList(int length) {
+    return new Int8List(length);
   }
 }
 
 
-class _Uint8Array extends _TypedList with _IntListMixin implements Uint8List {
+class Uint8List extends _TypedList with _IntListMixin implements List<int>, TypedData {
   // Factory constructors.
 
-  factory _Uint8Array(int length) native "TypedData_Uint8Array_new";
+  factory Uint8List(int length) native "TypedData_Uint8Array_new";
+
+  factory Uint8List.fromList(List<int> elements) {
+    return new Uint8List(elements.length)
+        ..setRange(0, elements.length, elements);
+  }
+
+  factory Uint8List.view(ByteBuffer buffer,
+                         [int offsetInBytes = 0, int length]) {
+    return buffer.asUint8List(offsetInBytes, length);
+  }
 
   // Methods implementing List interface.
   int operator[](int index) {
@@ -981,6 +1139,7 @@
     _setUint8(index, _toUint8(value));
   }
 
+  static const int BYTES_PER_ELEMENT = 1;
 
   // Methods implementing TypedData interface.
   int get elementSizeInBytes {
@@ -990,16 +1149,26 @@
 
   // Internal utility methods.
 
-  _Uint8Array _createList(int length) {
-    return new _Uint8Array(length);
+  Uint8List _createList(int length) {
+    return new Uint8List(length);
   }
 }
 
 
-class _Uint8ClampedArray extends _TypedList with _IntListMixin implements Uint8ClampedList {
+class Uint8ClampedList extends _TypedList with _IntListMixin implements List<int>, TypedData {
   // Factory constructors.
 
-  factory _Uint8ClampedArray(int length) native "TypedData_Uint8ClampedArray_new";
+  factory Uint8ClampedList(int length) native "TypedData_Uint8ClampedArray_new";
+
+  factory Uint8ClampedList.fromList(List<int> elements) {
+    return new Uint8ClampedList(elements.length)
+        ..setRange(0, elements.length, elements);
+  }
+
+  factory Uint8ClampedList.view(ByteBuffer buffer,
+                                [int offsetInBytes = 0, int length]) {
+    return buffer.asUint8ClampedList(offsetInBytes, length);
+  }
 
   // Methods implementing List interface.
 
@@ -1017,6 +1186,7 @@
     _setUint8(index, _toClampedUint8(value));
   }
 
+  static const int BYTES_PER_ELEMENT = 1;
 
   // Methods implementing TypedData interface.
   int get elementSizeInBytes {
@@ -1026,16 +1196,26 @@
 
   // Internal utility methods.
 
-  _Uint8ClampedArray _createList(int length) {
-    return new _Uint8ClampedArray(length);
+  Uint8ClampedList _createList(int length) {
+    return new Uint8ClampedList(length);
   }
 }
 
 
-class _Int16Array extends _TypedList with _IntListMixin implements Int16List {
+class Int16List extends _TypedList with _IntListMixin implements List<int>, TypedData {
   // Factory constructors.
 
-  factory _Int16Array(int length) native "TypedData_Int16Array_new";
+  factory Int16List(int length) native "TypedData_Int16Array_new";
+
+  factory Int16List.fromList(List<int> elements) {
+    return new Int16List(elements.length)
+        ..setRange(0, elements.length, elements);
+  }
+
+  factory Int16List.view(ByteBuffer buffer,
+                         [int offsetInBytes = 0, int length]) {
+    return buffer.asInt16List(offsetInBytes, length);
+  }
 
   // Method(s) implementing List interface.
 
@@ -1065,6 +1245,7 @@
   }
 
   // Method(s) implementing TypedData interface.
+  static const int BYTES_PER_ELEMENT = 2;
 
   int get elementSizeInBytes {
     return Int16List.BYTES_PER_ELEMENT;
@@ -1073,8 +1254,8 @@
 
   // Internal utility methods.
 
-  _Int16Array _createList(int length) {
-    return new _Int16Array(length);
+  Int16List _createList(int length) {
+    return new Int16List(length);
   }
 
   int _getIndexedInt16(int index) {
@@ -1087,10 +1268,20 @@
 }
 
 
-class _Uint16Array extends _TypedList with _IntListMixin implements Uint16List {
+class Uint16List extends _TypedList with _IntListMixin implements List<int>, TypedData {
   // Factory constructors.
 
-  factory _Uint16Array(int length) native "TypedData_Uint16Array_new";
+  factory Uint16List(int length) native "TypedData_Uint16Array_new";
+
+  factory Uint16List.fromList(List<int> elements) {
+    return new Uint16List(elements.length)
+        ..setRange(0, elements.length, elements);
+  }
+
+  factory Uint16List.view(ByteBuffer buffer,
+                          [int offsetInBytes = 0, int length]) {
+    return buffer.asUint16List(offsetInBytes, length);
+  }
 
   // Method(s) implementing the List interface.
 
@@ -1120,6 +1311,7 @@
   }
 
   // Method(s) implementing the TypedData interface.
+  static const int BYTES_PER_ELEMENT = 2;
 
   int get elementSizeInBytes {
     return Uint16List.BYTES_PER_ELEMENT;
@@ -1128,8 +1320,8 @@
 
   // Internal utility methods.
 
-  _Uint16Array _createList(int length) {
-    return new _Uint16Array(length);
+  Uint16List _createList(int length) {
+    return new Uint16List(length);
   }
 
   int _getIndexedUint16(int index) {
@@ -1142,10 +1334,20 @@
 }
 
 
-class _Int32Array extends _TypedList with _IntListMixin implements Int32List {
+class Int32List extends _TypedList with _IntListMixin implements List<int>, TypedData {
   // Factory constructors.
 
-  factory _Int32Array(int length) native "TypedData_Int32Array_new";
+  factory Int32List(int length) native "TypedData_Int32Array_new";
+
+  factory Int32List.fromList(List<int> elements) {
+    return new Int32List(elements.length)
+        ..setRange(0, elements.length, elements);
+  }
+
+  factory Int32List.view(ByteBuffer buffer,
+                         [int offsetInBytes = 0, int length]) {
+    return buffer.asInt32List(offsetInBytes, length);
+  }
 
   // Method(s) implementing the List interface.
 
@@ -1165,6 +1367,7 @@
 
 
   // Method(s) implementing TypedData interface.
+  static const int BYTES_PER_ELEMENT = 4;
 
   int get elementSizeInBytes {
     return Int32List.BYTES_PER_ELEMENT;
@@ -1173,8 +1376,8 @@
 
   // Internal utility methods.
 
-  _Int32Array _createList(int length) {
-    return new _Int32Array(length);
+  Int32List _createList(int length) {
+    return new Int32List(length);
   }
 
   int _getIndexedInt32(int index) {
@@ -1188,10 +1391,20 @@
 }
 
 
-class _Uint32Array extends _TypedList with _IntListMixin implements Uint32List {
+class Uint32List extends _TypedList with _IntListMixin implements List<int>, TypedData {
   // Factory constructors.
 
-  factory _Uint32Array(int length) native "TypedData_Uint32Array_new";
+  factory Uint32List(int length) native "TypedData_Uint32Array_new";
+
+  factory Uint32List.fromList(List<int> elements) {
+    return new Uint32List(elements.length)
+        ..setRange(0, elements.length, elements);
+  }
+
+  factory Uint32List.view(ByteBuffer buffer,
+                          [int offsetInBytes = 0, int length]) {
+    return buffer.asUint32List(offsetInBytes, length);
+  }
 
   // Method(s) implementing the List interface.
 
@@ -1211,6 +1424,7 @@
 
 
   // Method(s) implementing the TypedData interface.
+  static const int BYTES_PER_ELEMENT = 4;
 
   int get elementSizeInBytes {
     return Uint32List.BYTES_PER_ELEMENT;
@@ -1219,8 +1433,8 @@
 
   // Internal utility methods.
 
-  _Uint32Array _createList(int length) {
-    return new _Uint32Array(length);
+  Uint32List _createList(int length) {
+    return new Uint32List(length);
   }
 
   int _getIndexedUint32(int index) {
@@ -1233,10 +1447,20 @@
 }
 
 
-class _Int64Array extends _TypedList with _IntListMixin implements Int64List {
+class Int64List extends _TypedList with _IntListMixin implements List<int>, TypedData {
   // Factory constructors.
 
-  factory _Int64Array(int length) native "TypedData_Int64Array_new";
+  factory Int64List(int length) native "TypedData_Int64Array_new";
+
+  factory Int64List.fromList(List<int> elements) {
+    return new Int64List(elements.length)
+        ..setRange(0, elements.length, elements);
+  }
+
+  factory Int64List.view(ByteBuffer buffer,
+                         [int offsetInBytes = 0, int length]) {
+    return buffer.asInt64List(offsetInBytes, length);
+  }
 
   // Method(s) implementing the List interface.
 
@@ -1256,6 +1480,7 @@
 
 
   // Method(s) implementing the TypedData interface.
+  static const int BYTES_PER_ELEMENT = 8;
 
   int get elementSizeInBytes {
     return Int64List.BYTES_PER_ELEMENT;
@@ -1264,8 +1489,8 @@
 
   // Internal utility methods.
 
-  _Int64Array _createList(int length) {
-    return new _Int64Array(length);
+  Int64List _createList(int length) {
+    return new Int64List(length);
   }
 
   int _getIndexedInt64(int index) {
@@ -1278,10 +1503,20 @@
 }
 
 
-class _Uint64Array extends _TypedList with _IntListMixin implements Uint64List {
+class Uint64List extends _TypedList with _IntListMixin implements List<int>, TypedData {
   // Factory constructors.
 
-  factory _Uint64Array(int length) native "TypedData_Uint64Array_new";
+  factory Uint64List(int length) native "TypedData_Uint64Array_new";
+
+  factory Uint64List.fromList(List<int> elements) {
+    return new Uint64List(elements.length)
+        ..setRange(0, elements.length, elements);
+  }
+
+  factory Uint64List.view(ByteBuffer buffer,
+                          [int offsetInBytes = 0, int length]) {
+    return buffer.asUint64List(offsetInBytes, length);
+  }
 
   // Method(s) implementing the List interface.
 
@@ -1301,6 +1536,7 @@
 
 
   // Method(s) implementing the TypedData interface.
+  static const int BYTES_PER_ELEMENT = 8;
 
   int get elementSizeInBytes {
     return Uint64List.BYTES_PER_ELEMENT;
@@ -1309,8 +1545,8 @@
 
   // Internal utility methods.
 
-  _Uint64Array _createList(int length) {
-    return new _Uint64Array(length);
+  Uint64List _createList(int length) {
+    return new Uint64List(length);
   }
 
   int _getIndexedUint64(int index) {
@@ -1323,10 +1559,20 @@
 }
 
 
-class _Float32Array extends _TypedList with _DoubleListMixin implements Float32List {
+class Float32List extends _TypedList with _DoubleListMixin implements List<double>, TypedData {
   // Factory constructors.
 
-  factory _Float32Array(int length) native "TypedData_Float32Array_new";
+  factory Float32List(int length) native "TypedData_Float32Array_new";
+
+  factory Float32List.fromList(List<double> elements) {
+    return new Float32List(elements.length)
+        ..setRange(0, elements.length, elements);
+  }
+
+  factory Float32List.view(ByteBuffer buffer,
+                           [int offsetInBytes = 0, int length]) {
+    return buffer.asFloat32List(offsetInBytes, length);
+  }
 
   // Method(s) implementing the List interface.
 
@@ -1346,6 +1592,7 @@
 
 
   // Method(s) implementing the TypedData interface.
+  static const int BYTES_PER_ELEMENT = 4;
 
   int get elementSizeInBytes {
     return Float32List.BYTES_PER_ELEMENT;
@@ -1354,8 +1601,8 @@
 
   // Internal utility methods.
 
-  _Float32Array _createList(int length) {
-    return new _Float32Array(length);
+  Float32List _createList(int length) {
+    return new Float32List(length);
   }
 
   double _getIndexedFloat32(int index) {
@@ -1368,10 +1615,20 @@
 }
 
 
-class _Float64Array extends _TypedList with _DoubleListMixin implements Float64List {
+class Float64List extends _TypedList with _DoubleListMixin implements List<double>, TypedData {
   // Factory constructors.
 
-  factory _Float64Array(int length) native "TypedData_Float64Array_new";
+  factory Float64List(int length) native "TypedData_Float64Array_new";
+
+  factory Float64List.fromList(List<double> elements) {
+    return new Float64List(elements.length)
+        ..setRange(0, elements.length, elements);
+  }
+
+  factory Float64List.view(ByteBuffer buffer,
+                           [int offsetInBytes = 0, int length]) {
+    return buffer.asFloat64List(offsetInBytes, length);
+  }
 
   // Method(s) implementing the List interface.
 
@@ -1391,6 +1648,7 @@
 
 
   // Method(s) implementing the TypedData interface.
+  static const int BYTES_PER_ELEMENT = 8;
 
   int get elementSizeInBytes {
     return Float64List.BYTES_PER_ELEMENT;
@@ -1399,8 +1657,8 @@
 
   // Internal utility methods.
 
-  _Float64Array _createList(int length) {
-    return new _Float64Array(length);
+  Float64List _createList(int length) {
+    return new Float64List(length);
   }
 
   double _getIndexedFloat64(int index) {
@@ -1413,10 +1671,20 @@
 }
 
 
-class _Float32x4Array extends _TypedList with _Float32x4ListMixin implements Float32x4List {
+class Float32x4List extends _TypedList with _Float32x4ListMixin implements List<Float32x4>, TypedData {
   // Factory constructors.
 
-  factory _Float32x4Array(int length) native "TypedData_Float32x4Array_new";
+  factory Float32x4List(int length) native "TypedData_Float32x4Array_new";
+
+  factory Float32x4List.fromList(List<Float32x4> elements) {
+    return new Float32x4List(elements.length)
+        ..setRange(0, elements.length, elements);
+  }
+
+  factory Float32x4List.view(ByteBuffer buffer,
+                             [int offsetInBytes = 0, int length]) {
+    return buffer.asFloat32x4List(offsetInBytes, length);
+  }
 
   Float32x4 operator[](int index) {
     if (index < 0 || index >= length) {
@@ -1434,6 +1702,7 @@
 
 
   // Method(s) implementing the TypedData interface.
+  static const int BYTES_PER_ELEMENT = 16;
 
   int get elementSizeInBytes {
     return Float32x4List.BYTES_PER_ELEMENT;
@@ -1442,8 +1711,8 @@
 
   // Internal utility methods.
 
-  _Float32x4Array _createList(int length) {
-    return new _Float32x4Array(length);
+  Float32x4List _createList(int length) {
+    return new Float32x4List(length);
   }
 
   Float32x4 _getIndexedFloat32x4(int index) {
@@ -1456,10 +1725,20 @@
 }
 
 
-class _Int32x4Array extends _TypedList with _Int32x4ListMixin implements Int32x4List {
+class Int32x4List extends _TypedList with _Int32x4ListMixin implements List<Int32x4>, TypedData {
   // Factory constructors.
 
-  factory _Int32x4Array(int length) native "TypedData_Int32x4Array_new";
+  factory Int32x4List(int length) native "TypedData_Int32x4Array_new";
+
+  factory Int32x4List.fromList(List<Int32x4> elements) {
+    return new Int32x4List(elements.length)
+        ..setRange(0, elements.length, elements);
+  }
+
+  factory Int32x4List.view(ByteBuffer buffer,
+                             [int offsetInBytes = 0, int length]) {
+    return buffer.asInt32x4List(offsetInBytes, length);
+  }
 
   Int32x4 operator[](int index) {
     if (index < 0 || index >= length) {
@@ -1477,6 +1756,7 @@
 
 
   // Method(s) implementing the TypedData interface.
+  static const int BYTES_PER_ELEMENT = 16;
 
   int get elementSizeInBytes {
     return Int32x4List.BYTES_PER_ELEMENT;
@@ -1485,8 +1765,8 @@
 
   // Internal utility methods.
 
-  _Int32x4Array _createList(int length) {
-    return new _Int32x4Array(length);
+  Int32x4List _createList(int length) {
+    return new Int32x4List(length);
   }
 
   Int32x4 _getIndexedInt32x4(int index) {
@@ -1499,10 +1779,20 @@
 }
 
 
-class _Float64x2Array extends _TypedList with _Float64x2ListMixin implements Float64x2List {
+class Float64x2List extends _TypedList with _Float64x2ListMixin implements List<Float64x2>, TypedData {
   // Factory constructors.
 
-  factory _Float64x2Array(int length) native "TypedData_Float64x2Array_new";
+  factory Float64x2List(int length) native "TypedData_Float64x2Array_new";
+
+  factory Float64x2List.fromList(List<Float64x2> elements) {
+    return new Float64x2List(elements.length)
+        ..setRange(0, elements.length, elements);
+  }
+
+  factory Float64x2List.view(ByteBuffer buffer,
+                             [int offsetInBytes = 0, int length]) {
+    return buffer.asFloat64x2List(offsetInBytes, length);
+  }
 
   Float64x2 operator[](int index) {
     if (index < 0 || index >= length) {
@@ -1520,6 +1810,7 @@
 
 
   // Method(s) implementing the TypedData interface.
+  static const int BYTES_PER_ELEMENT = 16;
 
   int get elementSizeInBytes {
     return Float64x2List.BYTES_PER_ELEMENT;
@@ -1528,8 +1819,8 @@
 
   // Internal utility methods.
 
-  _Float64x2Array _createList(int length) {
-    return new _Float64x2Array(length);
+  Float64x2List _createList(int length) {
+    return new Float64x2List(length);
   }
 
   Float64x2 _getIndexedFloat64x2(int index) {
@@ -2147,14 +2438,14 @@
 }
 
 
-class _Float32x4 implements Float32x4 {
-  factory _Float32x4(double x, double y, double z, double w)
+class Float32x4 {
+  factory Float32x4(double x, double y, double z, double w)
       native "Float32x4_fromDoubles";
-  factory _Float32x4.splat(double v) native "Float32x4_splat";
-  factory _Float32x4.zero() native "Float32x4_zero";
-  factory _Float32x4.fromInt32x4Bits(Int32x4 x)
+  factory Float32x4.splat(double v) native "Float32x4_splat";
+  factory Float32x4.zero() native "Float32x4_zero";
+  factory Float32x4.fromInt32x4Bits(Int32x4 x)
       native "Float32x4_fromInt32x4Bits";
-  factory _Float32x4.fromFloat64x2(Float64x2 v)
+  factory Float32x4.fromFloat64x2(Float64x2 v)
       native "Float32x4_fromFloat64x2";
   Float32x4 operator +(Float32x4 other) {
     return _add(other);
@@ -2248,15 +2539,274 @@
     return _reciprocalSqrt();
   }
   Float32x4 _reciprocalSqrt() native "Float32x4_reciprocalSqrt";
+
+  /// Mask passed to [shuffle] or [shuffleMix].
+  static const int XXXX = 0x0;
+  static const int XXXY = 0x40;
+  static const int XXXZ = 0x80;
+  static const int XXXW = 0xC0;
+  static const int XXYX = 0x10;
+  static const int XXYY = 0x50;
+  static const int XXYZ = 0x90;
+  static const int XXYW = 0xD0;
+  static const int XXZX = 0x20;
+  static const int XXZY = 0x60;
+  static const int XXZZ = 0xA0;
+  static const int XXZW = 0xE0;
+  static const int XXWX = 0x30;
+  static const int XXWY = 0x70;
+  static const int XXWZ = 0xB0;
+  static const int XXWW = 0xF0;
+  static const int XYXX = 0x4;
+  static const int XYXY = 0x44;
+  static const int XYXZ = 0x84;
+  static const int XYXW = 0xC4;
+  static const int XYYX = 0x14;
+  static const int XYYY = 0x54;
+  static const int XYYZ = 0x94;
+  static const int XYYW = 0xD4;
+  static const int XYZX = 0x24;
+  static const int XYZY = 0x64;
+  static const int XYZZ = 0xA4;
+  static const int XYZW = 0xE4;
+  static const int XYWX = 0x34;
+  static const int XYWY = 0x74;
+  static const int XYWZ = 0xB4;
+  static const int XYWW = 0xF4;
+  static const int XZXX = 0x8;
+  static const int XZXY = 0x48;
+  static const int XZXZ = 0x88;
+  static const int XZXW = 0xC8;
+  static const int XZYX = 0x18;
+  static const int XZYY = 0x58;
+  static const int XZYZ = 0x98;
+  static const int XZYW = 0xD8;
+  static const int XZZX = 0x28;
+  static const int XZZY = 0x68;
+  static const int XZZZ = 0xA8;
+  static const int XZZW = 0xE8;
+  static const int XZWX = 0x38;
+  static const int XZWY = 0x78;
+  static const int XZWZ = 0xB8;
+  static const int XZWW = 0xF8;
+  static const int XWXX = 0xC;
+  static const int XWXY = 0x4C;
+  static const int XWXZ = 0x8C;
+  static const int XWXW = 0xCC;
+  static const int XWYX = 0x1C;
+  static const int XWYY = 0x5C;
+  static const int XWYZ = 0x9C;
+  static const int XWYW = 0xDC;
+  static const int XWZX = 0x2C;
+  static const int XWZY = 0x6C;
+  static const int XWZZ = 0xAC;
+  static const int XWZW = 0xEC;
+  static const int XWWX = 0x3C;
+  static const int XWWY = 0x7C;
+  static const int XWWZ = 0xBC;
+  static const int XWWW = 0xFC;
+  static const int YXXX = 0x1;
+  static const int YXXY = 0x41;
+  static const int YXXZ = 0x81;
+  static const int YXXW = 0xC1;
+  static const int YXYX = 0x11;
+  static const int YXYY = 0x51;
+  static const int YXYZ = 0x91;
+  static const int YXYW = 0xD1;
+  static const int YXZX = 0x21;
+  static const int YXZY = 0x61;
+  static const int YXZZ = 0xA1;
+  static const int YXZW = 0xE1;
+  static const int YXWX = 0x31;
+  static const int YXWY = 0x71;
+  static const int YXWZ = 0xB1;
+  static const int YXWW = 0xF1;
+  static const int YYXX = 0x5;
+  static const int YYXY = 0x45;
+  static const int YYXZ = 0x85;
+  static const int YYXW = 0xC5;
+  static const int YYYX = 0x15;
+  static const int YYYY = 0x55;
+  static const int YYYZ = 0x95;
+  static const int YYYW = 0xD5;
+  static const int YYZX = 0x25;
+  static const int YYZY = 0x65;
+  static const int YYZZ = 0xA5;
+  static const int YYZW = 0xE5;
+  static const int YYWX = 0x35;
+  static const int YYWY = 0x75;
+  static const int YYWZ = 0xB5;
+  static const int YYWW = 0xF5;
+  static const int YZXX = 0x9;
+  static const int YZXY = 0x49;
+  static const int YZXZ = 0x89;
+  static const int YZXW = 0xC9;
+  static const int YZYX = 0x19;
+  static const int YZYY = 0x59;
+  static const int YZYZ = 0x99;
+  static const int YZYW = 0xD9;
+  static const int YZZX = 0x29;
+  static const int YZZY = 0x69;
+  static const int YZZZ = 0xA9;
+  static const int YZZW = 0xE9;
+  static const int YZWX = 0x39;
+  static const int YZWY = 0x79;
+  static const int YZWZ = 0xB9;
+  static const int YZWW = 0xF9;
+  static const int YWXX = 0xD;
+  static const int YWXY = 0x4D;
+  static const int YWXZ = 0x8D;
+  static const int YWXW = 0xCD;
+  static const int YWYX = 0x1D;
+  static const int YWYY = 0x5D;
+  static const int YWYZ = 0x9D;
+  static const int YWYW = 0xDD;
+  static const int YWZX = 0x2D;
+  static const int YWZY = 0x6D;
+  static const int YWZZ = 0xAD;
+  static const int YWZW = 0xED;
+  static const int YWWX = 0x3D;
+  static const int YWWY = 0x7D;
+  static const int YWWZ = 0xBD;
+  static const int YWWW = 0xFD;
+  static const int ZXXX = 0x2;
+  static const int ZXXY = 0x42;
+  static const int ZXXZ = 0x82;
+  static const int ZXXW = 0xC2;
+  static const int ZXYX = 0x12;
+  static const int ZXYY = 0x52;
+  static const int ZXYZ = 0x92;
+  static const int ZXYW = 0xD2;
+  static const int ZXZX = 0x22;
+  static const int ZXZY = 0x62;
+  static const int ZXZZ = 0xA2;
+  static const int ZXZW = 0xE2;
+  static const int ZXWX = 0x32;
+  static const int ZXWY = 0x72;
+  static const int ZXWZ = 0xB2;
+  static const int ZXWW = 0xF2;
+  static const int ZYXX = 0x6;
+  static const int ZYXY = 0x46;
+  static const int ZYXZ = 0x86;
+  static const int ZYXW = 0xC6;
+  static const int ZYYX = 0x16;
+  static const int ZYYY = 0x56;
+  static const int ZYYZ = 0x96;
+  static const int ZYYW = 0xD6;
+  static const int ZYZX = 0x26;
+  static const int ZYZY = 0x66;
+  static const int ZYZZ = 0xA6;
+  static const int ZYZW = 0xE6;
+  static const int ZYWX = 0x36;
+  static const int ZYWY = 0x76;
+  static const int ZYWZ = 0xB6;
+  static const int ZYWW = 0xF6;
+  static const int ZZXX = 0xA;
+  static const int ZZXY = 0x4A;
+  static const int ZZXZ = 0x8A;
+  static const int ZZXW = 0xCA;
+  static const int ZZYX = 0x1A;
+  static const int ZZYY = 0x5A;
+  static const int ZZYZ = 0x9A;
+  static const int ZZYW = 0xDA;
+  static const int ZZZX = 0x2A;
+  static const int ZZZY = 0x6A;
+  static const int ZZZZ = 0xAA;
+  static const int ZZZW = 0xEA;
+  static const int ZZWX = 0x3A;
+  static const int ZZWY = 0x7A;
+  static const int ZZWZ = 0xBA;
+  static const int ZZWW = 0xFA;
+  static const int ZWXX = 0xE;
+  static const int ZWXY = 0x4E;
+  static const int ZWXZ = 0x8E;
+  static const int ZWXW = 0xCE;
+  static const int ZWYX = 0x1E;
+  static const int ZWYY = 0x5E;
+  static const int ZWYZ = 0x9E;
+  static const int ZWYW = 0xDE;
+  static const int ZWZX = 0x2E;
+  static const int ZWZY = 0x6E;
+  static const int ZWZZ = 0xAE;
+  static const int ZWZW = 0xEE;
+  static const int ZWWX = 0x3E;
+  static const int ZWWY = 0x7E;
+  static const int ZWWZ = 0xBE;
+  static const int ZWWW = 0xFE;
+  static const int WXXX = 0x3;
+  static const int WXXY = 0x43;
+  static const int WXXZ = 0x83;
+  static const int WXXW = 0xC3;
+  static const int WXYX = 0x13;
+  static const int WXYY = 0x53;
+  static const int WXYZ = 0x93;
+  static const int WXYW = 0xD3;
+  static const int WXZX = 0x23;
+  static const int WXZY = 0x63;
+  static const int WXZZ = 0xA3;
+  static const int WXZW = 0xE3;
+  static const int WXWX = 0x33;
+  static const int WXWY = 0x73;
+  static const int WXWZ = 0xB3;
+  static const int WXWW = 0xF3;
+  static const int WYXX = 0x7;
+  static const int WYXY = 0x47;
+  static const int WYXZ = 0x87;
+  static const int WYXW = 0xC7;
+  static const int WYYX = 0x17;
+  static const int WYYY = 0x57;
+  static const int WYYZ = 0x97;
+  static const int WYYW = 0xD7;
+  static const int WYZX = 0x27;
+  static const int WYZY = 0x67;
+  static const int WYZZ = 0xA7;
+  static const int WYZW = 0xE7;
+  static const int WYWX = 0x37;
+  static const int WYWY = 0x77;
+  static const int WYWZ = 0xB7;
+  static const int WYWW = 0xF7;
+  static const int WZXX = 0xB;
+  static const int WZXY = 0x4B;
+  static const int WZXZ = 0x8B;
+  static const int WZXW = 0xCB;
+  static const int WZYX = 0x1B;
+  static const int WZYY = 0x5B;
+  static const int WZYZ = 0x9B;
+  static const int WZYW = 0xDB;
+  static const int WZZX = 0x2B;
+  static const int WZZY = 0x6B;
+  static const int WZZZ = 0xAB;
+  static const int WZZW = 0xEB;
+  static const int WZWX = 0x3B;
+  static const int WZWY = 0x7B;
+  static const int WZWZ = 0xBB;
+  static const int WZWW = 0xFB;
+  static const int WWXX = 0xF;
+  static const int WWXY = 0x4F;
+  static const int WWXZ = 0x8F;
+  static const int WWXW = 0xCF;
+  static const int WWYX = 0x1F;
+  static const int WWYY = 0x5F;
+  static const int WWYZ = 0x9F;
+  static const int WWYW = 0xDF;
+  static const int WWZX = 0x2F;
+  static const int WWZY = 0x6F;
+  static const int WWZZ = 0xAF;
+  static const int WWZW = 0xEF;
+  static const int WWWX = 0x3F;
+  static const int WWWY = 0x7F;
+  static const int WWWZ = 0xBF;
+  static const int WWWW = 0xFF;
+
 }
 
 
-class _Int32x4 implements Int32x4 {
-  factory _Int32x4(int x, int y, int z, int w)
+class Int32x4 {
+  factory Int32x4(int x, int y, int z, int w)
       native "Int32x4_fromInts";
-  factory _Int32x4.bool(bool x, bool y, bool z, bool w)
+  factory Int32x4.bool(bool x, bool y, bool z, bool w)
       native "Int32x4_fromBools";
-  factory _Int32x4.fromFloat32x4Bits(Float32x4 x)
+  factory Int32x4.fromFloat32x4Bits(Float32x4 x)
       native "Int32x4_fromFloat32x4Bits";
   Int32x4 operator |(Int32x4 other) {
     return _or(other);
@@ -2304,14 +2854,273 @@
   Float32x4 _select(Float32x4 trueValue,
                            Float32x4 falseValue)
       native "Int32x4_select";
+
+  /// Mask passed to [shuffle] or [shuffleMix].
+  static const int XXXX = 0x0;
+  static const int XXXY = 0x40;
+  static const int XXXZ = 0x80;
+  static const int XXXW = 0xC0;
+  static const int XXYX = 0x10;
+  static const int XXYY = 0x50;
+  static const int XXYZ = 0x90;
+  static const int XXYW = 0xD0;
+  static const int XXZX = 0x20;
+  static const int XXZY = 0x60;
+  static const int XXZZ = 0xA0;
+  static const int XXZW = 0xE0;
+  static const int XXWX = 0x30;
+  static const int XXWY = 0x70;
+  static const int XXWZ = 0xB0;
+  static const int XXWW = 0xF0;
+  static const int XYXX = 0x4;
+  static const int XYXY = 0x44;
+  static const int XYXZ = 0x84;
+  static const int XYXW = 0xC4;
+  static const int XYYX = 0x14;
+  static const int XYYY = 0x54;
+  static const int XYYZ = 0x94;
+  static const int XYYW = 0xD4;
+  static const int XYZX = 0x24;
+  static const int XYZY = 0x64;
+  static const int XYZZ = 0xA4;
+  static const int XYZW = 0xE4;
+  static const int XYWX = 0x34;
+  static const int XYWY = 0x74;
+  static const int XYWZ = 0xB4;
+  static const int XYWW = 0xF4;
+  static const int XZXX = 0x8;
+  static const int XZXY = 0x48;
+  static const int XZXZ = 0x88;
+  static const int XZXW = 0xC8;
+  static const int XZYX = 0x18;
+  static const int XZYY = 0x58;
+  static const int XZYZ = 0x98;
+  static const int XZYW = 0xD8;
+  static const int XZZX = 0x28;
+  static const int XZZY = 0x68;
+  static const int XZZZ = 0xA8;
+  static const int XZZW = 0xE8;
+  static const int XZWX = 0x38;
+  static const int XZWY = 0x78;
+  static const int XZWZ = 0xB8;
+  static const int XZWW = 0xF8;
+  static const int XWXX = 0xC;
+  static const int XWXY = 0x4C;
+  static const int XWXZ = 0x8C;
+  static const int XWXW = 0xCC;
+  static const int XWYX = 0x1C;
+  static const int XWYY = 0x5C;
+  static const int XWYZ = 0x9C;
+  static const int XWYW = 0xDC;
+  static const int XWZX = 0x2C;
+  static const int XWZY = 0x6C;
+  static const int XWZZ = 0xAC;
+  static const int XWZW = 0xEC;
+  static const int XWWX = 0x3C;
+  static const int XWWY = 0x7C;
+  static const int XWWZ = 0xBC;
+  static const int XWWW = 0xFC;
+  static const int YXXX = 0x1;
+  static const int YXXY = 0x41;
+  static const int YXXZ = 0x81;
+  static const int YXXW = 0xC1;
+  static const int YXYX = 0x11;
+  static const int YXYY = 0x51;
+  static const int YXYZ = 0x91;
+  static const int YXYW = 0xD1;
+  static const int YXZX = 0x21;
+  static const int YXZY = 0x61;
+  static const int YXZZ = 0xA1;
+  static const int YXZW = 0xE1;
+  static const int YXWX = 0x31;
+  static const int YXWY = 0x71;
+  static const int YXWZ = 0xB1;
+  static const int YXWW = 0xF1;
+  static const int YYXX = 0x5;
+  static const int YYXY = 0x45;
+  static const int YYXZ = 0x85;
+  static const int YYXW = 0xC5;
+  static const int YYYX = 0x15;
+  static const int YYYY = 0x55;
+  static const int YYYZ = 0x95;
+  static const int YYYW = 0xD5;
+  static const int YYZX = 0x25;
+  static const int YYZY = 0x65;
+  static const int YYZZ = 0xA5;
+  static const int YYZW = 0xE5;
+  static const int YYWX = 0x35;
+  static const int YYWY = 0x75;
+  static const int YYWZ = 0xB5;
+  static const int YYWW = 0xF5;
+  static const int YZXX = 0x9;
+  static const int YZXY = 0x49;
+  static const int YZXZ = 0x89;
+  static const int YZXW = 0xC9;
+  static const int YZYX = 0x19;
+  static const int YZYY = 0x59;
+  static const int YZYZ = 0x99;
+  static const int YZYW = 0xD9;
+  static const int YZZX = 0x29;
+  static const int YZZY = 0x69;
+  static const int YZZZ = 0xA9;
+  static const int YZZW = 0xE9;
+  static const int YZWX = 0x39;
+  static const int YZWY = 0x79;
+  static const int YZWZ = 0xB9;
+  static const int YZWW = 0xF9;
+  static const int YWXX = 0xD;
+  static const int YWXY = 0x4D;
+  static const int YWXZ = 0x8D;
+  static const int YWXW = 0xCD;
+  static const int YWYX = 0x1D;
+  static const int YWYY = 0x5D;
+  static const int YWYZ = 0x9D;
+  static const int YWYW = 0xDD;
+  static const int YWZX = 0x2D;
+  static const int YWZY = 0x6D;
+  static const int YWZZ = 0xAD;
+  static const int YWZW = 0xED;
+  static const int YWWX = 0x3D;
+  static const int YWWY = 0x7D;
+  static const int YWWZ = 0xBD;
+  static const int YWWW = 0xFD;
+  static const int ZXXX = 0x2;
+  static const int ZXXY = 0x42;
+  static const int ZXXZ = 0x82;
+  static const int ZXXW = 0xC2;
+  static const int ZXYX = 0x12;
+  static const int ZXYY = 0x52;
+  static const int ZXYZ = 0x92;
+  static const int ZXYW = 0xD2;
+  static const int ZXZX = 0x22;
+  static const int ZXZY = 0x62;
+  static const int ZXZZ = 0xA2;
+  static const int ZXZW = 0xE2;
+  static const int ZXWX = 0x32;
+  static const int ZXWY = 0x72;
+  static const int ZXWZ = 0xB2;
+  static const int ZXWW = 0xF2;
+  static const int ZYXX = 0x6;
+  static const int ZYXY = 0x46;
+  static const int ZYXZ = 0x86;
+  static const int ZYXW = 0xC6;
+  static const int ZYYX = 0x16;
+  static const int ZYYY = 0x56;
+  static const int ZYYZ = 0x96;
+  static const int ZYYW = 0xD6;
+  static const int ZYZX = 0x26;
+  static const int ZYZY = 0x66;
+  static const int ZYZZ = 0xA6;
+  static const int ZYZW = 0xE6;
+  static const int ZYWX = 0x36;
+  static const int ZYWY = 0x76;
+  static const int ZYWZ = 0xB6;
+  static const int ZYWW = 0xF6;
+  static const int ZZXX = 0xA;
+  static const int ZZXY = 0x4A;
+  static const int ZZXZ = 0x8A;
+  static const int ZZXW = 0xCA;
+  static const int ZZYX = 0x1A;
+  static const int ZZYY = 0x5A;
+  static const int ZZYZ = 0x9A;
+  static const int ZZYW = 0xDA;
+  static const int ZZZX = 0x2A;
+  static const int ZZZY = 0x6A;
+  static const int ZZZZ = 0xAA;
+  static const int ZZZW = 0xEA;
+  static const int ZZWX = 0x3A;
+  static const int ZZWY = 0x7A;
+  static const int ZZWZ = 0xBA;
+  static const int ZZWW = 0xFA;
+  static const int ZWXX = 0xE;
+  static const int ZWXY = 0x4E;
+  static const int ZWXZ = 0x8E;
+  static const int ZWXW = 0xCE;
+  static const int ZWYX = 0x1E;
+  static const int ZWYY = 0x5E;
+  static const int ZWYZ = 0x9E;
+  static const int ZWYW = 0xDE;
+  static const int ZWZX = 0x2E;
+  static const int ZWZY = 0x6E;
+  static const int ZWZZ = 0xAE;
+  static const int ZWZW = 0xEE;
+  static const int ZWWX = 0x3E;
+  static const int ZWWY = 0x7E;
+  static const int ZWWZ = 0xBE;
+  static const int ZWWW = 0xFE;
+  static const int WXXX = 0x3;
+  static const int WXXY = 0x43;
+  static const int WXXZ = 0x83;
+  static const int WXXW = 0xC3;
+  static const int WXYX = 0x13;
+  static const int WXYY = 0x53;
+  static const int WXYZ = 0x93;
+  static const int WXYW = 0xD3;
+  static const int WXZX = 0x23;
+  static const int WXZY = 0x63;
+  static const int WXZZ = 0xA3;
+  static const int WXZW = 0xE3;
+  static const int WXWX = 0x33;
+  static const int WXWY = 0x73;
+  static const int WXWZ = 0xB3;
+  static const int WXWW = 0xF3;
+  static const int WYXX = 0x7;
+  static const int WYXY = 0x47;
+  static const int WYXZ = 0x87;
+  static const int WYXW = 0xC7;
+  static const int WYYX = 0x17;
+  static const int WYYY = 0x57;
+  static const int WYYZ = 0x97;
+  static const int WYYW = 0xD7;
+  static const int WYZX = 0x27;
+  static const int WYZY = 0x67;
+  static const int WYZZ = 0xA7;
+  static const int WYZW = 0xE7;
+  static const int WYWX = 0x37;
+  static const int WYWY = 0x77;
+  static const int WYWZ = 0xB7;
+  static const int WYWW = 0xF7;
+  static const int WZXX = 0xB;
+  static const int WZXY = 0x4B;
+  static const int WZXZ = 0x8B;
+  static const int WZXW = 0xCB;
+  static const int WZYX = 0x1B;
+  static const int WZYY = 0x5B;
+  static const int WZYZ = 0x9B;
+  static const int WZYW = 0xDB;
+  static const int WZZX = 0x2B;
+  static const int WZZY = 0x6B;
+  static const int WZZZ = 0xAB;
+  static const int WZZW = 0xEB;
+  static const int WZWX = 0x3B;
+  static const int WZWY = 0x7B;
+  static const int WZWZ = 0xBB;
+  static const int WZWW = 0xFB;
+  static const int WWXX = 0xF;
+  static const int WWXY = 0x4F;
+  static const int WWXZ = 0x8F;
+  static const int WWXW = 0xCF;
+  static const int WWYX = 0x1F;
+  static const int WWYY = 0x5F;
+  static const int WWYZ = 0x9F;
+  static const int WWYW = 0xDF;
+  static const int WWZX = 0x2F;
+  static const int WWZY = 0x6F;
+  static const int WWZZ = 0xAF;
+  static const int WWZW = 0xEF;
+  static const int WWWX = 0x3F;
+  static const int WWWY = 0x7F;
+  static const int WWWZ = 0xBF;
+  static const int WWWW = 0xFF;
+
 }
 
 
-class _Float64x2 implements Float64x2 {
-  factory _Float64x2(double x, double y) native "Float64x2_fromDoubles";
-  factory _Float64x2.splat(double v) native "Float64x2_splat";
-  factory _Float64x2.zero() native "Float64x2_zero";
-  factory _Float64x2.fromFloat32x4(Float32x4 v) native "Float64x2_fromFloat32x4";
+class Float64x2 {
+  factory Float64x2(double x, double y) native "Float64x2_fromDoubles";
+  factory Float64x2.splat(double v) native "Float64x2_splat";
+  factory Float64x2.zero() native "Float64x2_zero";
+  factory Float64x2.fromFloat32x4(Float32x4 v) native "Float64x2_fromFloat32x4";
 
   Float64x2 operator +(Float64x2 other) {
     return _add(other);
@@ -2397,7 +3206,7 @@
 
 
 class _TypedListView extends _TypedListBase implements TypedData {
-  _TypedListView(_ByteBuffer _buffer, int _offset, int _length)
+  _TypedListView(ByteBuffer _buffer, int _offset, int _length)
     : _typedData = _buffer._data,
       offsetInBytes = _offset,
       length = _length {
diff --git a/runtime/observatory/lib/src/app/location_manager.dart b/runtime/observatory/lib/src/app/location_manager.dart
index fee2884..577cb92 100644
--- a/runtime/observatory/lib/src/app/location_manager.dart
+++ b/runtime/observatory/lib/src/app/location_manager.dart
@@ -34,6 +34,13 @@
     _updateApplicationLocation(applicationPath);
   }
 
+  bool getBoolParameter(String name, bool defaultValue) {
+    var value = uri.queryParameters[name];
+    if ("true" == value) return true;
+    if ("false" == value) return false;
+    return defaultValue;
+  }
+
   /// Called whenever the browser changes the location bar (e.g. forward or
   /// back button press).
   void _onBrowserNavigation(PopStateEvent event) {
diff --git a/runtime/observatory/lib/src/app/view_model.dart b/runtime/observatory/lib/src/app/view_model.dart
index 072b156..94edb49 100644
--- a/runtime/observatory/lib/src/app/view_model.dart
+++ b/runtime/observatory/lib/src/app/view_model.dart
@@ -68,7 +68,8 @@
 
   HtmlElement _makeExpander() {
     var expander = new SpanElement();
-    expander.style.minWidth = '2em';
+    expander.style.minWidth = '24px';
+    expander.style.minHeight = '24px';
     listeners.add(expander.onClick.listen(onClick));
     return expander;
   }
diff --git a/runtime/observatory/lib/src/elements/class_tree.dart b/runtime/observatory/lib/src/elements/class_tree.dart
index 42de21c..16f6928 100644
--- a/runtime/observatory/lib/src/elements/class_tree.dart
+++ b/runtime/observatory/lib/src/elements/class_tree.dart
@@ -5,6 +5,7 @@
 library class_tree_element;
 
 import 'observatory_element.dart';
+import 'dart:async';
 import 'dart:html';
 import 'package:logging/logging.dart';
 import 'package:observatory/app.dart';
@@ -20,27 +21,92 @@
     assert(cls != null);
   }
 
-  void onShow() {
-    super.onShow();
-    if (children.length == 0) {
-      for (var subclass in cls.subclasses) {
-        if (subclass.isPatch) {
-          continue;
-        }
+  void _addChildren(List<Class> subclasses) {
+    for (var subclass in subclasses) {
+      if (subclass.isPatch) {
+        continue;
+      }
+      if (subclass.mixin != null) {
+        _addChildren(subclass.subclasses);
+      } else {
         var row = new ClassTreeRow(isolate, subclass, tree, this);
         children.add(row);
       }
     }
+  }
+
+  Future _addMixins(Class cls) async {
+    var classCell = flexColumns[0];
+    if (cls.superclass == null) {
+      return;
+    }
+    bool first = true;
+    while (cls.superclass != null && cls.superclass.mixin != null) {
+      cls = cls.superclass;
+      await cls.mixin.load();
+      var span = new SpanElement();
+      span.style.alignSelf = 'center';
+      span.style.whiteSpace = 'pre';
+      if (first) {
+        span.text = ' with ';
+      } else {
+        span.text = ', ';
+      }
+      classCell.children.add(span);
+      var mixinRef = new Element.tag('class-ref');
+      mixinRef.ref = cls.mixin.typeClass;
+      mixinRef.style.alignSelf = 'center';
+      classCell.children.add(mixinRef);
+      first = false;
+    }
+  }
+
+  Future _addClass(Class cls) async {
     var classCell = flexColumns[0];
     classCell.style.justifyContent = 'flex-start';
     var classRef = new Element.tag('class-ref');
     classRef.ref = cls;
     classRef.style.alignSelf = 'center';
     classCell.children.add(classRef);
+    if (cls.superclass != null && cls.superclass.mixin != null) {
+      await _addMixins(cls);
+    }
+    if (cls.subclasses.isNotEmpty) {
+      var span = new SpanElement();
+      span.style.paddingLeft = '.5em';
+      span.style.alignSelf = 'center';
+      int subclassCount = _indirectSubclassCount(cls) - 1;
+      if (subclassCount > 1) {
+        span.text = '($subclassCount subclasses)';
+      } else {
+        span.text = '($subclassCount subclass)';
+      }
+      classCell.children.add(span);
+    }
+  }
+
+  void onShow() {
+    super.onShow();
+    if (children.length == 0) {
+      _addChildren(cls.subclasses);
+    }
+    _addClass(cls);
+  }
+
+  static int _indirectSubclassCount(var cls) {
+    int count = 0;
+    if (cls.mixin == null) {
+      // Don't count synthetic mixin classes in subclass count.
+      count++;
+    }
+    for (var subclass in cls.subclasses) {
+      count += _indirectSubclassCount(subclass);
+    }
+    return count;
   }
 
   bool hasChildren() {
-    return cls.subclasses.length > 0;
+    return cls.subclasses.isNotEmpty;
   }
 }
 
diff --git a/runtime/observatory/lib/src/elements/class_view.dart b/runtime/observatory/lib/src/elements/class_view.dart
index d50b092..c13cbb3 100644
--- a/runtime/observatory/lib/src/elements/class_view.dart
+++ b/runtime/observatory/lib/src/elements/class_view.dart
@@ -35,7 +35,7 @@
   }
 
   Future<ServiceObject> retainedToplist(var limit) {
-    return cls.isolate.fetchHeapSnapshot().last
+    return cls.isolate.fetchHeapSnapshot(true).last
       .then((HeapSnapshot snapshot) =>
           Future.wait(snapshot.getMostRetained(classId: cls.vmCid,
                                                limit: 10)))
diff --git a/runtime/observatory/lib/src/elements/class_view.html b/runtime/observatory/lib/src/elements/class_view.html
index 60e8ee0..a40ef165d 100644
--- a/runtime/observatory/lib/src/elements/class_view.html
+++ b/runtime/observatory/lib/src/elements/class_view.html
@@ -35,6 +35,9 @@
         <template if="{{ cls.isPatch }}">
           patch
         </template>
+        <template if="{{ cls.mixin != null }}">
+          mixin
+        </template>
         class {{ cls.name }}
       </h1>
 
@@ -59,12 +62,28 @@
 
         <template if="{{ cls.superclass != null }}">
           <div class="memberItem">
-            <div class="memberName">extends</div>
+            <div class="memberName">superclass</div>
             <div class="memberValue">
               <class-ref ref="{{ cls.superclass }}"></class-ref>
             </div>
           </div>
         </template>
+        <template if="{{ cls.superType != null }}">
+          <div class="memberItem">
+            <div class="memberName">supertype</div>
+            <div class="memberValue">
+              <instance-ref ref="{{ cls.superType }}"></instance-ref>
+            </div>
+          </div>
+        </template>
+        <template if="{{ cls.mixin != null }}">
+          <div class="memberItem">
+            <div class="memberName">mixin</div>
+            <div class="memberValue">
+              <instance-ref ref="{{ cls.mixin }}"></instance-ref>
+            </div>
+          </div>
+        </template>
         <template if="{{ cls.subclasses.length > 0 }}">
           <div class="memberItem">
             <div class="memberName">extended by</div>
diff --git a/runtime/observatory/lib/src/elements/heap_snapshot.dart b/runtime/observatory/lib/src/elements/heap_snapshot.dart
index a9e4a8e..4894e9f 100644
--- a/runtime/observatory/lib/src/elements/heap_snapshot.dart
+++ b/runtime/observatory/lib/src/elements/heap_snapshot.dart
@@ -407,8 +407,12 @@
     var completer = new Completer();
     state = "Requesting heap snapshot...";
     isolate.getClassRefs();
+
+    bool collectGarbage =
+        app.locationManager.getBoolParameter('collectGarbage', true);
+
     var stopwatch = new Stopwatch()..start();
-    isolate.fetchHeapSnapshot().listen((event) {
+    isolate.fetchHeapSnapshot(collectGarbage).listen((event) {
       if (event is String) {
         print("${stopwatch.elapsedMilliseconds} $event");
         state = event;
diff --git a/runtime/observatory/lib/src/elements/instance_view.dart b/runtime/observatory/lib/src/elements/instance_view.dart
index 96a3b74..dda1cc5 100644
--- a/runtime/observatory/lib/src/elements/instance_view.dart
+++ b/runtime/observatory/lib/src/elements/instance_view.dart
@@ -15,6 +15,19 @@
 
   InstanceViewElement.created() : super.created();
 
+  instanceChanged(oldValue) {
+    if (instance != null) {
+      // We load typeClass and typeArguments because we want to
+      // display this info.
+      if (instance.typeClass != null) {
+        instance.typeClass.load();
+      }
+      if (instance.typeArguments != null) {
+        instance.typeArguments.load();
+      }
+    }
+  }
+
   Future<ServiceObject> evaluate(String expression) {
     return instance.evaluate(expression);
   }
diff --git a/runtime/observatory/lib/src/elements/instance_view.html b/runtime/observatory/lib/src/elements/instance_view.html
index f54059f..77e84f9 100644
--- a/runtime/observatory/lib/src/elements/instance_view.html
+++ b/runtime/observatory/lib/src/elements/instance_view.html
@@ -69,6 +69,57 @@
               </div>
             </div>
           </template>
+          <template if="{{ instance.typeArguments.length > 0 }}">
+            <div class="memberItem">
+              <div class="memberName">type arguments</div>
+              <div class="memberValue">
+                &lt;
+                <template repeat="{{ index in instance.typeArguments['types'].asMap().keys }}">
+                  <instance-ref ref="{{ instance.typeArguments['types'][index] }}">
+                  </instance-ref>
+                  <template if="{{ index < instance.typeArguments['types'].length - 1 }}">
+                    ,
+                  </template>
+                </template>
+                &gt;
+              </div>
+            </div>
+          </template>
+          <template if="{{ instance.parameterizedClass != null }}">
+            <div class="memberItem">
+              <div class="memberName">parameterized class</div>
+              <div class="memberValue">
+                <class-ref ref="{{ instance.parameterizedClass }}">
+                </class-ref>
+              </div>
+            </div>
+          </template>
+          <template if="{{ instance.parameterIndex != null }}">
+            <div class="memberItem">
+              <div class="memberName">parameter index</div>
+              <div class="memberValue">
+                {{ instance.parameterIndex }}
+              </div>
+            </div>
+          </template>
+          <template if="{{ instance.targetType != null }}">
+            <div class="memberItem">
+              <div class="memberName">target type</div>
+              <div class="memberValue">
+                <instance-ref ref="{{ instance.targetType }}">
+                </instance-ref>
+              </div>
+            </div>
+          </template>
+          <template if="{{ instance.bound != null }}">
+            <div class="memberItem">
+              <div class="memberName">bound</div>
+              <div class="memberValue">
+                <instance-ref ref="{{ instance.bound }}">
+                </instance-ref>
+              </div>
+            </div>
+          </template>
 
           <template if="{{ instance.isClosure }}">
             <div class="memberItem">
@@ -109,6 +160,12 @@
               <eval-link callback="{{ evaluate }}" expr="toString()"></eval-link>
             </div>
           </div>
+          <div class="memberItem">
+            <div class="memberName">runtimeType</div>
+            <div class="memberValue">
+              <eval-link callback="{{ evaluate }}" expr="runtimeType"></eval-link>
+            </div>
+          </div>
         </div>
       </div>
 
@@ -300,6 +357,9 @@
         <template if="{{ instance.isClosure }}">
           <source-inset location="{{ instance.function.location }}"></source-inset>
         </template>
+        <template if="{{ instance.typeClass != null }}">
+          <source-inset location="{{ instance.typeClass.location }}"></source-inset>
+        </template>
       </div>
 
     </template>
diff --git a/runtime/observatory/lib/src/elements/isolate_view.html b/runtime/observatory/lib/src/elements/isolate_view.html
index b090fdd..a2fe66d 100644
--- a/runtime/observatory/lib/src/elements/isolate_view.html
+++ b/runtime/observatory/lib/src/elements/isolate_view.html
@@ -90,6 +90,10 @@
               <div class="memberName">isolate id</div>
               <div class="memberValue">{{ isolate.number }}</div>
             </div>
+            <div class="memberItem">
+              <div class="memberName">service protocol extensions</div>
+              <div class="memberValue">{{ isolate.extensionRPCs }}</div>
+            </div>
           </div>
         </div>
       </div>
diff --git a/runtime/observatory/lib/src/elements/script_inset.dart b/runtime/observatory/lib/src/elements/script_inset.dart
index 6528c8d..1b94f38 100644
--- a/runtime/observatory/lib/src/elements/script_inset.dart
+++ b/runtime/observatory/lib/src/elements/script_inset.dart
@@ -386,15 +386,19 @@
     return Utils.formatPercent(totalTicks, sampleCount);
   }
 
-  double _percent() {
+  double _percent(bool self) {
     if (sampleCount == 0) {
       return 0.0;
     }
-    return totalTicks / sampleCount;
+    if (self) {
+      return selfTicks / sampleCount;
+    } else {
+      return totalTicks / sampleCount;
+    }
   }
 
-  bool get isHot => _percent() > kHotThreshold;
-  bool get isMedium => _percent() > kMediumThreshold;
+  bool isHot(bool self) => _percent(self) > kHotThreshold;
+  bool isMedium(bool self) => _percent(self) > kMediumThreshold;
 }
 
 /// Box with script source code in it.
@@ -1140,9 +1144,9 @@
       e.text = lineProfile.formattedTotalTicks;
     }
 
-    if (lineProfile.isHot) {
+    if (lineProfile.isHot(self)) {
       e.classes.add('hotProfile');
-    } else if (lineProfile.isMedium) {
+    } else if (lineProfile.isMedium(self)) {
       e.classes.add('mediumProfile');
     } else {
       e.classes.add('coldProfile');
diff --git a/runtime/observatory/lib/src/elements/timeline_page.dart b/runtime/observatory/lib/src/elements/timeline_page.dart
index 7a70c11..cdcb1d7 100644
--- a/runtime/observatory/lib/src/elements/timeline_page.dart
+++ b/runtime/observatory/lib/src/elements/timeline_page.dart
@@ -47,6 +47,8 @@
   }
 
   Future refresh() async {
+    await app.vm.reload();
+    await app.vm.reloadIsolates();
     return postMessage('refresh');
   }
 
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 19a086c..f36683b 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -1365,11 +1365,12 @@
     }
   }
 
-  Stream fetchHeapSnapshot() {
+  Stream fetchHeapSnapshot(collectGarbage) {
     if (_snapshotFetch == null || _snapshotFetch.isClosed) {
       _snapshotFetch = new StreamController();
       // isolate.vm.streamListen('_Graph');
-      isolate.invokeRpcNoUpgrade('_requestHeapSnapshot', {});
+      isolate.invokeRpcNoUpgrade('_requestHeapSnapshot',
+                                 {'collectGarbage': collectGarbage});
     }
     return _snapshotFetch.stream;
   }
@@ -2180,6 +2181,9 @@
   @reflectable final interfaces = new ObservableList<Instance>();
   @reflectable final subclasses = new ObservableList<Class>();
 
+  @observable Instance superType;
+  @observable Instance mixin;
+
   bool get canCache => true;
   bool get immutable => false;
 
@@ -2243,6 +2247,9 @@
     if (superclass != null && superclass.name == "Object") {
       superclass._addSubclass(this);
     }
+    superType = map['superType'];
+    mixin = map['mixin'];
+
     error = map['error'];
 
     traceAllocations =
@@ -2292,11 +2299,17 @@
   @observable bool valueAsStringIsTruncated;
   @observable ServiceFunction function;  // If a closure.
   @observable Context context;  // If a closure.
-  @observable String name;  // If a Type.
   @observable int length; // If a List, Map or TypedData.
   @observable Instance pattern;  // If a RegExp.
 
-  @observable var typeClass;
+  @observable String name;
+  @observable Class typeClass;
+  @observable Class parameterizedClass;
+  @observable ServiceObject typeArguments;
+  @observable int parameterIndex;
+  @observable Instance targetType;
+  @observable Instance bound;
+
   @observable var fields;
   @observable var nativeFields;
   @observable var elements;  // If a List.
@@ -2440,6 +2453,12 @@
       }
     }
     typeClass = map['typeClass'];
+    parameterizedClass = map['parameterizedClass'];
+    typeArguments = map['typeArguments'];
+    parameterIndex = map['parameterIndex'];
+    targetType = map['targetType'];
+    bound = map['bound'];
+
     referent = map['mirrorReferent'];
     key = map['propertyKey'];
     value = map['propertyValue'];
diff --git a/runtime/observatory/tests/service/crash_dump_test.dart b/runtime/observatory/tests/service/crash_dump_test.dart
index 8b60567..0d9d178 100644
--- a/runtime/observatory/tests/service/crash_dump_test.dart
+++ b/runtime/observatory/tests/service/crash_dump_test.dart
@@ -18,9 +18,11 @@
 var tests = [
   (VM vm) async {
     HttpClient client = new HttpClient();
+    print('Requesting uri ${serviceHttpAddress}/_getCrashDump');
     var request =
         await client.getUrl(Uri.parse('$serviceHttpAddress/_getCrashDump'));
     var response = await request.close();
+    print('Received response');
     Completer completer = new Completer();
     StringBuffer sb = new StringBuffer();
     response.transform(UTF8.decoder).listen((chunk) {
diff --git a/runtime/observatory/tests/service/dominator_tree_test.dart b/runtime/observatory/tests/service/dominator_tree_test.dart
index a778f62..5c279c9 100644
--- a/runtime/observatory/tests/service/dominator_tree_test.dart
+++ b/runtime/observatory/tests/service/dominator_tree_test.dart
@@ -57,7 +57,7 @@
 var tests = [
 (Isolate isolate) async {
   var rootLib = await isolate.rootLibrary.load();
-  var snapshot = await isolate.fetchHeapSnapshot().last;
+  var snapshot = await isolate.fetchHeapSnapshot(false).last;
 
   node(String className) {
     var cls = rootLib.classes.singleWhere((cls) => cls.name == className);
diff --git a/runtime/observatory/tests/service/get_object_rpc_test.dart b/runtime/observatory/tests/service/get_object_rpc_test.dart
index a98c535..2f45f3a 100644
--- a/runtime/observatory/tests/service/get_object_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_object_rpc_test.dart
@@ -441,7 +441,7 @@
     expect(result['id'], startsWith('objects/'));
     expect(result['valueAsString'], isNull);
     expect(result['class']['type'], equals('@Class'));
-    expect(result['class']['name'], equals('_Uint8Array'));
+    expect(result['class']['name'], equals('Uint8List'));
     expect(result['size'], isPositive);
     expect(result['fields'], isEmpty);
     expect(result['length'], equals(3));
@@ -467,7 +467,7 @@
     expect(result['id'], startsWith('objects/'));
     expect(result['valueAsString'], isNull);
     expect(result['class']['type'], equals('@Class'));
-    expect(result['class']['name'], equals('_Uint8Array'));
+    expect(result['class']['name'], equals('Uint8List'));
     expect(result['size'], isPositive);
     expect(result['fields'], isEmpty);
     expect(result['length'], equals(3));
@@ -494,7 +494,7 @@
     expect(result['id'], startsWith('objects/'));
     expect(result['valueAsString'], isNull);
     expect(result['class']['type'], equals('@Class'));
-    expect(result['class']['name'], equals('_Uint8Array'));
+    expect(result['class']['name'], equals('Uint8List'));
     expect(result['size'], isPositive);
     expect(result['fields'], isEmpty);
     expect(result['length'], equals(3));
@@ -521,7 +521,7 @@
     expect(result['id'], startsWith('objects/'));
     expect(result['valueAsString'], isNull);
     expect(result['class']['type'], equals('@Class'));
-    expect(result['class']['name'], equals('_Uint8Array'));
+    expect(result['class']['name'], equals('Uint8List'));
     expect(result['size'], isPositive);
     expect(result['fields'], isEmpty);
     expect(result['length'], equals(3));
@@ -544,7 +544,7 @@
     expect(result['id'], startsWith('objects/'));
     expect(result['valueAsString'], isNull);
     expect(result['class']['type'], equals('@Class'));
-    expect(result['class']['name'], equals('_Uint64Array'));
+    expect(result['class']['name'], equals('Uint64List'));
     expect(result['size'], isPositive);
     expect(result['fields'], isEmpty);
     expect(result['length'], equals(3));
@@ -570,7 +570,7 @@
     expect(result['id'], startsWith('objects/'));
     expect(result['valueAsString'], isNull);
     expect(result['class']['type'], equals('@Class'));
-    expect(result['class']['name'], equals('_Uint64Array'));
+    expect(result['class']['name'], equals('Uint64List'));
     expect(result['size'], isPositive);
     expect(result['fields'], isEmpty);
     expect(result['length'], equals(3));
@@ -597,7 +597,7 @@
     expect(result['id'], startsWith('objects/'));
     expect(result['valueAsString'], isNull);
     expect(result['class']['type'], equals('@Class'));
-    expect(result['class']['name'], equals('_Uint64Array'));
+    expect(result['class']['name'], equals('Uint64List'));
     expect(result['size'], isPositive);
     expect(result['fields'], isEmpty);
     expect(result['length'], equals(3));
@@ -624,7 +624,7 @@
     expect(result['id'], startsWith('objects/'));
     expect(result['valueAsString'], isNull);
     expect(result['class']['type'], equals('@Class'));
-    expect(result['class']['name'], equals('_Uint64Array'));
+    expect(result['class']['name'], equals('Uint64List'));
     expect(result['size'], isPositive);
     expect(result['fields'], isEmpty);
     expect(result['length'], equals(3));
diff --git a/runtime/observatory/tests/service/graph_test.dart b/runtime/observatory/tests/service/graph_test.dart
index fe31d16..424747b 100644
--- a/runtime/observatory/tests/service/graph_test.dart
+++ b/runtime/observatory/tests/service/graph_test.dart
@@ -42,7 +42,7 @@
   Class fooClass = lib.classes.first;
   fooId = fooClass.vmCid;
 
-  HeapSnapshot snapshot = await isolate.fetchHeapSnapshot().last;
+  HeapSnapshot snapshot = await isolate.fetchHeapSnapshot(false).last;
   ObjectGraph graph = snapshot.graph;
 
   expect(fooId, isNotNull);
diff --git a/runtime/observatory/web/timeline.js b/runtime/observatory/web/timeline.js
index 9bdf46a..402723d 100644
--- a/runtime/observatory/web/timeline.js
+++ b/runtime/observatory/web/timeline.js
@@ -55,15 +55,21 @@
 function fetchTimelineOnLoad(event) {
   var xhr = event.target;
   var response = JSON.parse(xhr.responseText);
-  var result = response['result'];
-  var newStackFrames = result['stackFrames'];  // Map.
-  var newTraceEvents = result['traceEvents'];  // List.
 
-  // Merge in timeline events.
-  traceObject.traceEvents = traceObject.traceEvents.concat(newTraceEvents);
-  for (var key in newStackFrames) {
-    if (newStackFrames.hasOwnProperty(key)) {
-      traceObject.stackFrames[key] = newStackFrames[key];
+  if (response.error) {
+    // Maybe profiling is disabled.
+    console.log("ERROR " + response.error.message);
+  } else {
+    var result = response['result'];
+    var newStackFrames = result['stackFrames'];  // Map.
+    var newTraceEvents = result['traceEvents'];  // List.
+
+    // Merge in timeline events.
+    traceObject.traceEvents = traceObject.traceEvents.concat(newTraceEvents);
+    for (var key in newStackFrames) {
+      if (newStackFrames.hasOwnProperty(key)) {
+        traceObject.stackFrames[key] = newStackFrames[key];
+      }
     }
   }
 
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index c8a025f..62cc6da 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -91,6 +91,7 @@
 
 [ $runtime == dart_product || $runtime == dart_precompiled ]
 dart/data_uri_spawn_test: SkipByDesign # Isolate.spawnUri
+dart/optimized_stacktrace_test: SkipByDesign # Requires line numbers
 
 [ $runtime == vm && $mode == product ]
 cc/IsolateSetCheckedMode: Fail,OK  # Expects exact type name.
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index 07da822..f9f418b 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -82,7 +82,7 @@
   INIT_LIBRARY(ObjectStore::kTypedData,
                typed_data,
                Bootstrap::typed_data_source_paths_,
-               Bootstrap::typed_data_patch_paths_),
+               NULL),
   INIT_LIBRARY(ObjectStore::kVMService,
                _vmservice,
                Bootstrap::_vmservice_source_paths_,
@@ -132,9 +132,9 @@
   const uint8_t* utf8_array = NULL;
   intptr_t file_length = -1;
 
-  Dart_FileOpenCallback file_open = Isolate::file_open_callback();
-  Dart_FileReadCallback file_read = Isolate::file_read_callback();
-  Dart_FileCloseCallback file_close = Isolate::file_close_callback();
+  Dart_FileOpenCallback file_open = Dart::file_open_callback();
+  Dart_FileReadCallback file_read = Dart::file_read_callback();
+  Dart_FileCloseCallback file_close = Dart::file_close_callback();
   if ((file_open != NULL) && (file_read != NULL) && (file_close != NULL)) {
     // Try to open and read the file.
     void* stream = (*file_open)(source_path, false);
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 03f2869..1e79c57 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -99,12 +99,12 @@
   V(Double_toStringAsExponential, 2)                                           \
   V(Double_toStringAsPrecision, 2)                                             \
   V(Double_flipSignBit, 1)                                                     \
-  V(JSSyntaxRegExp_factory, 4)                                                 \
-  V(JSSyntaxRegExp_getPattern, 1)                                              \
-  V(JSSyntaxRegExp_getIsMultiLine, 1)                                          \
-  V(JSSyntaxRegExp_getIsCaseSensitive, 1)                                      \
-  V(JSSyntaxRegExp_getGroupCount, 1)                                           \
-  V(JSSyntaxRegExp_ExecuteMatch, 3)                                            \
+  V(RegExp_factory, 4)                                                         \
+  V(RegExp_getPattern, 1)                                                      \
+  V(RegExp_getIsMultiLine, 1)                                                  \
+  V(RegExp_getIsCaseSensitive, 1)                                              \
+  V(RegExp_getGroupCount, 1)                                                   \
+  V(RegExp_ExecuteMatch, 3)                                                    \
   V(List_allocate, 2)                                                          \
   V(List_getIndexed, 2)                                                        \
   V(List_setIndexed, 3)                                                        \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 81860b2..1a256cd 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -456,10 +456,9 @@
 }
 
 
-RawAbstractType* ClassFinalizer::ResolveTypeClass(const Class& cls,
-                                                  const Type& type) {
+void ClassFinalizer::ResolveTypeClass(const Class& cls, const Type& type) {
   if (type.IsFinalized()) {
-    return type.raw();
+    return;
   }
   if (FLAG_trace_type_finalization) {
     THR_Print("Resolve type class of '%s'\n",
@@ -489,66 +488,61 @@
           "cannot resolve class '%s' from '%s'",
           String::Handle(unresolved_class.Name()).ToCString(),
           String::Handle(cls.Name()).ToCString());
-      return type.raw();
+      return;
     }
+    // Replace unresolved class with resolved type class.
+    type.set_type_class(type_class);
   }
-  // Promote the Type to a FunctionType in case its type class is a typedef.
-  if (type_class.IsTypedefClass()) {
-    return FunctionType::New(type_class,
-                             TypeArguments::Handle(type.arguments()),
-                             Function::Handle(type_class.signature_function()),
-                             type.token_pos());
+  // Promote the type to a function type in case its type class is a typedef.
+  // Note that the type may already be a function type if it was parsed as a
+  // formal parameter function type.
+  if (!type.IsFunctionType() &&
+      type_class.IsTypedefClass() &&
+      !type.IsMalformedOrMalbounded()) {
+    type.set_signature(Function::Handle(type_class.signature_function()));
   }
-  // Replace unresolved class with resolved type class.
-  type.set_type_class(type_class);
-  return type.raw();
+  ASSERT(!type_class.IsTypedefClass() ||
+         (type.signature() != Function::null()));
 }
 
 
-RawAbstractType* ClassFinalizer::ResolveType(const Class& cls,
-                                             const AbstractType& type) {
+void ClassFinalizer::ResolveType(const Class& cls, const AbstractType& type) {
   if (type.IsResolved()) {
-    return type.raw();
+    return;
   }
   if (FLAG_trace_type_finalization) {
     THR_Print("Resolve type '%s'\n", String::Handle(type.Name()).ToCString());
   }
-  AbstractType& resolved_type = AbstractType::Handle();
   if (type.IsType()) {
-    resolved_type = ResolveTypeClass(cls, Type::Cast(type));
-    if (resolved_type.IsMalformed()) {
-      ASSERT(resolved_type.IsResolved());
-      return resolved_type.raw();
+    ResolveTypeClass(cls, Type::Cast(type));
+    if (type.IsMalformed()) {
+      ASSERT(type.IsResolved());
+      return;
     }
-  } else {
-    ASSERT(type.IsFunctionType());
-    const Function& signature =
-        Function::Handle(FunctionType::Cast(type).signature());
-    const Class& scope_class =
-        Class::Handle(FunctionType::Cast(type).scope_class());
-    if (scope_class.IsTypedefClass()) {
-      ResolveSignature(scope_class, signature);
-    } else {
-      ResolveSignature(cls, signature);
-    }
-    resolved_type = type.raw();
   }
-  // Mark type as resolved before resolving its type arguments in order to avoid
-  // repeating resolution of recursive types.
-  resolved_type.SetIsResolved();
+  // Mark type as resolved before resolving its type arguments and, in case of a
+  // function type, its signature, in order to avoid cycles.
+  type.SetIsResolved();
   // Resolve type arguments, if any.
-  const TypeArguments& arguments =
-      TypeArguments::Handle(resolved_type.arguments());
+  const TypeArguments& arguments = TypeArguments::Handle(type.arguments());
   if (!arguments.IsNull()) {
     const intptr_t num_arguments = arguments.Length();
     AbstractType& type_argument = AbstractType::Handle();
     for (intptr_t i = 0; i < num_arguments; i++) {
       type_argument = arguments.TypeAt(i);
-      type_argument = ResolveType(cls, type_argument);
-      arguments.SetTypeAt(i, type_argument);
+      ResolveType(cls, type_argument);
     }
   }
-  return resolved_type.raw();
+  // Resolve signature if function type.
+  if (type.IsFunctionType()) {
+    const Function& signature = Function::Handle(Type::Cast(type).signature());
+    const Class& scope_class = Class::Handle(type.type_class());
+    if (scope_class.IsTypedefClass()) {
+      ResolveSignature(scope_class, signature);
+    } else {
+      ResolveSignature(cls, signature);
+    }
+  }
 }
 
 
@@ -654,13 +648,13 @@
     const Class& cls,
     const AbstractType& type,
     PendingTypes* pending_types) {
-  Zone* Z = Thread::Current()->zone();
+  Zone* zone = Thread::Current()->zone();
   // The type class does not need to be finalized in order to finalize the type,
   // however, it must at least be resolved (this was done as part of resolving
   // the type itself, a precondition to calling FinalizeType).
   // Also, the interfaces of the type class must be resolved and the type
   // parameters of the type class must be finalized.
-  Class& type_class = Class::Handle(Z, type.type_class());
+  Class& type_class = Class::Handle(zone, type.type_class());
   if (!type_class.is_type_finalized()) {
     FinalizeTypeParameters(type_class, pending_types);
     ResolveUpperBounds(type_class);
@@ -673,18 +667,18 @@
 
   // If we are not reifying types, drop type arguments.
   if (!FLAG_reify) {
-    type.set_arguments(TypeArguments::Handle(Z, TypeArguments::null()));
+    type.set_arguments(TypeArguments::Handle(zone, TypeArguments::null()));
   }
 
   // Initialize the type argument vector.
   // Check the number of parsed type arguments, if any.
   // Specifying no type arguments indicates a raw type, which is not an error.
   // However, type parameter bounds are checked below, even for a raw type.
-  TypeArguments& arguments = TypeArguments::Handle(Z, type.arguments());
+  TypeArguments& arguments = TypeArguments::Handle(zone, type.arguments());
   if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) {
     // Wrong number of type arguments. The type is mapped to the raw type.
     if (Isolate::Current()->error_on_bad_type()) {
-      const String& type_class_name = String::Handle(Z, type_class.Name());
+      const String& type_class_name = String::Handle(zone, type_class.Name());
       ReportError(cls, type.token_pos(),
                   "wrong number of type arguments for class '%s'",
                   type_class_name.ToCString());
@@ -704,7 +698,7 @@
   // The full type argument vector consists of the type arguments of the
   // super types of type_class, which are initialized from the parsed
   // type arguments, followed by the parsed type arguments.
-  TypeArguments& full_arguments = TypeArguments::Handle(Z);
+  TypeArguments& full_arguments = TypeArguments::Handle(zone);
   if (FLAG_reify && (num_type_arguments > 0)) {
     // If no type arguments were parsed and if the super types do not prepend
     // type arguments to the vector, we can leave the vector as null.
@@ -714,7 +708,7 @@
       // argument vector.
       const intptr_t offset = num_type_arguments - num_type_parameters;
       AbstractType& type_arg =
-          AbstractType::Handle(Z, Type::DynamicType());
+          AbstractType::Handle(zone, Type::DynamicType());
       // Leave the temporary type arguments at indices [0..offset[ as null.
       for (intptr_t i = 0; i < num_type_parameters; i++) {
         // If no type parameters were provided, a raw type is desired, so we
@@ -746,8 +740,8 @@
         }
       }
       if (offset > 0) {
-        TrailPtr instantiation_trail = new Trail(Z, 4);
-        Error& bound_error = Error::Handle(Z);
+        TrailPtr instantiation_trail = new Trail(zone, 4);
+        Error& bound_error = Error::Handle(zone);
         FinalizeTypeArguments(type_class, full_arguments, offset,
                               &bound_error, pending_types, instantiation_trail);
       }
@@ -768,8 +762,8 @@
            !full_arguments.IsRaw(0, num_type_arguments));
     if (FLAG_trace_type_finalization) {
       THR_Print("Marking type '%s' as finalized for class '%s'\n",
-                String::Handle(Z, type.Name()).ToCString(),
-                String::Handle(Z, cls.Name()).ToCString());
+                String::Handle(zone, type.Name()).ToCString(),
+                String::Handle(zone, cls.Name()).ToCString());
     }
     // Mark the type as finalized.
     type.SetIsFinalized();
@@ -846,7 +840,7 @@
         super_type_arg = super_type_args.TypeAt(i);
         if (!super_type_arg.IsTypeRef()) {
           if (super_type_arg.IsBeingFinalized()) {
-            ASSERT(super_type_arg.IsType() || super_type_arg.IsFunctionType());
+            ASSERT(super_type_arg.IsType());
             CheckRecursiveType(cls, super_type_arg, pending_types);
             if (FLAG_trace_type_finalization) {
               THR_Print("Creating TypeRef '%s': '%s'\n",
@@ -1005,8 +999,7 @@
               TypeParameter::Cast(type_arg).parameterized_class());
           AbstractType& bound = AbstractType::Handle(
               TypeParameter::Cast(type_arg).bound());
-          bound = ResolveType(type_arg_cls, bound);
-          TypeParameter::Cast(type_arg).set_bound(bound);
+          ResolveType(type_arg_cls, bound);
         }
         // This may be called only if type needs to be finalized, therefore
         // seems OK to allocate finalized types in old space.
@@ -1033,21 +1026,21 @@
 
 void ClassFinalizer::CheckTypeBounds(const Class& cls,
                                      const AbstractType& type) {
-  Zone* Z = Thread::Current()->zone();
-  ASSERT(type.IsType() || type.IsFunctionType());
+  Zone* zone = Thread::Current()->zone();
+  ASSERT(type.IsType());
   ASSERT(type.IsFinalized());
   ASSERT(!type.IsCanonical());
-  TypeArguments& arguments = TypeArguments::Handle(Z, type.arguments());
+  TypeArguments& arguments = TypeArguments::Handle(zone, type.arguments());
   if (arguments.IsNull()) {
     return;
   }
   if (FLAG_trace_type_finalization) {
     THR_Print("Checking bounds of type '%s' for class '%s'\n",
-              String::Handle(Z, type.Name()).ToCString(),
-              String::Handle(Z, cls.Name()).ToCString());
+              String::Handle(zone, type.Name()).ToCString(),
+              String::Handle(zone, cls.Name()).ToCString());
   }
-  const Class& type_class = Class::Handle(Z, type.type_class());
-  Error& bound_error = Error::Handle(Z);
+  const Class& type_class = Class::Handle(zone, type.type_class());
+  Error& bound_error = Error::Handle(zone);
   CheckTypeArgumentBounds(type_class, arguments, &bound_error);
   // CheckTypeArgumentBounds may have indirectly canonicalized this type.
   if (!type.IsCanonical()) {
@@ -1056,22 +1049,22 @@
     // The bound error will be ignored in production mode.
     if (!bound_error.IsNull()) {
       // No compile-time error during finalization.
-      const String& type_name = String::Handle(Z, type.UserVisibleName());
+      const String& type_name = String::Handle(zone, type.UserVisibleName());
       FinalizeMalboundedType(bound_error,
-                             Script::Handle(Z, cls.script()),
+                             Script::Handle(zone, cls.script()),
                              type,
                              "type '%s' has an out of bound type argument",
                              type_name.ToCString());
       if (FLAG_trace_type_finalization) {
         THR_Print("Marking type '%s' as malbounded: %s\n",
-                  String::Handle(Z, type.Name()).ToCString(),
+                  String::Handle(zone, type.Name()).ToCString(),
                   bound_error.ToErrorCString());
       }
     }
   }
   if (FLAG_trace_type_finalization) {
     THR_Print("Done checking bounds of type '%s': %s\n",
-              String::Handle(Z, type.Name()).ToCString(),
+              String::Handle(zone, type.Name()).ToCString(),
               type.ToCString());
   }
 }
@@ -1091,7 +1084,7 @@
     if ((finalization >= kCanonicalize) &&
         !type.IsMalformed() &&
         !type.IsCanonical() &&
-        (type.IsType() || type.IsFunctionType())) {
+        type.IsType()) {
       CheckTypeBounds(cls, type);
       return type.Canonicalize();
     }
@@ -1109,25 +1102,24 @@
   // encountered here.
   ASSERT(!type.IsBeingFinalized());
 
-  Zone* Z = Thread::Current()->zone();
-  const AbstractType& resolved_type =
-      AbstractType::Handle(Z, ResolveType(cls, type));
+  Zone* zone = Thread::Current()->zone();
+  ResolveType(cls, type);
   // A malformed type gets mapped to a finalized type.
-  if (resolved_type.IsMalformed()) {
-    ASSERT(resolved_type.IsFinalized());
-    return resolved_type.raw();
+  if (type.IsMalformed()) {
+    ASSERT(type.IsFinalized());
+    return type.raw();
   }
 
   if (FLAG_trace_type_finalization) {
     THR_Print("Finalizing type '%s' for class '%s'\n",
-              String::Handle(Z, resolved_type.Name()).ToCString(),
-              String::Handle(Z, cls.Name()).ToCString());
+              String::Handle(zone, type.Name()).ToCString(),
+              String::Handle(zone, cls.Name()).ToCString());
   }
 
-  if (resolved_type.IsTypeParameter()) {
-    const TypeParameter& type_parameter = TypeParameter::Cast(resolved_type);
+  if (type.IsTypeParameter()) {
+    const TypeParameter& type_parameter = TypeParameter::Cast(type);
     const Class& parameterized_class =
-        Class::Handle(Z, type_parameter.parameterized_class());
+        Class::Handle(zone, type_parameter.parameterized_class());
     ASSERT(!parameterized_class.IsNull());
     // The index must reflect the position of this type parameter in the type
     // arguments vector of its parameterized class. The offset to add is the
@@ -1147,7 +1139,7 @@
 
     if (FLAG_trace_type_finalization) {
       THR_Print("Done finalizing type parameter '%s' with index %" Pd "\n",
-                String::Handle(Z, type_parameter.name()).ToCString(),
+                String::Handle(zone, type_parameter.name()).ToCString(),
                 type_parameter.index());
     }
 
@@ -1155,18 +1147,18 @@
     return type_parameter.raw();
   }
 
-  // At this point, we can only have a Type or a FunctionType.
-  ASSERT(resolved_type.IsType() || resolved_type.IsFunctionType());
+  // At this point, we can only have a Type.
+  ASSERT(type.IsType());
 
   // This type is the root type of the type graph if no pending types queue is
   // allocated yet.
   const bool is_root_type = (pending_types == NULL);
   if (is_root_type) {
-    pending_types = new PendingTypes(Z, 4);
+    pending_types = new PendingTypes(zone, 4);
   }
 
   const intptr_t num_expanded_type_arguments =
-      ExpandAndFinalizeTypeArguments(cls, resolved_type, pending_types);
+      ExpandAndFinalizeTypeArguments(cls, type, pending_types);
 
   // If we are done finalizing a graph of mutually recursive types, check their
   // bounds.
@@ -1179,18 +1171,18 @@
     }
   }
 
-  // If the type is a FunctionType, we also need to finalize the types in its
+  // If the type is a function type, we also need to finalize the types in its
   // signature, i.e. finalize the result type and parameter types of the
   // signature function of this function type.
   // We do this after marking this type as finalized in order to allow a
   // function type to refer to itself via its parameter types and result type.
   // Note that we do not instantiate these types according to the type
   // arguments. This will happen on demand when executing a type test.
-  if (resolved_type.IsFunctionType()) {
+  if (type.IsFunctionType()) {
     const Function& signature =
-        Function::Handle(Z, FunctionType::Cast(resolved_type).signature());
+        Function::Handle(zone, Type::Cast(type).signature());
     const Class& scope_class =
-        Class::Handle(Z, FunctionType::Cast(resolved_type).scope_class());
+        Class::Handle(zone, Type::Cast(type).type_class());
     if (scope_class.IsTypedefClass()) {
       FinalizeSignature(scope_class, signature);
     } else {
@@ -1200,24 +1192,24 @@
 
   if (FLAG_trace_type_finalization) {
     THR_Print("Done finalizing type '%s' with %" Pd " type args: %s\n",
-              String::Handle(Z, resolved_type.Name()).ToCString(),
+              String::Handle(zone, type.Name()).ToCString(),
               num_expanded_type_arguments,
-              resolved_type.ToCString());
+              type.ToCString());
   }
 
   if (finalization >= kCanonicalize) {
     if (FLAG_trace_type_finalization) {
       THR_Print("Canonicalizing type '%s'\n",
-                String::Handle(Z, resolved_type.Name()).ToCString());
+                String::Handle(zone, type.Name()).ToCString());
       AbstractType& canonical_type =
-          AbstractType::Handle(Z, resolved_type.Canonicalize());
+          AbstractType::Handle(zone, type.Canonicalize());
       THR_Print("Done canonicalizing type '%s'\n",
-                String::Handle(Z, canonical_type.Name()).ToCString());
+                String::Handle(zone, canonical_type.Name()).ToCString());
       return canonical_type.raw();
     }
-    return resolved_type.Canonicalize();
+    return type.Canonicalize();
   } else {
-    return resolved_type.raw();
+    return type.raw();
   }
 }
 
@@ -1228,18 +1220,12 @@
   AbstractType& type = AbstractType::Handle(function.result_type());
   // It is not a compile time error if this name does not resolve to a class or
   // interface.
-  AbstractType& resolved_type = AbstractType::Handle(ResolveType(cls, type));
-  if (resolved_type.raw() != type.raw()) {
-    function.set_result_type(resolved_type);
-  }
+  ResolveType(cls, type);
   // Resolve formal parameter types.
   const intptr_t num_parameters = function.NumParameters();
   for (intptr_t i = 0; i < num_parameters; i++) {
     type = function.ParameterTypeAt(i);
-    resolved_type = ResolveType(cls, type);
-    if (resolved_type.raw() != type.raw()) {
-      function.SetParameterTypeAt(i, resolved_type);
-    }
+    ResolveType(cls, type);
   }
 }
 
@@ -1330,8 +1316,7 @@
   for (intptr_t i = 0; i < num_type_params; i++) {
     type_param ^= type_params.TypeAt(i);
     bound = type_param.bound();
-    bound = ResolveType(cls, bound);
-    type_param.set_bound(bound);
+    ResolveType(cls, bound);
   }
 }
 
@@ -1382,14 +1367,14 @@
   //   instance method.
 
   // Resolve type of fields and check for conflicts in super classes.
-  Zone* Z = Thread::Current()->zone();
-  Array& array = Array::Handle(Z, cls.fields());
-  Field& field = Field::Handle(Z);
-  AbstractType& type = AbstractType::Handle(Z);
-  String& name = String::Handle(Z);
-  String& getter_name = String::Handle(Z);
-  String& setter_name = String::Handle(Z);
-  Class& super_class = Class::Handle(Z);
+  Zone* zone = Thread::Current()->zone();
+  Array& array = Array::Handle(zone, cls.fields());
+  Field& field = Field::Handle(zone);
+  AbstractType& type = AbstractType::Handle(zone);
+  String& name = String::Handle(zone);
+  String& getter_name = String::Handle(zone);
+  String& setter_name = String::Handle(zone);
+  Class& super_class = Class::Handle(zone);
   const intptr_t num_fields = array.Length();
   for (intptr_t i = 0; i < num_fields; i++) {
     field ^= array.At(i);
@@ -1401,15 +1386,15 @@
       getter_name = Field::GetterSymbol(name);
       super_class = FindSuperOwnerOfInstanceMember(cls, name, getter_name);
       if (!super_class.IsNull()) {
-        const String& class_name = String::Handle(Z, cls.Name());
-        const String& super_class_name = String::Handle(Z, super_class.Name());
+        const String& class_name = String::Handle(zone, cls.Name());
+        const String& super_cls_name = String::Handle(zone, super_class.Name());
         ReportError(cls, field.token_pos(),
                     "static field '%s' of class '%s' conflicts with "
                     "instance member '%s' of super class '%s'",
                     name.ToCString(),
                     class_name.ToCString(),
                     name.ToCString(),
-                    super_class_name.ToCString());
+                    super_cls_name.ToCString());
       }
       // An implicit setter is not generated for a static field, therefore, we
       // cannot rely on the code below handling the static setter case to report
@@ -1417,15 +1402,15 @@
       setter_name = Field::SetterSymbol(name);
       super_class = FindSuperOwnerOfFunction(cls, setter_name);
       if (!super_class.IsNull()) {
-        const String& class_name = String::Handle(Z, cls.Name());
-        const String& super_class_name = String::Handle(Z, super_class.Name());
+        const String& class_name = String::Handle(zone, cls.Name());
+        const String& super_cls_name = String::Handle(zone, super_class.Name());
         ReportError(cls, field.token_pos(),
                     "static field '%s' of class '%s' conflicts with "
                     "instance setter '%s=' of super class '%s'",
                     name.ToCString(),
                     class_name.ToCString(),
                     name.ToCString(),
-                    super_class_name.ToCString());
+                    super_cls_name.ToCString());
       }
 
     } else {
@@ -1433,15 +1418,15 @@
       // (but not getter).
       super_class = FindSuperOwnerOfFunction(cls, name);
       if (!super_class.IsNull()) {
-        const String& class_name = String::Handle(Z, cls.Name());
-        const String& super_class_name = String::Handle(Z, super_class.Name());
+        const String& class_name = String::Handle(zone, cls.Name());
+        const String& super_cls_name = String::Handle(zone, super_class.Name());
         ReportError(cls, field.token_pos(),
                     "field '%s' of class '%s' conflicts with method '%s' "
                     "of super class '%s'",
                     name.ToCString(),
                     class_name.ToCString(),
                     name.ToCString(),
-                    super_class_name.ToCString());
+                    super_cls_name.ToCString());
       }
     }
     if (field.is_static() &&
@@ -1449,14 +1434,14 @@
         (field.StaticValue() != Object::sentinel().raw())) {
       // The parser does not preset the value if the type is a type parameter or
       // is parameterized unless the value is null.
-      Error& error = Error::Handle(Z);
+      Error& error = Error::Handle(zone);
       if (type.IsMalformedOrMalbounded()) {
         error = type.error();
       } else {
         ASSERT(type.IsInstantiated());
       }
       const Instance& const_value =
-          Instance::Handle(Z, field.StaticValue());
+          Instance::Handle(zone, field.StaticValue());
       if (!error.IsNull() ||
           (!type.IsDynamicType() &&
            !const_value.IsInstanceOf(type,
@@ -1464,10 +1449,11 @@
                                      &error))) {
         if (Isolate::Current()->error_on_bad_type()) {
           const AbstractType& const_value_type = AbstractType::Handle(
-              Z, const_value.GetType());
+              zone, const_value.GetType());
           const String& const_value_type_name = String::Handle(
-              Z, const_value_type.UserVisibleName());
-          const String& type_name = String::Handle(Z, type.UserVisibleName());
+              zone, const_value_type.UserVisibleName());
+          const String& type_name = String::Handle(
+              zone, type.UserVisibleName());
           ReportErrors(error, cls, field.token_pos(),
                        "error initializing static %s field '%s': "
                        "type '%s' is not a subtype of type '%s'",
@@ -1485,7 +1471,7 @@
           // we create an implicit static final getter and reset the field value
           // to the sentinel value.
           const Function& getter = Function::Handle(
-              Z,
+              zone,
               Function::New(getter_name,
                             RawFunction::kImplicitStaticFinalGetter,
                             /* is_static = */ true,
@@ -1504,22 +1490,22 @@
     }
   }
   // Collect interfaces, super interfaces, and super classes of this class.
-  GrowableArray<const Class*> interfaces(Z, 4);
+  GrowableArray<const Class*> interfaces(zone, 4);
   CollectInterfaces(cls, &interfaces);
   // Include superclasses in list of interfaces and super interfaces.
   super_class = cls.SuperClass();
   while (!super_class.IsNull()) {
-    interfaces.Add(&Class::ZoneHandle(Z, super_class.raw()));
+    interfaces.Add(&Class::ZoneHandle(zone, super_class.raw()));
     CollectInterfaces(super_class, &interfaces);
     super_class = super_class.SuperClass();
   }
   // Resolve function signatures and check for conflicts in super classes and
   // interfaces.
   array = cls.functions();
-  Function& function = Function::Handle(Z);
-  Function& overridden_function = Function::Handle(Z);
+  Function& function = Function::Handle(zone);
+  Function& overridden_function = Function::Handle(zone);
   const intptr_t num_functions = array.Length();
-  Error& error = Error::Handle(Z);
+  Error& error = Error::Handle(zone);
   for (intptr_t i = 0; i < num_functions; i++) {
     function ^= array.At(i);
     FinalizeSignature(cls, function);
@@ -1537,15 +1523,15 @@
         if (!overridden_function.IsNull() &&
             !function.HasCompatibleParametersWith(overridden_function,
                                                   &error)) {
-          const String& class_name = String::Handle(Z, cls.Name());
-          const String& super_class_name =
-              String::Handle(Z, super_class->Name());
+          const String& class_name = String::Handle(zone, cls.Name());
+          const String& super_cls_name =
+              String::Handle(zone, super_class->Name());
           ReportErrors(error, cls, function.token_pos(),
                        "class '%s' overrides method '%s' of super "
                        "class '%s' with incompatible parameters",
                        class_name.ToCString(),
                        name.ToCString(),
-                       super_class_name.ToCString());
+                       super_cls_name.ToCString());
         }
       }
     }
@@ -1553,16 +1539,16 @@
       if (function.is_static()) {
         super_class = FindSuperOwnerOfFunction(cls, name);
         if (!super_class.IsNull()) {
-          const String& class_name = String::Handle(Z, cls.Name());
-          const String& super_class_name =
-              String::Handle(Z, super_class.Name());
+          const String& class_name = String::Handle(zone, cls.Name());
+          const String& super_cls_name =
+              String::Handle(zone, super_class.Name());
           ReportError(cls, function.token_pos(),
                       "static setter '%s=' of class '%s' conflicts with "
                       "instance setter '%s=' of super class '%s'",
                       name.ToCString(),
                       class_name.ToCString(),
                       name.ToCString(),
-                      super_class_name.ToCString());
+                      super_cls_name.ToCString());
         }
       }
       continue;
@@ -1576,8 +1562,8 @@
     if (function.is_static()) {
       super_class = FindSuperOwnerOfInstanceMember(cls, name, getter_name);
       if (!super_class.IsNull()) {
-        const String& class_name = String::Handle(Z, cls.Name());
-        const String& super_class_name = String::Handle(Z, super_class.Name());
+        const String& class_name = String::Handle(zone, cls.Name());
+        const String& super_cls_name = String::Handle(zone, super_class.Name());
         ReportError(cls, function.token_pos(),
                     "static %s '%s' of class '%s' conflicts with "
                     "instance member '%s' of super class '%s'",
@@ -1586,7 +1572,7 @@
                     name.ToCString(),
                     class_name.ToCString(),
                     name.ToCString(),
-                    super_class_name.ToCString());
+                    super_cls_name.ToCString());
       }
       if (function.IsRedirectingFactory()) {
         // The function may be a still unresolved redirecting factory. Do not
@@ -1594,7 +1580,7 @@
         // However, the redirection type should be finalized.
         // If the redirection type is from a deferred library and is not
         // yet loaded, do not attempt to resolve.
-        Type& type = Type::Handle(Z, function.RedirectionType());
+        Type& type = Type::Handle(zone, function.RedirectionType());
         if (IsLoaded(type)) {
           type ^= FinalizeType(cls, type, kCanonicalize);
           function.SetRedirectionType(type);
@@ -1604,15 +1590,15 @@
                function.IsImplicitGetterFunction()) {
       super_class = FindSuperOwnerOfFunction(cls, name);
       if (!super_class.IsNull()) {
-        const String& class_name = String::Handle(Z, cls.Name());
-        const String& super_class_name = String::Handle(Z, super_class.Name());
+        const String& class_name = String::Handle(zone, cls.Name());
+        const String& super_cls_name = String::Handle(zone, super_class.Name());
         ReportError(cls, function.token_pos(),
                     "getter '%s' of class '%s' conflicts with "
                     "method '%s' of super class '%s'",
                     name.ToCString(),
                     class_name.ToCString(),
                     name.ToCString(),
-                    super_class_name.ToCString());
+                    super_cls_name.ToCString());
       }
     } else if (!function.IsSetterFunction() &&
                !function.IsImplicitSetterFunction()) {
@@ -1620,15 +1606,15 @@
       // have the same name. Thus, we do not need to check setters.
       super_class = FindSuperOwnerOfFunction(cls, getter_name);
       if (!super_class.IsNull()) {
-        const String& class_name = String::Handle(Z, cls.Name());
-        const String& super_class_name = String::Handle(Z, super_class.Name());
+        const String& class_name = String::Handle(zone, cls.Name());
+        const String& super_cls_name = String::Handle(zone, super_class.Name());
         ReportError(cls, function.token_pos(),
                     "method '%s' of class '%s' conflicts with "
                     "getter '%s' of super class '%s'",
                     name.ToCString(),
                     class_name.ToCString(),
                     name.ToCString(),
-                    super_class_name.ToCString());
+                    super_cls_name.ToCString());
       }
     }
   }
@@ -2362,7 +2348,7 @@
   }
   if (cls.IsTypedefClass()) {
     const Function& signature = Function::Handle(cls.signature_function());
-    FunctionType& type = FunctionType::Handle(signature.SignatureType());
+    Type& type = Type::Handle(signature.SignatureType());
 
     // Check for illegal self references.
     GrowableArray<intptr_t> visited_aliases;
@@ -2590,15 +2576,14 @@
                                         const AbstractType& type,
                                         GrowableArray<intptr_t>* visited) {
   ASSERT(visited != NULL);
-  AbstractType& resolved_type = AbstractType::Handle(ResolveType(cls, type));
+  ResolveType(cls, type);
   bool checking_typedef = false;
-  if ((resolved_type.IsType() || resolved_type.IsFunctionType()) &&
-      !resolved_type.IsMalformed()) {
+  if (type.IsType() && !type.IsMalformed()) {
     AbstractType& other_type = AbstractType::Handle();
-    if (resolved_type.IsFunctionType()) {
-      const Class& scope_class = Class::Handle(resolved_type.type_class());
+    if (type.IsFunctionType()) {
+      const Class& scope_class = Class::Handle(type.type_class());
       const Function& signature_function =
-          Function::Handle(FunctionType::Cast(resolved_type).signature());
+          Function::Handle(Type::Cast(type).signature());
       // The signature function of this function type may be a local signature
       // function used in a formal parameter type of the typedef signature, but
       // not the typedef signature function itself, thus not qualifying as an
@@ -2645,8 +2630,7 @@
         }
       }
     }
-    const TypeArguments& type_args =
-        TypeArguments::Handle(resolved_type.arguments());
+    const TypeArguments& type_args = TypeArguments::Handle(type.arguments());
     if (!type_args.IsNull()) {
       for (intptr_t i = 0; i < type_args.Length(); i++) {
         other_type = type_args.TypeAt(i);
@@ -2746,7 +2730,7 @@
       GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
   AbstractType& mixin_super_type =
       AbstractType::Handle(zone, mixin_app_type.super_type());
-  mixin_super_type = ResolveType(cls, mixin_super_type);
+  ResolveType(cls, mixin_super_type);
   ASSERT(mixin_super_type.HasResolvedTypeClass());  // Even if malformed.
   if (mixin_super_type.IsMalformedOrMalbounded()) {
     ReportError(Error::Handle(zone, mixin_super_type.error()));
@@ -2770,7 +2754,7 @@
   for (intptr_t i = 0; i < depth; i++) {
     mixin_type = mixin_app_type.MixinTypeAt(i);
     ASSERT(!mixin_type.IsNull());
-    mixin_type = ResolveType(cls, mixin_type);
+    ResolveType(cls, mixin_type);
     ASSERT(mixin_type.HasResolvedTypeClass());  // Even if malformed.
     ASSERT(mixin_type.IsType());
     const intptr_t num_super_type_args = type_args.Length();
@@ -2931,7 +2915,7 @@
   Class& interface_class = Class::Handle(zone);
 
   // Resolve super type. Failures lead to a longjmp.
-  super_type = ResolveType(cls, super_type);
+  ResolveType(cls, super_type);
   if (super_type.IsMalformedOrMalbounded()) {
     ReportError(Error::Handle(zone, super_type.error()));
   }
@@ -3011,7 +2995,7 @@
   // Resolve interfaces. Failures lead to a longjmp.
   for (intptr_t i = 0; i < super_interfaces.Length(); i++) {
     interface ^= super_interfaces.At(i);
-    interface = ResolveType(cls, interface);
+    ResolveType(cls, interface);
     ASSERT(!interface.IsTypeParameter());  // Should be detected by parser.
     // A malbounded interface is only reported when involved in a type test.
     if (interface.IsMalformed()) {
diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h
index e630df0..81850f6 100644
--- a/runtime/vm/class_finalizer.h
+++ b/runtime/vm/class_finalizer.h
@@ -89,8 +89,8 @@
 #endif  // defined(DART_NO_SNAPSHOT).
 
   // Resolve the class of the type, but not the type's type arguments.
-  // May promote the type from Type to FunctionType.
-  static RawAbstractType* ResolveTypeClass(const Class& cls, const Type& type);
+  // May promote the type to function type by setting its signature field.
+  static void ResolveTypeClass(const Class& cls, const Type& type);
 
   // Resolve the type and target of the redirecting factory.
   static void ResolveRedirectingFactory(const Class& cls,
@@ -111,8 +111,7 @@
   static void CheckForLegalConstClass(const Class& cls);
   static RawClass* ResolveClass(const Class& cls,
                                 const UnresolvedClass& unresolved_class);
-  static RawAbstractType* ResolveType(const Class& cls,
-                                      const AbstractType& type);
+  static void ResolveType(const Class& cls, const AbstractType& type);
   static void ResolveRedirectingFactoryTarget(
       const Class& cls,
       const Function& factory,
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 85212a7..bb7d5e0 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1262,17 +1262,17 @@
 #if defined(USING_SIMULATOR)
   uword stack_pos = Simulator::Current()->get_register(SPREG);
 #else
-  uword stack_pos = Isolate::GetCurrentStackPointer();
+  uword stack_pos = Thread::GetCurrentStackPointer();
 #endif
   // Always clear the stack overflow flags.  They are meant for this
   // particular stack overflow runtime call and are not meant to
   // persist.
-  uword stack_overflow_flags = isolate->GetAndClearStackOverflowFlags();
+  uword stack_overflow_flags = thread->GetAndClearStackOverflowFlags();
 
   // 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 < isolate->saved_stack_limit()) {
+  if (stack_pos < thread->saved_stack_limit()) {
     // Use the preallocated stack overflow exception to avoid calling
     // into dart code.
     const Instance& exception =
@@ -1289,7 +1289,7 @@
     // TODO(turnidge): To make --deoptimize_every and
     // --stacktrace-every faster we could move this increment/test to
     // the generated code.
-    int32_t count = isolate->IncrementAndGetStackOverflowCount();
+    int32_t count = thread->IncrementAndGetStackOverflowCount();
     if (FLAG_deoptimize_every > 0 &&
         (count % FLAG_deoptimize_every) == 0) {
       do_deopt = true;
@@ -1344,13 +1344,13 @@
     }
   }
 
-  const Error& error = Error::Handle(isolate->HandleInterrupts());
+  const Error& error = Error::Handle(thread->HandleInterrupts());
   if (!error.IsNull()) {
     Exceptions::PropagateError(error);
     UNREACHABLE();
   }
 
-  if ((stack_overflow_flags & Isolate::kOsrRequest) != 0) {
+  if ((stack_overflow_flags & Thread::kOsrRequest) != 0) {
     ASSERT(FLAG_use_osr);
     DartFrameIterator iterator;
     StackFrame* frame = iterator.NextFrame();
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index dd5f71c..d7a889c 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -40,6 +40,7 @@
 #include "vm/symbols.h"
 #include "vm/tags.h"
 #include "vm/thread_registry.h"
+#include "vm/timeline.h"
 #include "vm/timer.h"
 
 namespace dart {
@@ -278,7 +279,7 @@
 NOT_IN_PRODUCT(
   VMTagScope tagScope(thread, VMTag::kCompileClassTagId);
   TimelineDurationScope tds(thread,
-                            thread->isolate()->GetCompilerStream(),
+                            Timeline::GetCompilerStream(),
                             "CompileClass");
   if (tds.enabled()) {
     tds.SetNumArguments(1);
@@ -487,10 +488,12 @@
   }
 );
   if (optimized()) {
+    bool code_was_installed = false;
     // Installs code while at safepoint.
     if (thread()->IsMutatorThread()) {
       const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
       function.InstallOptimizedCode(code, is_osr);
+      code_was_installed = true;
     } else {
       // Background compilation.
       // Before installing code check generation counts if the code may
@@ -527,28 +530,36 @@
       }
       if (code_is_valid) {
         const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
-        ASSERT(!is_osr);  // OSR is compiled in background.
+        ASSERT(!is_osr);  // OSR is not compiled in background.
         function.InstallOptimizedCode(code, is_osr);
+        code_was_installed = true;
       }
       if (function.usage_counter() < 0) {
         // Reset to 0 so that it can be recompiled if needed.
-        function.set_usage_counter(0);
+        if (code_is_valid) {
+          function.set_usage_counter(0);
+        } else {
+          // Trigger another optimization pass soon.
+          function.set_usage_counter(FLAG_optimization_counter_threshold - 100);
+        }
       }
     }
 
-    // Register code with the classes it depends on because of CHA and
-    // fields it depends on because of store guards, unless we cannot
-    // deopt.
-    for (intptr_t i = 0;
-         i < thread()->cha()->leaf_classes().length();
-         ++i) {
-      thread()->cha()->leaf_classes()[i]->RegisterCHACode(code);
-    }
-    const ZoneGrowableArray<const Field*>& guarded_fields =
-        *flow_graph->parsed_function().guarded_fields();
-    for (intptr_t i = 0; i < guarded_fields.length(); i++) {
-      const Field* field = guarded_fields[i];
-      field->RegisterDependentCode(code);
+    if (code_was_installed) {
+      // Register code with the classes it depends on because of CHA and
+      // fields it depends on because of store guards, unless we cannot
+      // deopt.
+      for (intptr_t i = 0;
+           i < thread()->cha()->leaf_classes().length();
+           ++i) {
+        thread()->cha()->leaf_classes()[i]->RegisterCHACode(code);
+      }
+      const ZoneGrowableArray<const Field*>& guarded_fields =
+          *flow_graph->parsed_function().guarded_fields();
+      for (intptr_t i = 0; i < guarded_fields.length(); i++) {
+        const Field* field = guarded_fields[i];
+        field->RegisterDependentCode(code);
+      }
     }
   } else {  // not optimized.
     if (function.ic_data_array() == Array::null()) {
@@ -582,7 +593,7 @@
   bool is_compiled = false;
   Zone* const zone = thread()->zone();
   NOT_IN_PRODUCT(
-      TimelineStream* compiler_timeline = isolate()->GetCompilerStream());
+      TimelineStream* compiler_timeline = Timeline::GetCompilerStream());
   CSTAT_TIMER_SCOPE(thread(), codegen_timer);
   HANDLESCOPE(thread());
 
@@ -1237,8 +1248,10 @@
   }
 #endif
   Isolate* isolate = thread->isolate();
+NOT_IN_PRODUCT(
   VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId);
-  TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "Function", function);
+  TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "CompileFunction", function);
+)  // !PRODUCT
 
   if (!isolate->compilation_allowed()) {
     FATAL3("Precompilation missed function %s (%s, %s)\n",
@@ -1293,9 +1306,13 @@
 RawError* Compiler::CompileOptimizedFunction(Thread* thread,
                                              const Function& function,
                                              intptr_t osr_id) {
+NOT_IN_PRODUCT(
   VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId);
-  TIMELINE_FUNCTION_COMPILATION_DURATION(thread,
-                                         "OptimizedFunction", function);
+  const char* event_name = IsBackgroundCompilation()
+      ? "BackgroundCompileOptimizedFunction"
+      : "CompileOptimizedFunction";
+  TIMELINE_FUNCTION_COMPILATION_DURATION(thread, event_name, function);
+)  // !PRODUCT
 
   // Optimization must happen in non-mutator/Dart thread if background
   // compilation is on. OSR compilation still occurs in the main thread.
@@ -1463,7 +1480,7 @@
         false,  // not abstract
         false,  // not external
         false,  // not native
-        Class::Handle(Type::Handle(Type::Function()).type_class()),
+        Class::Handle(Type::Handle(Type::DartFunctionType()).type_class()),
         fragment->token_pos()));
 
     func.set_result_type(Object::dynamic_type());
@@ -1635,7 +1652,7 @@
   while (running_) {
     // Maybe something is already in the queue, check first before waiting
     // to be notified.
-    bool result = Thread::EnterIsolateAsHelper(isolate_);
+    bool result = Thread::EnterIsolateAsHelper(isolate_, Thread::kCompilerTask);
     ASSERT(result);
     {
       Thread* thread = Thread::Current();
diff --git a/runtime/vm/coverage.cc b/runtime/vm/coverage.cc
index 2e85c3d..7a678a0 100644
--- a/runtime/vm/coverage.cc
+++ b/runtime/vm/coverage.cc
@@ -253,9 +253,9 @@
     return;
   }
 
-  Dart_FileOpenCallback file_open = Isolate::file_open_callback();
-  Dart_FileWriteCallback file_write = Isolate::file_write_callback();
-  Dart_FileCloseCallback file_close = Isolate::file_close_callback();
+  Dart_FileOpenCallback file_open = Dart::file_open_callback();
+  Dart_FileWriteCallback file_write = Dart::file_write_callback();
+  Dart_FileCloseCallback file_close = Dart::file_close_callback();
   if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) {
     return;
   }
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 36ef3f0..9c07dc0 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -29,6 +29,7 @@
 #include "vm/symbols.h"
 #include "vm/thread_interrupter.h"
 #include "vm/thread_pool.h"
+#include "vm/timeline.h"
 #include "vm/virtual_memory.h"
 #include "vm/zone.h"
 
@@ -51,6 +52,12 @@
 ReadOnlyHandles* Dart::predefined_handles_ = NULL;
 const uint8_t* Dart::instructions_snapshot_buffer_ = NULL;
 const uint8_t* Dart::data_snapshot_buffer_ = NULL;
+Dart_ThreadExitCallback Dart::thread_exit_callback_ = NULL;
+Dart_FileOpenCallback Dart::file_open_callback_ = NULL;
+Dart_FileReadCallback Dart::file_read_callback_ = NULL;
+Dart_FileWriteCallback Dart::file_write_callback_ = NULL;
+Dart_FileCloseCallback Dart::file_close_callback_ = NULL;
+Dart_EntropySource Dart::entropy_source_callback_ = NULL;
 
 // Structure for managing read-only global handles allocation used for
 // creating global read-only handles that are pre created and initialized
@@ -81,6 +88,7 @@
                            const uint8_t* data_snapshot,
                            Dart_IsolateCreateCallback create,
                            Dart_IsolateShutdownCallback shutdown,
+                           Dart_ThreadExitCallback thread_exit,
                            Dart_FileOpenCallback file_open,
                            Dart_FileReadCallback file_read,
                            Dart_FileWriteCallback file_write,
@@ -91,8 +99,9 @@
   if (vm_isolate_ != NULL || !Flags::Initialized()) {
     return "VM already initialized or flags not initialized.";
   }
-  Isolate::SetFileCallbacks(file_open, file_read, file_write, file_close);
-  Isolate::SetEntropySourceCallback(entropy_source);
+  set_thread_exit_callback(thread_exit);
+  SetFileCallbacks(file_open, file_read, file_write, file_close);
+  set_entropy_source_callback(entropy_source);
   OS::InitOnce();
   VirtualMemory::InitOnce();
   OSThread::InitOnce();
@@ -391,7 +400,9 @@
   Thread* T = Thread::Current();
   Isolate* I = T->isolate();
   NOT_IN_PRODUCT(
-    TimelineDurationScope tds(T, I->GetIsolateStream(), "InitializeIsolate");
+    TimelineDurationScope tds(T,
+                              Timeline::GetIsolateStream(),
+                              "InitializeIsolate");
     tds.SetNumArguments(1);
     tds.CopyArgument(0, "isolateName", I->name());
   )
@@ -400,7 +411,7 @@
   HandleScope handle_scope(T);
   {
     NOT_IN_PRODUCT(TimelineDurationScope tds(T,
-        I->GetIsolateStream(), "ObjectStore::Init"));
+        Timeline::GetIsolateStream(), "ObjectStore::Init"));
     ObjectStore::Init(I);
   }
 
@@ -411,7 +422,7 @@
   if (snapshot_buffer != NULL) {
     // Read the snapshot and setup the initial state.
     NOT_IN_PRODUCT(TimelineDurationScope tds(T,
-        I->GetIsolateStream(), "IsolateSnapshotReader"));
+        Timeline::GetIsolateStream(), "IsolateSnapshotReader"));
     // TODO(turnidge): Remove once length is not part of the snapshot.
     const Snapshot* snapshot = Snapshot::SetupFromBuffer(snapshot_buffer);
     if (snapshot == NULL) {
@@ -449,7 +460,7 @@
 
   {
     NOT_IN_PRODUCT(TimelineDurationScope tds(T,
-        I->GetIsolateStream(), "StubCode::Init"));
+        Timeline::GetIsolateStream(), "StubCode::Init"));
     StubCode::Init(I);
   }
 
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index aa43e12..afa2499 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -26,6 +26,7 @@
       const uint8_t* data_snapshot,
       Dart_IsolateCreateCallback create,
       Dart_IsolateShutdownCallback shutdown,
+      Dart_ThreadExitCallback thread_exit,
       Dart_FileOpenCallback file_open,
       Dart_FileReadCallback file_read,
       Dart_FileWriteCallback file_write,
@@ -76,6 +77,42 @@
     data_snapshot_buffer_ = buffer;
   }
 
+  static Dart_ThreadExitCallback thread_exit_callback() {
+    return thread_exit_callback_;
+  }
+  static void set_thread_exit_callback(Dart_ThreadExitCallback cback) {
+    thread_exit_callback_ = cback;
+  }
+  static void SetFileCallbacks(Dart_FileOpenCallback file_open,
+                               Dart_FileReadCallback file_read,
+                               Dart_FileWriteCallback file_write,
+                               Dart_FileCloseCallback file_close) {
+    file_open_callback_ = file_open;
+    file_read_callback_ = file_read;
+    file_write_callback_ = file_write;
+    file_close_callback_ = file_close;
+  }
+
+  static Dart_FileOpenCallback file_open_callback() {
+    return file_open_callback_;
+  }
+  static Dart_FileReadCallback file_read_callback() {
+    return file_read_callback_;
+  }
+  static Dart_FileWriteCallback file_write_callback() {
+    return file_write_callback_;
+  }
+  static Dart_FileCloseCallback file_close_callback() {
+    return file_close_callback_;
+  }
+
+  static void set_entropy_source_callback(Dart_EntropySource entropy_source) {
+    entropy_source_callback_ = entropy_source;
+  }
+  static Dart_EntropySource entropy_source_callback() {
+    return entropy_source_callback_;
+  }
+
  private:
   static void WaitForIsolateShutdown();
 
@@ -86,6 +123,12 @@
   static ReadOnlyHandles* predefined_handles_;
   static const uint8_t* instructions_snapshot_buffer_;
   static const uint8_t* data_snapshot_buffer_;
+  static Dart_ThreadExitCallback thread_exit_callback_;
+  static Dart_FileOpenCallback file_open_callback_;
+  static Dart_FileReadCallback file_read_callback_;
+  static Dart_FileWriteCallback file_write_callback_;
+  static Dart_FileCloseCallback file_close_callback_;
+  static Dart_EntropySource entropy_source_callback_;
 };
 
 }  // namespace dart
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 12a7fdb..cb540bc 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -78,12 +78,12 @@
 #ifndef PRODUCT
 #define API_TIMELINE_DURATION                                                  \
   TimelineDurationScope tds(Thread::Current(),                                 \
-                            Timeline::GetVMApiStream(),                        \
+                            Timeline::GetAPIStream(),                          \
                             CURRENT_FUNC)
 
 #define API_TIMELINE_BEGIN_END                                                 \
   TimelineBeginEndScope tbes(Thread::Current(),                                \
-                             Timeline::GetVMApiStream(),                       \
+                             Timeline::GetAPIStream(),                         \
                              CURRENT_FUNC)
 #else
 #define API_TIMELINE_DURATION do { } while (false)
@@ -1139,6 +1139,7 @@
     Dart_IsolateInterruptCallback interrupt,
     Dart_IsolateUnhandledExceptionCallback unhandled,
     Dart_IsolateShutdownCallback shutdown,
+    Dart_ThreadExitCallback thread_exit,
     Dart_FileOpenCallback file_open,
     Dart_FileReadCallback file_read,
     Dart_FileWriteCallback file_write,
@@ -1160,6 +1161,7 @@
                                        instructions_snapshot,
                                        data_snapshot,
                                        create, shutdown,
+                                       thread_exit,
                                        file_open, file_read, file_write,
                                        file_close, entropy_source,
                                        get_service_assets);
@@ -3491,8 +3493,8 @@
   }
   Object& result = Object::Handle(Z);
   result = GetByteBufferConstructor(T,
-                                    Symbols::_ByteBuffer(),
-                                    Symbols::_ByteBufferDot_New(),
+                                    Symbols::ByteBuffer(),
+                                    Symbols::ByteBufferDot_New(),
                                     1);
   ASSERT(!result.IsNull());
   ASSERT(result.IsFunction());
@@ -5775,31 +5777,7 @@
 }
 
 
-DART_EXPORT void Dart_TimelineSetRecordedStreams(int64_t stream_mask) {
-  if (!FLAG_support_timeline) {
-    return;
-  }
-  Isolate* isolate = Isolate::Current();
-  CHECK_ISOLATE(isolate);
-  isolate->GetAPIStream()->set_enabled(
-      (stream_mask & DART_TIMELINE_STREAM_API) != 0);
-  isolate->GetCompilerStream()->set_enabled(
-      (stream_mask & DART_TIMELINE_STREAM_COMPILER) != 0);
-  isolate->GetDartStream()->set_enabled(
-      (stream_mask & DART_TIMELINE_STREAM_DART) != 0);
-  isolate->GetDebuggerStream()->set_enabled(
-      (stream_mask & DART_TIMELINE_STREAM_DEBUGGER) != 0);
-  isolate->GetEmbedderStream()->set_enabled(
-      (stream_mask & DART_TIMELINE_STREAM_EMBEDDER) != 0);
-  isolate->GetGCStream()->set_enabled(
-      (stream_mask & DART_TIMELINE_STREAM_GC) != 0);
-  isolate->GetIsolateStream()->set_enabled(
-      (stream_mask & DART_TIMELINE_STREAM_ISOLATE) != 0);
-}
-
-
 DART_EXPORT void Dart_GlobalTimelineSetRecordedStreams(int64_t stream_mask) {
-  // Per isolate overrides.
   if (!FLAG_support_timeline) {
     return;
   }
@@ -5815,6 +5793,8 @@
   const bool gc_enabled = (stream_mask & DART_TIMELINE_STREAM_GC) != 0;
   const bool isolate_enabled =
       (stream_mask & DART_TIMELINE_STREAM_ISOLATE) != 0;
+  const bool vm_enabled =
+      (stream_mask & DART_TIMELINE_STREAM_VM) != 0;
   Timeline::SetStreamAPIEnabled(api_enabled);
   Timeline::SetStreamCompilerEnabled(compiler_enabled);
   Timeline::SetStreamDartEnabled(dart_enabled);
@@ -5822,10 +5802,7 @@
   Timeline::SetStreamEmbedderEnabled(embedder_enabled);
   Timeline::SetStreamGCEnabled(gc_enabled);
   Timeline::SetStreamIsolateEnabled(isolate_enabled);
-  // VM wide.
-  const bool vm_enabled =
-      (stream_mask & DART_TIMELINE_STREAM_VM) != 0;
-  Timeline::GetVMStream()->set_enabled(vm_enabled);
+  Timeline::SetStreamVMEnabled(vm_enabled);
 }
 
 
@@ -5924,44 +5901,14 @@
 }
 
 
-DART_EXPORT bool Dart_TimelineGetTrace(Dart_StreamConsumer consumer,
-                                       void* user_data) {
-  if (!FLAG_support_timeline) {
-    return false;
-  }
-  Isolate* isolate = Isolate::Current();
-  CHECK_ISOLATE(isolate);
-  if (consumer == NULL) {
-    return false;
-  }
-  TimelineEventRecorder* timeline_recorder = Timeline::recorder();
-  if (timeline_recorder == NULL) {
-    // Nothing has been recorded.
-    return false;
-  }
-  Thread* T = Thread::Current();
-  StackZone zone(T);
-  Timeline::ReclaimCachedBlocksFromThreads();
-  JSONStream js;
-  IsolateTimelineEventFilter filter(isolate->main_port());
-  timeline_recorder->PrintTraceEvent(&js, &filter);
-  StartStreamToConsumer(consumer, user_data, "timeline");
-  bool success = StreamTraceEvents(consumer, user_data, &js);
-  FinishStreamToConsumer(consumer, user_data, "timeline");
-  return success;
-}
-
-
 DART_EXPORT void Dart_SetEmbedderTimelineCallbacks(
     Dart_EmbedderTimelineStartRecording start_recording,
-    Dart_EmbedderTimelineStopRecording stop_recording,
-    Dart_EmbedderTimelineGetTimeline get_timeline) {
+    Dart_EmbedderTimelineStopRecording stop_recording) {
   if (!FLAG_support_timeline) {
     return;
   }
   Timeline::set_start_recording_cb(start_recording);
   Timeline::set_stop_recording_cb(stop_recording);
-  Timeline::set_get_timeline_cb(get_timeline);
 }
 
 
@@ -5996,67 +5943,105 @@
 }
 
 
-DART_EXPORT Dart_Handle Dart_TimelineDuration(const char* label,
-                                              int64_t start_micros,
-                                              int64_t end_micros) {
+DART_EXPORT void Dart_TimelineEvent(const char* label,
+                                    int64_t timestamp0,
+                                    int64_t timestamp1,
+                                    Dart_Timeline_Event_Type type,
+                                    intptr_t argument_count,
+                                    const char** argument_names,
+                                    const char** argument_values) {
   if (!FLAG_support_timeline) {
-    return Api::Success();
+    return;
   }
-  Isolate* isolate = Isolate::Current();
-  CHECK_ISOLATE(isolate);
-  if (label == NULL) {
-    RETURN_NULL_ERROR(label);
+  if (type < Dart_Timeline_Event_Begin) {
+    return;
+  }
+  if (type > Dart_Timeline_Event_Duration) {
+    return;
+  }
+  TimelineStream* stream = Timeline::GetEmbedderStream();
+  ASSERT(stream != NULL);
+  TimelineEvent* event = stream->StartEvent();
+  if (event == NULL) {
+    return;
+  }
+  switch (type) {
+    case Dart_Timeline_Event_Begin:
+      event->Begin(label, timestamp0);
+    break;
+    case Dart_Timeline_Event_End:
+      event->End(label, timestamp0);
+    break;
+    case Dart_Timeline_Event_Instant:
+      event->Instant(label, timestamp0);
+    break;
+    case Dart_Timeline_Event_Duration:
+      event->Duration(label, timestamp0, timestamp1);
+    break;
+    default:
+      FATAL("Unknown Dart_Timeline_Event_Type");
+  }
+  event->SetNumArguments(argument_count);
+  for (intptr_t i = 0; i < argument_count; i++) {
+    event->CopyArgument(i, argument_names[i], argument_values[i]);
+  }
+  event->Complete();
+}
+
+
+DART_EXPORT void Dart_TimelineDuration(const char* label,
+                                       int64_t start_micros,
+                                       int64_t end_micros) {
+  if (!FLAG_support_timeline) {
+    return;
   }
   if (start_micros > end_micros) {
-    const char* msg = "%s: start_micros must be <= end_micros";
-    return Api::NewError(msg, CURRENT_FUNC);
+    FATAL1("%s: start_micros must be <= end_micros", CURRENT_FUNC);
   }
-  TimelineStream* stream = isolate->GetEmbedderStream();
+  if (label == NULL) {
+    return;
+  }
+  TimelineStream* stream = Timeline::GetEmbedderStream();
   ASSERT(stream != NULL);
   TimelineEvent* event = stream->StartEvent();
   if (event != NULL) {
     event->Duration(label, start_micros, end_micros);
     event->Complete();
   }
-  return Api::Success();
 }
 
 
-DART_EXPORT Dart_Handle Dart_TimelineInstant(const char* label) {
+DART_EXPORT void Dart_TimelineInstant(const char* label) {
   if (!FLAG_support_timeline) {
-    return Api::Success();
+    return;
   }
-  Isolate* isolate = Isolate::Current();
-  CHECK_ISOLATE(isolate);
   if (label == NULL) {
-    RETURN_NULL_ERROR(label);
+    return;
   }
-  TimelineStream* stream = isolate->GetEmbedderStream();
+  TimelineStream* stream = Timeline::GetEmbedderStream();
   ASSERT(stream != NULL);
   TimelineEvent* event = stream->StartEvent();
   if (event != NULL) {
     event->Instant(label);
     event->Complete();
   }
-  return Api::Success();
+  return;
 }
 
 
-DART_EXPORT Dart_Handle Dart_TimelineAsyncBegin(const char* label,
-                                                int64_t* async_id) {
+DART_EXPORT void Dart_TimelineAsyncBegin(const char* label,
+                                         int64_t* async_id) {
   if (!FLAG_support_timeline) {
-    return Api::Success();
+    return;
   }
-  Isolate* isolate = Isolate::Current();
-  CHECK_ISOLATE(isolate);
   if (label == NULL) {
-    RETURN_NULL_ERROR(label);
+    return;
   }
   if (async_id == NULL) {
-    RETURN_NULL_ERROR(async_id);
+    return;
   }
   *async_id = -1;
-  TimelineStream* stream = isolate->GetEmbedderStream();
+  TimelineStream* stream = Timeline::GetEmbedderStream();
   ASSERT(stream != NULL);
   TimelineEvent* event = stream->StartEvent();
   if (event != NULL) {
@@ -6066,55 +6051,51 @@
     event->AsyncBegin(label, *async_id);
     event->Complete();
   }
-  return Api::Success();
+  return;
 }
 
 
-DART_EXPORT Dart_Handle Dart_TimelineAsyncInstant(const char* label,
-                                                  int64_t async_id) {
+DART_EXPORT void Dart_TimelineAsyncInstant(const char* label,
+                                           int64_t async_id) {
   if (!FLAG_support_timeline) {
-    return Api::Success();
+    return;
   }
   if (async_id < 0) {
-    return Api::Success();
+    return;
   }
-  Isolate* isolate = Isolate::Current();
-  CHECK_ISOLATE(isolate);
   if (label == NULL) {
-    RETURN_NULL_ERROR(label);
+    return;
   }
-  TimelineStream* stream = isolate->GetEmbedderStream();
+  TimelineStream* stream = Timeline::GetEmbedderStream();
   ASSERT(stream != NULL);
   TimelineEvent* event = stream->StartEvent();
   if (event != NULL) {
     event->AsyncInstant(label, async_id);
     event->Complete();
   }
-  return Api::Success();
+  return;
 }
 
 
-DART_EXPORT Dart_Handle Dart_TimelineAsyncEnd(const char* label,
-                                              int64_t async_id) {
+DART_EXPORT void Dart_TimelineAsyncEnd(const char* label,
+                                       int64_t async_id) {
   if (!FLAG_support_timeline) {
-    return Api::Success();
+    return;
   }
   if (async_id < 0) {
-    return Api::Success();
+    return;
   }
-  Isolate* isolate = Isolate::Current();
-  CHECK_ISOLATE(isolate);
   if (label == NULL) {
-    RETURN_NULL_ERROR(label);
+    return;
   }
-  TimelineStream* stream = isolate->GetEmbedderStream();
+  TimelineStream* stream = Timeline::GetEmbedderStream();
   ASSERT(stream != NULL);
   TimelineEvent* event = stream->StartEvent();
   if (event != NULL) {
     event->AsyncEnd(label, async_id);
     event->Complete();
   }
-  return Api::Success();
+  return;
 }
 
 // The precompiler is included in dart_bootstrap and dart_noopt, and
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 4be3fa9..d8d4fb0 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -14,6 +14,7 @@
 #include "vm/dart_api_impl.h"
 #include "vm/dart_api_state.h"
 #include "vm/lockers.h"
+#include "vm/timeline.h"
 #include "vm/unit_test.h"
 #include "vm/verifier.h"
 
@@ -9190,7 +9191,7 @@
 TEST_CASE(Timeline_Dart_TimelineDuration) {
   Isolate* isolate = Isolate::Current();
   // Grab embedder stream.
-  TimelineStream* stream = isolate->GetEmbedderStream();
+  TimelineStream* stream = Timeline::GetEmbedderStream();
   // Make sure it is enabled.
   stream->set_enabled(true);
   // Add a duration event.
@@ -9208,7 +9209,7 @@
 TEST_CASE(Timeline_Dart_TimelineInstant) {
   Isolate* isolate = Isolate::Current();
   // Grab embedder stream.
-  TimelineStream* stream = isolate->GetEmbedderStream();
+  TimelineStream* stream = Timeline::GetEmbedderStream();
   // Make sure it is enabled.
   stream->set_enabled(true);
   Dart_TimelineInstant("testInstantEvent");
@@ -9223,9 +9224,8 @@
 
 
 TEST_CASE(Timeline_Dart_TimelineAsyncDisabled) {
-  Isolate* isolate = Isolate::Current();
   // Grab embedder stream.
-  TimelineStream* stream = isolate->GetEmbedderStream();
+  TimelineStream* stream = Timeline::GetEmbedderStream();
   // Make sure it is disabled.
   stream->set_enabled(false);
   int64_t async_id = -1;
@@ -9247,7 +9247,7 @@
 TEST_CASE(Timeline_Dart_TimelineAsync) {
   Isolate* isolate = Isolate::Current();
   // Grab embedder stream.
-  TimelineStream* stream = isolate->GetEmbedderStream();
+  TimelineStream* stream = Timeline::GetEmbedderStream();
   // Make sure it is enabled.
   stream->set_enabled(true);
   int64_t async_id = -1;
@@ -9315,7 +9315,7 @@
   bool success = false;
 
   // Enable recording of all streams.
-  Dart_TimelineSetRecordedStreams(DART_TIMELINE_STREAM_ALL);
+  Dart_GlobalTimelineSetRecordedStreams(DART_TIMELINE_STREAM_ALL);
 
   // Invoke main, which will be compiled resulting in a compiler event in
   // the timeline.
@@ -9327,7 +9327,7 @@
 
   // Grab the trace.
   AppendData data;
-  success = Dart_TimelineGetTrace(AppendStreamConsumer, &data);
+  success = Dart_GlobalTimelineGetTrace(AppendStreamConsumer, &data);
   EXPECT(success);
   buffer = reinterpret_cast<char*>(data.buffer);
   buffer_length = data.buffer_length;
@@ -9367,7 +9367,7 @@
   bool success = false;
 
   // Enable recording of the Dart stream.
-  Dart_TimelineSetRecordedStreams(DART_TIMELINE_STREAM_DART);
+  Dart_GlobalTimelineSetRecordedStreams(DART_TIMELINE_STREAM_DART);
 
   // Invoke main, which will add a new timeline event from Dart.
   Dart_Handle result = Dart_Invoke(lib,
@@ -9380,7 +9380,7 @@
   AppendData data;
   data.buffer = NULL;
   data.buffer_length = 0;
-  success = Dart_TimelineGetTrace(AppendStreamConsumer, &data);
+  success = Dart_GlobalTimelineGetTrace(AppendStreamConsumer, &data);
   EXPECT(success);
   buffer = reinterpret_cast<char*>(data.buffer);
   buffer_length = data.buffer_length;
@@ -9419,7 +9419,7 @@
   bool success = false;
 
   // Enable recording of all streams.
-  Dart_TimelineSetRecordedStreams(DART_TIMELINE_STREAM_ALL);
+  Dart_GlobalTimelineSetRecordedStreams(DART_TIMELINE_STREAM_ALL);
 
   // Invoke main, which will be compiled resulting in a compiler event in
   // the timeline.
@@ -9431,7 +9431,7 @@
 
   // Grab the trace.
   AppendData data;
-  success = Dart_TimelineGetTrace(AppendStreamConsumer, &data);
+  success = Dart_GlobalTimelineGetTrace(AppendStreamConsumer, &data);
   EXPECT(success);
   buffer = reinterpret_cast<char*>(data.buffer);
   buffer_length = data.buffer_length;
@@ -9480,7 +9480,7 @@
 
   // Grab the trace.
   AppendData data;
-  success = Dart_TimelineGetTrace(AppendStreamConsumer, &data);
+  success = Dart_GlobalTimelineGetTrace(AppendStreamConsumer, &data);
   EXPECT(success);
   buffer = reinterpret_cast<char*>(data.buffer);
   buffer_length = data.buffer_length;
@@ -9503,6 +9503,16 @@
 }
 
 
+static const char* arg_names[] = {
+  "arg0"
+};
+
+
+static const char* arg_values[] = {
+  "value0"
+};
+
+
 TEST_CASE(Timeline_Dart_GlobalTimelineGetTrace) {
   const char* kScriptChars =
     "bar() => 'z';\n"
@@ -9520,6 +9530,17 @@
     lib = TestCase::LoadTestScript(kScriptChars, NULL);
   }
 
+  {
+    // Add something to the embedder stream.
+    Dart_TimelineEvent("TRACE_EVENT",
+                       Dart_TimelineGetMicros(),
+                       0,
+                       Dart_Timeline_Event_Begin,
+                       1,
+                       &arg_names[0],
+                       &arg_values[0]);
+  }
+
   // Invoke main, which will be compiled resulting in a compiler event in
   // the timeline.
   Dart_Handle result = Dart_Invoke(lib,
@@ -9559,6 +9580,9 @@
   EXPECT_SUBSTRING("\"name\":\"CompileFunction\"", buffer);
   EXPECT_SUBSTRING("\"function\":\"::_main\"", buffer);
   EXPECT_NOTSUBSTRING("\"function\":\"::_bar\"", buffer);
+  EXPECT_SUBSTRING("TRACE_EVENT", buffer);
+  EXPECT_SUBSTRING("arg0", buffer);
+  EXPECT_SUBSTRING("value0", buffer);
 
   // Free buffer allocated by AppendStreamConsumer
   free(data.buffer);
@@ -9786,7 +9810,7 @@
 
 
 TEST_CASE(Timeline_Dart_EmbedderTimelineStartStopRecording) {
-  Dart_SetEmbedderTimelineCallbacks(StartRecording, StopRecording, NULL);
+  Dart_SetEmbedderTimelineCallbacks(StartRecording, StopRecording);
 
   EXPECT(!start_called);
   EXPECT(!stop_called);
@@ -9803,37 +9827,6 @@
   EXPECT(stop_called);
 }
 
-static bool GetTimeline(Dart_StreamConsumer stream_consumer,
-                        void* user_data) {
-  ASSERT(stream_consumer != NULL);
-  ASSERT(user_data != NULL);
-
-  const char* test_string = "HELLO FROM EMBEDDER";
-  stream_consumer(Dart_StreamConsumer_kData,
-                  "embedder.timeline",
-                  reinterpret_cast<const uint8_t*>(test_string),
-                  strlen(test_string),
-                  user_data);
-  return true;
-}
-
-TEST_CASE(Timeline_Dart_EmbedderTimelineGetTimeline) {
-  Dart_SetEmbedderTimelineCallbacks(NULL, NULL, GetTimeline);
-
-  Dart_GlobalTimelineSetRecordedStreams(DART_TIMELINE_STREAM_EMBEDDER);
-  Dart_TimelineDuration("testDurationEvent", 0, 1);
-
-  AppendData data;
-  bool success = Dart_GlobalTimelineGetTrace(AppendStreamConsumer, &data);
-  EXPECT(success);
-
-  EXPECT_SUBSTRING("}},HELLO FROM EMBEDDER",
-                   data.buffer);
-
-  // Free buffer allocated by AppendStreamConsumer
-  free(data.buffer);
-}
-
 #endif  // !PRODUCT
 
 }  // namespace dart
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 3845949..e8bc0ce 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -41,25 +41,23 @@
     // grows from high to low addresses).
     OSThread* os_thread = thread->os_thread();
     ASSERT(os_thread != NULL);
-    uword current_sp = Isolate::GetCurrentStackPointer();
+    uword current_sp = Thread::GetCurrentStackPointer();
     if (current_sp > os_thread->stack_base()) {
       os_thread->set_stack_base(current_sp);
     }
-    // Save the Isolate's current stack limit and adjust the stack
+    // Save the Thread's current stack limit and adjust the stack
     // limit based on the thread's stack_base.
-    Isolate* isolate = thread->isolate();
-    ASSERT(isolate == Isolate::Current());
-    saved_stack_limit_ = isolate->saved_stack_limit();
-    isolate->SetStackLimitFromStackBase(os_thread->stack_base());
+    ASSERT(thread->isolate() == Isolate::Current());
+    saved_stack_limit_ = thread->saved_stack_limit();
+    thread->SetStackLimitFromStackBase(os_thread->stack_base());
   }
 
   ~ScopedIsolateStackLimits() {
-    Isolate* isolate = thread_->isolate();
-    ASSERT(isolate == Isolate::Current());
+    ASSERT(thread_->isolate() == Isolate::Current());
     // Since we started with a stack limit of 0 we should be getting back
     // to a stack limit of 0 when all nested invocations are done and
     // we have bottomed out.
-    isolate->SetStackLimit(saved_stack_limit_);
+    thread_->SetStackLimit(saved_stack_limit_);
   }
 
  private:
@@ -167,12 +165,13 @@
     while (!cls.IsNull()) {
       function ^= cls.LookupDynamicFunction(getter_name);
       if (!function.IsNull()) {
-        Isolate* isolate = Isolate::Current();
-        volatile uword c_stack_pos = Isolate::GetCurrentStackPointer();
+        Thread* thread = Thread::Current();
+        Isolate* isolate = thread->isolate();
+        volatile uword c_stack_pos = Thread::GetCurrentStackPointer();
         volatile uword c_stack_limit = OSThread::Current()->stack_base() -
                                        OSThread::GetSpecifiedStackSize();
 #if !defined(USING_SIMULATOR)
-        ASSERT(c_stack_limit == isolate->saved_stack_limit());
+        ASSERT(c_stack_limit == thread->saved_stack_limit());
 #endif
 
         if (c_stack_pos < c_stack_limit) {
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 2739006..e9951c8 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -27,6 +27,7 @@
 #include "vm/stub_code.h"
 #include "vm/symbols.h"
 #include "vm/thread_interrupter.h"
+#include "vm/timeline.h"
 #include "vm/token_position.h"
 #include "vm/visitor.h"
 
@@ -2558,7 +2559,7 @@
     Thread* thread = Thread::Current();
     DisableThreadInterruptsScope dtis(thread);
     TimelineDurationScope tds(thread,
-                              isolate_->GetDebuggerStream(),
+                              Timeline::GetDebuggerStream(),
                               "Debugger Pause");
     InvokeEventHandler(event);
   }
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 1aa11b7..8b0aa72 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -139,8 +139,7 @@
   deferred_objects_ = NULL;
   deferred_objects_count_ = 0;
   if (FLAG_support_timeline && (deopt_start_micros_ != 0)) {
-    Isolate* isolate = Isolate::Current();
-    TimelineStream* compiler_stream = isolate->GetCompilerStream();
+    TimelineStream* compiler_stream = Timeline::GetCompilerStream();
     ASSERT(compiler_stream != NULL);
     if (compiler_stream->Enabled()) {
       // Allocate all Dart objects needed before calling StartEvent,
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index e55edd0..e2fa84e 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -238,7 +238,7 @@
       StubCode::JumpToExceptionHandler_entry()->EntryPoint());
 
   // Unpoison the stack before we tear it down in the generated stub code.
-  uword current_sp = Isolate::GetCurrentStackPointer() - 1024;
+  uword current_sp = Thread::GetCurrentStackPointer() - 1024;
   ASAN_UNPOISON(reinterpret_cast<void*>(current_sp),
                 stack_pointer - current_sp);
 
@@ -493,12 +493,24 @@
         pieces.Add(Symbols::SingleQuote());
       }
       // Print URIs of src and dst types.
-      pieces.Add(Symbols::SpaceWhereNewLine());
+      // Do not print "where" when no URIs get printed.
+      bool printed_where = false;
       if (!src_type.IsNull()) {
-        pieces.Add(String::Handle(zone, src_type.EnumerateURIs()));
+        const String& uris = String::Handle(zone, src_type.EnumerateURIs());
+        if (uris.Length() > Symbols::SpaceIsFromSpace().Length()) {
+          printed_where = true;
+          pieces.Add(Symbols::SpaceWhereNewLine());
+          pieces.Add(uris);
+        }
       }
       if (!dst_type.IsDynamicType() && !dst_type.IsVoidType()) {
-        pieces.Add(String::Handle(zone, dst_type.EnumerateURIs()));
+        const String& uris = String::Handle(zone, dst_type.EnumerateURIs());
+        if (uris.Length() > Symbols::SpaceIsFromSpace().Length()) {
+          if (!printed_where) {
+            pieces.Add(Symbols::SpaceWhereNewLine());
+          }
+          pieces.Add(uris);
+        }
       }
     }
   }
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index c411bbd..6f7ff8d 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -2505,9 +2505,8 @@
   { LocalVariable* closure_tmp_var = EnterTempLocalScope(closure_val,
                                                          node->token_pos());
     // Store type arguments if scope class is generic.
-    const FunctionType& function_type =
-        FunctionType::ZoneHandle(Z, function.SignatureType());
-    const Class& scope_cls = Class::ZoneHandle(Z, function_type.scope_class());
+    const Type& function_type = Type::ZoneHandle(Z, function.SignatureType());
+    const Class& scope_cls = Class::ZoneHandle(Z, function_type.type_class());
     if (scope_cls.IsGeneric()) {
       ASSERT(function.Owner() == scope_cls.raw());
       Value* closure_tmp_val = Bind(new(Z) LoadLocalInstr(*closure_tmp_var,
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 1ca6adc..d904c86 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -255,7 +255,7 @@
 void FlowGraphCompiler::InitCompiler() {
 #ifndef PRODUCT
   TimelineDurationScope tds(thread(),
-                            isolate()->GetCompilerStream(),
+                            Timeline::GetCompilerStream(),
                             "InitCompiler");
 #endif  // !PRODUCT
   pc_descriptors_list_ = new(zone()) DescriptorList(64);
@@ -1109,7 +1109,7 @@
           *return_node.value()->AsLoadInstanceFieldNode();
       // Only intrinsify getter if the field cannot contain a mutable double.
       // Reading from a mutable double box requires allocating a fresh double.
-      if (load_node.field().guarded_cid() == kDynamicCid) {
+      if (!IsPotentialUnboxedField(load_node.field())) {
         GenerateInlinedGetter(load_node.field().Offset());
         return !FLAG_use_field_guards;
       }
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 247537a..9f0da1e 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -516,7 +516,7 @@
     __ Bind(&fall_through);
     return type_test_cache.raw();
   }
-  if (type.IsType() || type.IsFunctionType()) {
+  if (type.IsType()) {
     const Register kInstanceReg = R0;
     const Register kTypeArgumentsReg = R1;
     __ tst(kInstanceReg, Operand(kSmiTagMask));  // Is instance Smi?
@@ -1367,7 +1367,7 @@
   __ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize);
   if (ic_data.NumArgsTested() == 1) {
     __ LoadUniqueObject(R9, ic_data);
-    __ BranchLinkPatchable(*StubCode::ICLookup_entry());
+    __ BranchLinkPatchable(*StubCode::ICLookupThroughFunction_entry());
   } else {
     const String& name = String::Handle(zone(), ic_data.target_name());
     const Array& arguments_descriptor =
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index 4f6474c..6750d70 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -508,7 +508,7 @@
     __ Bind(&fall_through);
     return type_test_cache.raw();
   }
-  if (type.IsType() || type.IsFunctionType()) {
+  if (type.IsType()) {
     const Register kInstanceReg = R0;
     const Register kTypeArgumentsReg = R1;
     __ tsti(kInstanceReg, Immediate(kSmiTagMask));  // Is instance Smi?
@@ -1347,7 +1347,7 @@
   __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize);
   if (ic_data.NumArgsTested() == 1) {
     __ LoadUniqueObject(R5, ic_data);
-    __ BranchLinkPatchable(*StubCode::ICLookup_entry());
+    __ BranchLinkPatchable(*StubCode::ICLookupThroughFunction_entry());
   } else {
     const String& name = String::Handle(zone(), ic_data.target_name());
     const Array& arguments_descriptor =
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 7407ac9..fe9696f 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -520,7 +520,7 @@
     __ Bind(&fall_through);
     return type_test_cache.raw();
   }
-  if (type.IsType() || type.IsFunctionType()) {
+  if (type.IsType()) {
     const Register kInstanceReg = EAX;
     const Register kTypeArgumentsReg = EDX;
     __ testl(kInstanceReg, Immediate(kSmiTagMask));  // Is instance Smi?
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 18b629b..c02d511 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -504,7 +504,7 @@
     __ Bind(&fall_through);
     return type_test_cache.raw();
   }
-  if (type.IsType() || type.IsFunctionType()) {
+  if (type.IsType()) {
     const Register kInstanceReg = A0;
     const Register kTypeArgumentsReg = A1;
     __ andi(CMPRES1, kInstanceReg, Immediate(kSmiTagMask));
@@ -1374,7 +1374,7 @@
   __ lw(T0, Address(SP, (argument_count - 1) * kWordSize));
   if (ic_data.NumArgsTested() == 1) {
     __ LoadUniqueObject(S5, ic_data);
-    __ BranchLinkPatchable(*StubCode::ICLookup_entry());
+    __ BranchLinkPatchable(*StubCode::ICLookupThroughFunction_entry());
   } else {
     const String& name = String::Handle(zone(), ic_data.target_name());
     const Array& arguments_descriptor =
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 301de20..7c5d7de 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -515,7 +515,7 @@
     __ Bind(&fall_through);
     return type_test_cache.raw();
   }
-  if (type.IsType() || type.IsFunctionType()) {
+  if (type.IsType()) {
     const Register kInstanceReg = RAX;
     const Register kTypeArgumentsReg = RDX;
     __ testq(kInstanceReg, Immediate(kSmiTagMask));  // Is instance Smi?
@@ -1377,7 +1377,7 @@
   __ movq(RDI, Address(RSP, (argument_count - 1) * kWordSize));
   if (ic_data.NumArgsTested() == 1) {
     __ LoadUniqueObject(RBX, ic_data);
-    __ CallPatchable(*StubCode::ICLookup_entry());
+    __ CallPatchable(*StubCode::ICLookupThroughFunction_entry());
   } else {
     const String& name = String::Handle(zone(), ic_data.target_name());
     const Array& arguments_descriptor =
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index df32f54..bd860d9 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -8,6 +8,7 @@
 #include "vm/bit_vector.h"
 #include "vm/il_printer.h"
 #include "vm/regexp_assembler.h"
+#include "vm/timeline.h"
 
 namespace dart {
 
@@ -20,8 +21,7 @@
 void FlowGraphTypePropagator::Propagate(FlowGraph* flow_graph) {
 #ifndef PRODUCT
   Thread* thread = flow_graph->thread();
-  Isolate* const isolate = flow_graph->isolate();
-  TimelineStream* compiler_timeline = isolate->GetCompilerStream();
+  TimelineStream* compiler_timeline = Timeline::GetCompilerStream();
   TimelineDurationScope tds2(thread,
                              compiler_timeline,
                              "FlowGraphTypePropagator");
@@ -713,7 +713,7 @@
     // from being generated.
     switch (index()) {
       case RegExpMacroAssembler::kParamRegExpIndex:
-        return CompileType::FromCid(kJSRegExpCid);
+        return CompileType::FromCid(kRegExpCid);
       case RegExpMacroAssembler::kParamStringIndex:
         return CompileType::FromCid(function.string_specialization_cid());
       case RegExpMacroAssembler::kParamStartOffsetIndex:
@@ -981,8 +981,7 @@
     ASSERT(cls().id() == kClosureCid);
     return CompileType(CompileType::kNonNullable,
                        kClosureCid,
-                       &FunctionType::ZoneHandle(
-                           closure_function().SignatureType()));
+                       &Type::ZoneHandle(closure_function().SignatureType()));
   }
   // TODO(vegorov): Incorporate type arguments into the returned type.
   return CompileType::FromCid(cls().id());
@@ -1009,8 +1008,9 @@
 
   const AbstractType* abstract_type = NULL;
   if (Isolate::Current()->type_checks() &&
-      type().HasResolvedTypeClass() &&
-      !Field::IsExternalizableCid(Class::Handle(type().type_class()).id())) {
+      (type().IsFunctionType() ||
+       (type().HasResolvedTypeClass() &&
+       !Field::IsExternalizableCid(Class::Handle(type().type_class()).id())))) {
     abstract_type = &type();
   }
 
diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc
index c9ac9fa..cc5db20 100644
--- a/runtime/vm/gc_marker.cc
+++ b/runtime/vm/gc_marker.cc
@@ -19,6 +19,7 @@
 #include "vm/thread_barrier.h"
 #include "vm/thread_pool.h"
 #include "vm/thread_registry.h"
+#include "vm/timeline.h"
 #include "vm/visitor.h"
 #include "vm/object_id_ring.h"
 
@@ -599,10 +600,13 @@
   }
 
   virtual void Run() {
-    bool result = Thread::EnterIsolateAsHelper(isolate_, true);
+    bool result =
+        Thread::EnterIsolateAsHelper(isolate_, Thread::kMarkerTask, true);
     ASSERT(result);
     {
-      StackZone stack_zone(Thread::Current());
+      Thread* thread = Thread::Current();
+      TIMELINE_FUNCTION_GC_DURATION(thread, "MarkTask");
+      StackZone stack_zone(thread);
       Zone* zone = stack_zone.GetZone();
       SkippedCodeFunctions* skipped_code_functions =
           collect_code_ ? new(zone) SkippedCodeFunctions() : NULL;
diff --git a/runtime/vm/gc_sweeper.cc b/runtime/vm/gc_sweeper.cc
index 0dcf62f..5b7949b 100644
--- a/runtime/vm/gc_sweeper.cc
+++ b/runtime/vm/gc_sweeper.cc
@@ -11,6 +11,7 @@
 #include "vm/pages.h"
 #include "vm/safepoint.h"
 #include "vm/thread_pool.h"
+#include "vm/timeline.h"
 
 namespace dart {
 
@@ -114,32 +115,36 @@
   }
 
   virtual void Run() {
-    bool result = Thread::EnterIsolateAsHelper(task_isolate_);
+    bool result = Thread::EnterIsolateAsHelper(task_isolate_,
+                                               Thread::kSweeperTask);
     ASSERT(result);
-    Thread* thread = Thread::Current();
-    GCSweeper sweeper;
+    {
+      Thread* thread = Thread::Current();
+      TIMELINE_FUNCTION_GC_DURATION(thread, "SweeperTask");
+      GCSweeper sweeper;
 
-    HeapPage* page = first_;
-    HeapPage* prev_page = NULL;
+      HeapPage* page = first_;
+      HeapPage* prev_page = NULL;
 
-    while (page != NULL) {
-      thread->CheckForSafepoint();
-      HeapPage* next_page = page->next();
-      ASSERT(page->type() == HeapPage::kData);
-      bool page_in_use = sweeper.SweepPage(page, freelist_, false);
-      if (page_in_use) {
-        prev_page = page;
-      } else {
-        old_space_->FreePage(page, prev_page);
+      while (page != NULL) {
+        thread->CheckForSafepoint();
+        HeapPage* next_page = page->next();
+        ASSERT(page->type() == HeapPage::kData);
+        bool page_in_use = sweeper.SweepPage(page, freelist_, false);
+        if (page_in_use) {
+          prev_page = page;
+        } else {
+          old_space_->FreePage(page, prev_page);
+        }
+        {
+          // Notify the mutator thread that we have added elements to the free
+          // list or that more capacity is available.
+          MonitorLocker ml(old_space_->tasks_lock());
+          ml.Notify();
+        }
+        if (page == last_) break;
+        page = next_page;
       }
-      {
-        // Notify the mutator thread that we have added elements to the free
-        // list or that more capacity is available.
-        MonitorLocker ml(old_space_->tasks_lock());
-        ml.Notify();
-      }
-      if (page == last_) break;
-      page = next_page;
     }
     // Exit isolate cleanly *before* notifying it, to avoid shutdown race.
     Thread::ExitIsolateAsHelper();
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index b34af54..138e9b1 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -224,7 +224,7 @@
   ASSERT(old_space_->iterating_thread_ != thread());
 #endif
   while (old_space_->tasks() > 0) {
-    ml.Wait();
+    ml.WaitWithSafepointCheck(thread());
   }
 #if defined(DEBUG)
   ASSERT(old_space_->iterating_thread_ == NULL);
@@ -367,11 +367,7 @@
     bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks);
     RecordBeforeGC(kNew, reason);
     VMTagScope tagScope(thread, VMTag::kGCNewSpaceTagId);
-#ifndef PRODUCT
-    TimelineDurationScope tds(thread,
-                              isolate()->GetGCStream(),
-                              "CollectNewGeneration");
-#endif  // !PRODUCT
+    TIMELINE_FUNCTION_GC_DURATION(thread, "CollectNewGeneration");
     UpdateClassHeapStatsBeforeGC(kNew);
     new_space_.Scavenge(invoke_api_callbacks);
     isolate()->class_table()->UpdatePromoted();
@@ -394,11 +390,7 @@
     bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks);
     RecordBeforeGC(kOld, reason);
     VMTagScope tagScope(thread, VMTag::kGCOldSpaceTagId);
-#ifndef PRODUCT
-    TimelineDurationScope tds(thread,
-                              isolate()->GetGCStream(),
-                              "CollectOldGeneration");
-#endif  // !PRODUCT
+    TIMELINE_FUNCTION_GC_DURATION(thread, "CollectOldGeneration");
     UpdateClassHeapStatsBeforeGC(kOld);
     old_space_.MarkSweep(invoke_api_callbacks);
     RecordAfterGC(kOld);
diff --git a/runtime/vm/instructions_x64.cc b/runtime/vm/instructions_x64.cc
index 2dc98bc..3fa610a 100644
--- a/runtime/vm/instructions_x64.cc
+++ b/runtime/vm/instructions_x64.cc
@@ -48,7 +48,11 @@
     int32_t offset = *reinterpret_cast<int32_t*>(pc + 3);
     return Thread::ObjectAtOffset(offset, obj);
   }
-  if (((bytes[0] == 0x4d) && (bytes[1] == 0x8b) && (bytes[2] == 0x5e)) ||
+  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))) {
     uint8_t offset = *reinterpret_cast<uint8_t*>(pc + 3);
     return Thread::ObjectAtOffset(offset, obj);
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 4f4032f..4b55595 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -3714,9 +3714,9 @@
 
 
 void NativeCallInstr::SetupNative() {
-  Zone* Z = Thread::Current()->zone();
-  const Class& cls = Class::Handle(Z, function().Owner());
-  const Library& library = Library::Handle(Z, cls.library());
+  Zone* zone = Thread::Current()->zone();
+  const Class& cls = Class::Handle(zone, function().Owner());
+  const Library& library = Library::Handle(zone, cls.library());
   const int num_params =
       NativeArguments::ParameterCountForResolution(function());
   bool auto_setup_scope = true;
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 269b1893..6b180bd 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -2874,19 +2874,11 @@
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
     if (FLAG_use_osr && osr_entry_label()->IsLinked()) {
-      uword flags_address = Isolate::Current()->stack_overflow_flags_address();
       const Register value = instruction_->locs()->temp(0).reg();
       __ Comment("CheckStackOverflowSlowPathOsr");
       __ Bind(osr_entry_label());
-      if (FLAG_allow_absolute_addresses) {
-        __ LoadImmediate(IP, flags_address);
-        __ LoadImmediate(value, Isolate::kOsrRequest);
-        __ str(value, Address(IP));
-      } else {
-        __ LoadIsolate(IP);
-        __ LoadImmediate(value, Isolate::kOsrRequest);
-        __ str(value, Address(IP, Isolate::stack_overflow_flags_offset()));
-      }
+      __ LoadImmediate(value, Thread::kOsrRequest);
+      __ str(value, Address(THR, Thread::stack_overflow_flags_offset()));
     }
     __ Comment("CheckStackOverflowSlowPath");
     __ Bind(entry_label());
@@ -2928,13 +2920,7 @@
   CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
   compiler->AddSlowPathCode(slow_path);
 
-  if (compiler->is_optimizing() && FLAG_allow_absolute_addresses) {
-    __ LoadImmediate(IP, Isolate::Current()->stack_limit_address());
-    __ ldr(IP, Address(IP));
-  } else {
-    __ LoadIsolate(IP);
-    __ ldr(IP, Address(IP, Isolate::stack_limit_offset()));
-  }
+  __ ldr(IP, Address(THR, Thread::stack_limit_offset()));
   __ cmp(SP, Operand(IP));
   __ b(slow_path->entry_label(), LS);
   if (compiler->CanOSRFunction() && in_loop()) {
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index f43e2bb..cb225a2 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -2584,19 +2584,11 @@
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
     if (FLAG_use_osr && osr_entry_label()->IsLinked()) {
-      uword flags_address = Isolate::Current()->stack_overflow_flags_address();
       const Register value = instruction_->locs()->temp(0).reg();
       __ Comment("CheckStackOverflowSlowPathOsr");
       __ Bind(osr_entry_label());
-      if (FLAG_allow_absolute_addresses) {
-        __ LoadImmediate(TMP, flags_address);
-        __ LoadImmediate(value, Isolate::kOsrRequest);
-        __ str(value, Address(TMP));
-      } else {
-        __ LoadIsolate(TMP);
-        __ LoadImmediate(value, Isolate::kOsrRequest);
-        __ str(value, Address(TMP, Isolate::stack_overflow_flags_offset()));
-      }
+      __ LoadImmediate(value, Thread::kOsrRequest);
+      __ str(value, Address(THR, Thread::stack_overflow_flags_offset()));
     }
     __ Comment("CheckStackOverflowSlowPath");
     __ Bind(entry_label());
@@ -2638,13 +2630,7 @@
   CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
   compiler->AddSlowPathCode(slow_path);
 
-  if (compiler->is_optimizing() && FLAG_allow_absolute_addresses) {
-    __ LoadImmediate(TMP, Isolate::Current()->stack_limit_address());
-    __ ldr(TMP, Address(TMP));
-  } else {
-    __ LoadIsolate(TMP);
-    __ ldr(TMP, Address(TMP, Isolate::stack_limit_offset()));
-  }
+  __ ldr(TMP, Address(THR, Thread::stack_limit_offset()));
   __ CompareRegisters(SP, TMP);
   __ b(slow_path->entry_label(), LS);
   if (compiler->CanOSRFunction() && in_loop()) {
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index bd83626..a6471e1 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -2583,11 +2583,10 @@
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
     if (FLAG_use_osr && osr_entry_label()->IsLinked()) {
-      uword flags_address = Isolate::Current()->stack_overflow_flags_address();
       __ Comment("CheckStackOverflowSlowPathOsr");
       __ Bind(osr_entry_label());
-      __ movl(Address::Absolute(flags_address),
-              Immediate(Isolate::kOsrRequest));
+      __ movl(Address(THR, Thread::stack_overflow_flags_offset()),
+              Immediate(Thread::kOsrRequest));
     }
     __ Comment("CheckStackOverflowSlowPath");
     __ Bind(entry_label());
@@ -2629,13 +2628,7 @@
   CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
   compiler->AddSlowPathCode(slow_path);
 
-  if (compiler->is_optimizing()) {
-    __ cmpl(ESP, Address::Absolute(Isolate::Current()->stack_limit_address()));
-  } else {
-    Register tmp = locs()->temp(0).reg();
-    __ LoadIsolate(tmp);
-    __ cmpl(ESP, Address(tmp, Isolate::stack_limit_offset()));
-  }
+  __ cmpl(ESP, Address(THR, Thread::stack_limit_offset()));
   __ j(BELOW_EQUAL, slow_path->entry_label());
   if (compiler->CanOSRFunction() && in_loop()) {
     // In unoptimized code check the usage counter to trigger OSR at loop
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 7799bd9..7342fb6 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -2702,19 +2702,11 @@
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
     if (FLAG_use_osr && osr_entry_label()->IsLinked()) {
-      uword flags_address = Isolate::Current()->stack_overflow_flags_address();
       Register value = instruction_->locs()->temp(0).reg();
       __ Comment("CheckStackOverflowSlowPathOsr");
       __ Bind(osr_entry_label());
-      if (FLAG_allow_absolute_addresses) {
-        __ LoadImmediate(TMP, flags_address);
-        __ LoadImmediate(value, Isolate::kOsrRequest);
-        __ sw(value, Address(TMP));
-      } else {
-        __ LoadIsolate(TMP);
-        __ LoadImmediate(value, Isolate::kOsrRequest);
-        __ sw(value, Address(TMP, Isolate::stack_overflow_flags_offset()));
-      }
+      __ LoadImmediate(value, Thread::kOsrRequest);
+      __ sw(value, Address(THR, Thread::stack_overflow_flags_offset()));
     }
     __ Comment("CheckStackOverflowSlowPath");
     __ Bind(entry_label());
@@ -2757,13 +2749,7 @@
   CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
   compiler->AddSlowPathCode(slow_path);
 
-  if (compiler->is_optimizing() && FLAG_allow_absolute_addresses) {
-    __ LoadImmediate(TMP, Isolate::Current()->stack_limit_address());
-    __ lw(CMPRES1, Address(TMP));
-  } else {
-    __ LoadIsolate(TMP);
-    __ lw(CMPRES1, Address(TMP, Isolate::stack_limit_offset()));
-  }
+  __ lw(CMPRES1, Address(THR, Thread::stack_limit_offset()));
   __ BranchUnsignedLessEqual(SP, CMPRES1, slow_path->entry_label());
   if (compiler->CanOSRFunction() && in_loop()) {
     Register temp = locs()->temp(0).reg();
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 9623ec2..1738532 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -2602,18 +2602,10 @@
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
     if (FLAG_use_osr && osr_entry_label()->IsLinked()) {
-      uword flags_address = Isolate::Current()->stack_overflow_flags_address();
-      Register temp = instruction_->locs()->temp(0).reg();
       __ Comment("CheckStackOverflowSlowPathOsr");
       __ Bind(osr_entry_label());
-      if (FLAG_allow_absolute_addresses) {
-        __ LoadImmediate(temp, Immediate(flags_address));
-        __ movq(Address(temp, 0), Immediate(Isolate::kOsrRequest));
-      } else {
-        __ LoadIsolate(TMP);
-        __ movq(Address(TMP, Isolate::stack_overflow_flags_offset()),
-                Immediate(Isolate::kOsrRequest));
-      }
+      __ movq(Address(THR, Thread::stack_overflow_flags_offset()),
+              Immediate(Thread::kOsrRequest));
     }
     __ Comment("CheckStackOverflowSlowPath");
     __ Bind(entry_label());
@@ -2658,14 +2650,7 @@
 
   Register temp = locs()->temp(0).reg();
   // Generate stack overflow check.
-  if (compiler->is_optimizing() && FLAG_allow_absolute_addresses) {
-    __ LoadImmediate(
-        temp, Immediate(Isolate::Current()->stack_limit_address()));
-    __ cmpq(RSP, Address(temp, 0));
-  } else {
-    __ LoadIsolate(temp);
-    __ cmpq(RSP, Address(temp, Isolate::stack_limit_offset()));
-  }
+  __ cmpq(RSP, Address(THR, Thread::stack_limit_offset()));
   __ j(BELOW_EQUAL, slow_path->entry_label());
   if (compiler->CanOSRFunction() && in_loop()) {
     // In unoptimized code check the usage counter to trigger OSR at loop
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index 979ca87..4eeee12 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -2055,7 +2055,7 @@
 }
 
 
-void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) {
+void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
   if (FLAG_interpret_irregexp) return;
 
   static const intptr_t kRegExpParamOffset = 2 * kWordSize;
@@ -2074,7 +2074,7 @@
   __ LoadClassId(R1, R1);
   __ AddImmediate(R1, R1, -kOneByteStringCid);
   __ add(R1, R2, Operand(R1, LSL, kWordSizeLog2));
-  __ ldr(R0, FieldAddress(R1, JSRegExp::function_offset(kOneByteStringCid)));
+  __ ldr(R0, FieldAddress(R1, RegExp::function_offset(kOneByteStringCid)));
 
   // Registers are now set up for the lazy compile stub. It expects the function
   // in R0, the argument descriptor in R4, and IC-Data in R9.
diff --git a/runtime/vm/intrinsifier_arm64.cc b/runtime/vm/intrinsifier_arm64.cc
index fa7c20d0..f8611a1 100644
--- a/runtime/vm/intrinsifier_arm64.cc
+++ b/runtime/vm/intrinsifier_arm64.cc
@@ -2130,7 +2130,7 @@
 }
 
 
-void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) {
+void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
   if (FLAG_interpret_irregexp) return;
 
   static const intptr_t kRegExpParamOffset = 2 * kWordSize;
@@ -2149,7 +2149,7 @@
   __ LoadClassId(R1, R1);
   __ AddImmediate(R1, R1, -kOneByteStringCid);
   __ add(R1, R2, Operand(R1, LSL, kWordSizeLog2));
-  __ ldr(R0, FieldAddress(R1, JSRegExp::function_offset(kOneByteStringCid)));
+  __ ldr(R0, FieldAddress(R1, RegExp::function_offset(kOneByteStringCid)));
 
   // Registers are now set up for the lazy compile stub. It expects the function
   // in R0, the argument descriptor in R4, and IC-Data in R5.
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index ab3fcb3..4e2a8e9 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -2083,7 +2083,7 @@
 }
 
 
-void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) {
+void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
   if (FLAG_interpret_irregexp) return;
 
   static const intptr_t kRegExpParamOffset = 3 * kWordSize;
@@ -2102,7 +2102,7 @@
   __ LoadClassId(EDI, EDI);
   __ SubImmediate(EDI, Immediate(kOneByteStringCid));
   __ movl(EAX, FieldAddress(EBX, EDI, TIMES_4,
-                            JSRegExp::function_offset(kOneByteStringCid)));
+                            RegExp::function_offset(kOneByteStringCid)));
 
   // Registers are now set up for the lazy compile stub. It expects the function
   // in EAX, the argument descriptor in EDX, and IC-Data in ECX.
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index 3625b13..1fd65bc 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -2161,7 +2161,7 @@
 }
 
 
-void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) {
+void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
   if (FLAG_interpret_irregexp) return;
 
   static const intptr_t kRegExpParamOffset = 2 * kWordSize;
@@ -2181,7 +2181,7 @@
   __ AddImmediate(T2, -kOneByteStringCid);
   __ sll(T2, T2, kWordSizeLog2);
   __ addu(T2, T2, T1);
-  __ lw(T0, FieldAddress(T2, JSRegExp::function_offset(kOneByteStringCid)));
+  __ lw(T0, FieldAddress(T2, RegExp::function_offset(kOneByteStringCid)));
 
   // Registers are now set up for the lazy compile stub. It expects the function
   // in T0, the argument descriptor in S4, and IC-Data in S5.
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index b3f0a73..5fd3ad7 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -2039,7 +2039,7 @@
 }
 
 
-void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) {
+void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
   if (FLAG_interpret_irregexp) return;
 
   static const intptr_t kRegExpParamOffset = 3 * kWordSize;
@@ -2058,7 +2058,7 @@
   __ LoadClassId(RDI, RDI);
   __ SubImmediate(RDI, Immediate(kOneByteStringCid));
   __ movq(RAX, FieldAddress(RBX, RDI, TIMES_8,
-                            JSRegExp::function_offset(kOneByteStringCid)));
+                            RegExp::function_offset(kOneByteStringCid)));
 
   // Registers are now set up for the lazy compile stub. It expects the function
   // in RAX, the argument descriptor in R10, and IC-Data in RCX.
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 0c6a662..7678eef 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -53,7 +53,6 @@
 DECLARE_FLAG(bool, print_metrics);
 DECLARE_FLAG(bool, timing);
 DECLARE_FLAG(bool, trace_service);
-DECLARE_FLAG(bool, trace_service_verbose);
 
 DEFINE_FLAG(bool, trace_isolates, false,
             "Trace isolate creation and shut down.");
@@ -149,12 +148,12 @@
 
 
 NoOOBMessageScope::NoOOBMessageScope(Thread* thread) : StackResource(thread) {
-  isolate()->DeferOOBMessageInterrupts();
+  thread->DeferOOBMessageInterrupts();
 }
 
 
 NoOOBMessageScope::~NoOOBMessageScope() {
-  isolate()->RestoreOOBMessageInterrupts();
+  thread()->RestoreOOBMessageInterrupts();
 }
 
 
@@ -432,8 +431,8 @@
 
 void IsolateMessageHandler::MessageNotify(Message::Priority priority) {
   if (priority >= Message::kOOBPriority) {
-    // Handle out of band messages even if the isolate is busy.
-    I->ScheduleInterrupts(Isolate::kMessageInterrupt);
+    // Handle out of band messages even if the mutator thread is busy.
+    I->ScheduleMessageInterrupts();
   }
   Dart_MessageNotifyCallback callback = I->message_notify_callback();
   if (callback) {
@@ -451,7 +450,9 @@
   Zone* zone = stack_zone.GetZone();
   HandleScope handle_scope(thread);
 #ifndef PRODUCT
-  TimelineDurationScope tds(thread, I->GetIsolateStream(), "HandleMessage");
+  TimelineDurationScope tds(thread,
+                            Timeline::GetIsolateStream(),
+                            "HandleMessage");
   tds.SetNumArguments(1);
   tds.CopyArgument(0, "isolateName", I->name());
 #endif
@@ -757,8 +758,7 @@
 // TODO(srdjan): Some Isolate monitors can be shared. Replace their usage with
 // that shared monitor.
 Isolate::Isolate(const Dart_IsolateFlags& api_flags)
-  :   stack_limit_(0),
-      store_buffer_(new StoreBuffer()),
+  :   store_buffer_(new StoreBuffer()),
       heap_(NULL),
       user_tag_(0),
       current_tag_(UserTag::null()),
@@ -792,11 +792,6 @@
       symbols_mutex_(new Mutex()),
       type_canonicalization_mutex_(new Mutex()),
       constant_canonicalization_mutex_(new Mutex()),
-      saved_stack_limit_(0),
-      deferred_interrupts_mask_(0),
-      deferred_interrupts_(0),
-      stack_overflow_flags_(0),
-      stack_overflow_count_(0),
       message_handler_(NULL),
       spawn_state_(NULL),
       is_runnable_(false),
@@ -903,11 +898,6 @@
   ISOLATE_METRIC_LIST(ISOLATE_METRIC_INIT);
 #undef ISOLATE_METRIC_INIT
 
-#ifndef PRODUCT
-  // Initialize Timeline streams.
-  Timeline::SetupIsolateStreams(result);
-#endif  // !PRODUCT
-
   Heap::Init(result,
              is_vm_isolate
                  ? 0  // New gen size 0; VM isolate should only allocate in old.
@@ -979,28 +969,6 @@
 }
 
 
-/* static */
-uword Isolate::GetCurrentStackPointer() {
-  // 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.
-  uword (*func)() = reinterpret_cast<uword (*)()>(
-      StubCode::GetStackPointer_entry()->EntryPoint());
-  // But for performance (and to support simulators), we normally use a local.
-#if defined(__has_feature)
-#if __has_feature(address_sanitizer)
-  uword current_sp = func();
-  return current_sp;
-#else
-  uword stack_allocated_local_address = reinterpret_cast<uword>(&func);
-  return stack_allocated_local_address;
-#endif
-#else
-  uword stack_allocated_local_address = reinterpret_cast<uword>(&func);
-  return stack_allocated_local_address;
-#endif
-}
-
-
 void Isolate::SetupInstructionsSnapshotPage(
     const uint8_t* instructions_snapshot_buffer) {
   InstructionsSnapshot snapshot(instructions_snapshot_buffer);
@@ -1034,6 +1002,16 @@
 }
 
 
+void Isolate::ScheduleMessageInterrupts() {
+  // We take the threads lock here to ensure that the mutator thread does not
+  // exit the isolate while we are trying to schedule interrupts on it.
+  MonitorLocker ml(threads_lock());
+  Thread* mthread = mutator_thread();
+  if (mthread != NULL) {
+    mthread->ScheduleInterrupts(Thread::kMessageInterrupt);
+  }
+}
+
 
 void Isolate::set_debugger_name(const char* name) {
   free(debugger_name_);
@@ -1055,36 +1033,6 @@
 }
 
 
-void Isolate::SetStackLimitFromStackBase(uword stack_base) {
-  // Set stack limit.
-#if defined(USING_SIMULATOR)
-  // Ignore passed-in native stack top and use Simulator stack top.
-  Simulator* sim = Simulator::Current();  // May allocate a simulator.
-  ASSERT(simulator() == sim);  // This isolate's simulator is the current one.
-  stack_base = sim->StackTop();
-  // The overflow area is accounted for by the simulator.
-#endif
-  SetStackLimit(stack_base - OSThread::GetSpecifiedStackSize());
-}
-
-
-void Isolate::SetStackLimit(uword limit) {
-  // The isolate setting the stack limit is not necessarily the isolate which
-  // the stack limit is being set on.
-  MutexLocker ml(mutex_);
-  if (stack_limit_ == saved_stack_limit_) {
-    // No interrupt pending, set stack_limit_ too.
-    stack_limit_ = limit;
-  }
-  saved_stack_limit_ = limit;
-}
-
-
-void Isolate::ClearStackLimit() {
-  SetStackLimit(~static_cast<uword>(0));
-}
-
-
 void Isolate::DoneLoading() {
   GrowableObjectArray& libs = GrowableObjectArray::Handle(current_zone(),
       object_store()->libraries());
@@ -1126,7 +1074,7 @@
   }
 #ifndef PRODUCT
   if (FLAG_support_timeline) {
-    TimelineStream* stream = GetIsolateStream();
+    TimelineStream* stream = Timeline::GetIsolateStream();
     ASSERT(stream != NULL);
     TimelineEvent* event = stream->StartEvent();
     if (event != NULL) {
@@ -1488,118 +1436,6 @@
 }
 
 
-void Isolate::ScheduleInterrupts(uword interrupt_bits) {
-  MutexLocker ml(mutex_);
-  ASSERT((interrupt_bits & ~kInterruptsMask) == 0);  // Must fit in mask.
-
-  // Check to see if any of the requested interrupts should be deferred.
-  uword defer_bits = interrupt_bits & deferred_interrupts_mask_;
-  if (defer_bits != 0) {
-    deferred_interrupts_ |= defer_bits;
-    interrupt_bits &= ~deferred_interrupts_mask_;
-    if (interrupt_bits == 0) {
-      return;
-    }
-  }
-
-  if (stack_limit_ == saved_stack_limit_) {
-    stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask;
-  }
-  stack_limit_ |= interrupt_bits;
-}
-
-
-uword Isolate::GetAndClearInterrupts() {
-  MutexLocker ml(mutex_);
-  if (stack_limit_ == saved_stack_limit_) {
-    return 0;  // No interrupt was requested.
-  }
-  uword interrupt_bits = stack_limit_ & kInterruptsMask;
-  stack_limit_ = saved_stack_limit_;
-  return interrupt_bits;
-}
-
-
-void Isolate::DeferOOBMessageInterrupts() {
-  MutexLocker ml(mutex_);
-  ASSERT(deferred_interrupts_mask_ == 0);
-  deferred_interrupts_mask_ = kMessageInterrupt;
-
-  if (stack_limit_ != saved_stack_limit_) {
-    // Defer any interrupts which are currently pending.
-    deferred_interrupts_ = stack_limit_ & deferred_interrupts_mask_;
-
-    // Clear deferrable interrupts, if present.
-    stack_limit_ &= ~deferred_interrupts_mask_;
-
-    if ((stack_limit_ & kInterruptsMask) == 0) {
-      // No other pending interrupts.  Restore normal stack limit.
-      stack_limit_ = saved_stack_limit_;
-    }
-  }
-  if (FLAG_trace_service && FLAG_trace_service_verbose) {
-    OS::Print("[+%" Pd64 "ms] Isolate %s deferring OOB interrupts\n",
-              Dart::timestamp(), name());
-  }
-}
-
-
-void Isolate::RestoreOOBMessageInterrupts() {
-  MutexLocker ml(mutex_);
-  ASSERT(deferred_interrupts_mask_ == kMessageInterrupt);
-  deferred_interrupts_mask_ = 0;
-  if (deferred_interrupts_ != 0) {
-    if (stack_limit_ == saved_stack_limit_) {
-      stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask;
-    }
-    stack_limit_ |= deferred_interrupts_;
-    deferred_interrupts_ = 0;
-  }
-  if (FLAG_trace_service && FLAG_trace_service_verbose) {
-    OS::Print("[+%" Pd64 "ms] Isolate %s restoring OOB interrupts\n",
-              Dart::timestamp(), name());
-  }
-}
-
-
-RawError* Isolate::HandleInterrupts() {
-  uword interrupt_bits = GetAndClearInterrupts();
-  if ((interrupt_bits & kVMInterrupt) != 0) {
-    if (store_buffer()->Overflowed()) {
-      if (FLAG_verbose_gc) {
-        OS::PrintErr("Scavenge scheduled by store buffer overflow.\n");
-      }
-      heap()->CollectGarbage(Heap::kNew);
-    }
-  }
-  if ((interrupt_bits & kMessageInterrupt) != 0) {
-    MessageHandler::MessageStatus status =
-        message_handler()->HandleOOBMessages();
-    if (status != MessageHandler::kOK) {
-      // False result from HandleOOBMessages signals that the isolate should
-      // be terminating.
-      if (FLAG_trace_isolates) {
-        OS::Print("[!] Terminating isolate due to OOB message:\n"
-                  "\tisolate:    %s\n", name());
-      }
-      Thread* thread = Thread::Current();
-      const Error& error = Error::Handle(thread->sticky_error());
-      ASSERT(!error.IsNull() && error.IsUnwindError());
-      thread->clear_sticky_error();
-      return error.raw();
-    }
-  }
-  return Error::null();
-}
-
-
-uword Isolate::GetAndClearStackOverflowFlags() {
-  uword stack_overflow_flags = stack_overflow_flags_;
-  stack_overflow_flags_ = 0;
-  return stack_overflow_flags;
-}
-
-
 void Isolate::AddClosureFunction(const Function& function) const {
   GrowableObjectArray& closures =
       GrowableObjectArray::Handle(object_store()->closure_functions());
@@ -1757,7 +1593,7 @@
   Thread* thread = Thread::Current();
 
   // Don't allow anymore dart code to execution on this isolate.
-  ClearStackLimit();
+  thread->ClearStackLimit();
 
   // First, perform higher-level cleanup that may need to allocate.
   {
@@ -1813,11 +1649,6 @@
 
 Dart_IsolateCreateCallback Isolate::create_callback_ = NULL;
 Dart_IsolateShutdownCallback Isolate::shutdown_callback_ = NULL;
-Dart_FileOpenCallback Isolate::file_open_callback_ = NULL;
-Dart_FileReadCallback Isolate::file_read_callback_ = NULL;
-Dart_FileWriteCallback Isolate::file_write_callback_ = NULL;
-Dart_FileCloseCallback Isolate::file_close_callback_ = NULL;
-Dart_EntropySource Isolate::entropy_source_callback_ = NULL;
 
 Monitor* Isolate::isolates_list_monitor_ = NULL;
 Isolate* Isolate::isolates_list_head_ = NULL;
@@ -2607,6 +2438,9 @@
       sticky_error_ = thread->sticky_error();
       thread->clear_sticky_error();
     }
+  } else {
+    ASSERT(thread->api_top_scope_ == NULL);
+    ASSERT(thread->zone_ == NULL);
   }
   if (!bypass_safepoint) {
     // Ensure that the thread reports itself as being at a safepoint.
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index c6a5bd9..8d2508f 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -17,7 +17,6 @@
 #include "vm/tags.h"
 #include "vm/thread.h"
 #include "vm/os_thread.h"
-#include "vm/timeline.h"
 #include "vm/timer.h"
 #include "vm/token_position.h"
 
@@ -229,78 +228,12 @@
     library_tag_handler_ = value;
   }
 
-  void SetStackLimit(uword value);
-  void SetStackLimitFromStackBase(uword stack_base);
-  void ClearStackLimit();
-
-  // Returns the current C++ stack pointer. Equivalent taking the address of a
-  // stack allocated local, but plays well with AddressSanitizer.
-  // TODO(koda): Move to Thread.
-  static uword GetCurrentStackPointer();
-
   void SetupInstructionsSnapshotPage(
       const uint8_t* instructions_snapshot_buffer);
   void SetupDataSnapshotPage(
       const uint8_t* instructions_snapshot_buffer);
 
-  // Returns true if any of the interrupts specified by 'interrupt_bits' are
-  // currently scheduled for this isolate, but leaves them unchanged.
-  //
-  // NOTE: The read uses relaxed memory ordering, i.e., it is atomic and
-  // an interrupt is guaranteed to be observed eventually, but any further
-  // order guarantees must be ensured by other synchronization. See the
-  // tests in isolate_test.cc for example usage.
-  bool HasInterruptsScheduled(uword interrupt_bits) {
-    ASSERT(interrupt_bits == (interrupt_bits & kInterruptsMask));
-    uword limit = AtomicOperations::LoadRelaxed(&stack_limit_);
-    return (limit != saved_stack_limit_) &&
-        (((limit & kInterruptsMask) & interrupt_bits) != 0);
-  }
-
-  // Access to the current stack limit for generated code.  This may be
-  // overwritten with a special value to trigger interrupts.
-  uword stack_limit_address() const {
-    return reinterpret_cast<uword>(&stack_limit_);
-  }
-  static intptr_t stack_limit_offset() {
-    return OFFSET_OF(Isolate, stack_limit_);
-  }
-
-  // The true stack limit for this isolate.
-  uword saved_stack_limit() const { return saved_stack_limit_; }
-
-  // Stack overflow flags
-  enum {
-    kOsrRequest = 0x1,  // Current stack overflow caused by OSR request.
-  };
-
-  uword stack_overflow_flags_address() const {
-    return reinterpret_cast<uword>(&stack_overflow_flags_);
-  }
-  static intptr_t stack_overflow_flags_offset() {
-    return OFFSET_OF(Isolate, stack_overflow_flags_);
-  }
-
-  int32_t IncrementAndGetStackOverflowCount() {
-    return ++stack_overflow_count_;
-  }
-
-  // Retrieves and clears the stack overflow flags.  These are set by
-  // the generated code before the slow path runtime routine for a
-  // stack overflow is called.
-  uword GetAndClearStackOverflowFlags();
-
-  // Interrupt bits.
-  enum {
-    kVMInterrupt = 0x1,  // Internal VM checks: safepoints, store buffers, etc.
-    kMessageInterrupt = 0x2,  // An interrupt to process an out of band message.
-
-    kInterruptsMask = (kVMInterrupt | kMessageInterrupt),
-  };
-
-  void ScheduleInterrupts(uword interrupt_bits);
-  RawError* HandleInterrupts();
-  uword GetAndClearInterrupts();
+  void ScheduleMessageInterrupts();
 
   // Marks all libraries as loaded.
   void DoneLoading();
@@ -432,36 +365,6 @@
     return shutdown_callback_;
   }
 
-  static void SetFileCallbacks(Dart_FileOpenCallback file_open,
-                               Dart_FileReadCallback file_read,
-                               Dart_FileWriteCallback file_write,
-                               Dart_FileCloseCallback file_close) {
-    file_open_callback_ = file_open;
-    file_read_callback_ = file_read;
-    file_write_callback_ = file_write;
-    file_close_callback_ = file_close;
-  }
-
-  static Dart_FileOpenCallback file_open_callback() {
-    return file_open_callback_;
-  }
-  static Dart_FileReadCallback file_read_callback() {
-    return file_read_callback_;
-  }
-  static Dart_FileWriteCallback file_write_callback() {
-    return file_write_callback_;
-  }
-  static Dart_FileCloseCallback file_close_callback() {
-    return file_close_callback_;
-  }
-
-  static void SetEntropySourceCallback(Dart_EntropySource entropy_source) {
-    entropy_source_callback_ = entropy_source;
-  }
-  static Dart_EntropySource entropy_source_callback() {
-    return entropy_source_callback_;
-  }
-
   void set_object_id_ring(ObjectIdRing* ring) {
     object_id_ring_ = ring;
   }
@@ -469,6 +372,7 @@
     return object_id_ring_;
   }
 
+  bool IsDeoptimizing() const { return deopt_context_ != NULL; }
   DeoptContext* deopt_context() const { return deopt_context_; }
   void set_deopt_context(DeoptContext* value) {
     ASSERT(value == NULL || deopt_context_ == NULL);
@@ -542,18 +446,6 @@
   ISOLATE_METRIC_LIST(ISOLATE_METRIC_ACCESSOR);
 #undef ISOLATE_METRIC_ACCESSOR
 
-#ifndef PRODUCT
-#define ISOLATE_TIMELINE_STREAM_ACCESSOR(name, not_used)                       \
-  TimelineStream* Get##name##Stream() { return &stream_##name##_; }
-  ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_ACCESSOR)
-#undef ISOLATE_TIMELINE_STREAM_ACCESSOR
-#else
-#define ISOLATE_TIMELINE_STREAM_ACCESSOR(name, not_used)                       \
-  TimelineStream* Get##name##Stream() { return NULL; }
-  ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_ACCESSOR)
-#undef ISOLATE_TIMELINE_STREAM_ACCESSOR
-#endif  // !PRODUCT
-
   static intptr_t IsolateListLength();
 
   RawGrowableObjectArray* tag_table() const { return tag_table_; }
@@ -676,7 +568,6 @@
  private:
   friend class Dart;  // Init, InitOnce, Shutdown.
   friend class IsolateKillerVisitor;  // Kill().
-  friend class NoOOBMessageScope;
 
   explicit Isolate(const Dart_IsolateFlags& api_flags);
 
@@ -703,9 +594,6 @@
     user_tag_ = tag;
   }
 
-  void DeferOOBMessageInterrupts();
-  void RestoreOOBMessageInterrupts();
-
   RawGrowableObjectArray* GetAndClearPendingServiceExtensionCalls();
   RawGrowableObjectArray* pending_service_extension_calls() const {
     return pending_service_extension_calls_;
@@ -730,9 +618,6 @@
   }
 
   // Accessed from generated code:
-  // TODO(asiva): Need to consider moving the stack_limit_ from isolate to
-  // being thread specific.
-  uword stack_limit_;
   StoreBuffer* store_buffer_;
   Heap* heap_;
   uword user_tag_;
@@ -766,15 +651,10 @@
   bool has_compiled_code_;  // Can check that no compilation occured.
   Random random_;
   Simulator* simulator_;
-  Mutex* mutex_;  // Protects stack_limit_, saved_stack_limit_, compiler stats.
+  Mutex* mutex_;  // Protects compiler stats.
   Mutex* symbols_mutex_;  // Protects concurrent access to the symbol table.
   Mutex* type_canonicalization_mutex_;  // Protects type canonicalization.
   Mutex* constant_canonicalization_mutex_;  // Protects const canonicalization.
-  uword saved_stack_limit_;
-  uword deferred_interrupts_mask_;
-  uword deferred_interrupts_;
-  uword stack_overflow_flags_;
-  int32_t stack_overflow_count_;
   MessageHandler* message_handler_;
   IsolateSpawnState* spawn_state_;
   bool is_runnable_;
@@ -869,20 +749,9 @@
   ISOLATE_METRIC_LIST(ISOLATE_METRIC_VARIABLE);
 #undef ISOLATE_METRIC_VARIABLE
 
-#ifndef PRODUCT
-#define ISOLATE_TIMELINE_STREAM_VARIABLE(name, not_used)                       \
-  TimelineStream stream_##name##_;
-  ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_VARIABLE)
-#undef ISOLATE_TIMELINE_STREAM_VARIABLE
-#endif  // !PRODUCT
 
   static Dart_IsolateCreateCallback create_callback_;
   static Dart_IsolateShutdownCallback shutdown_callback_;
-  static Dart_FileOpenCallback file_open_callback_;
-  static Dart_FileReadCallback file_read_callback_;
-  static Dart_FileWriteCallback file_write_callback_;
-  static Dart_FileCloseCallback file_close_callback_;
-  static Dart_EntropySource entropy_source_callback_;
   static Dart_IsolateInterruptCallback vmstats_callback_;
 
   static void WakePauseEventHandler(Dart_Isolate isolate);
@@ -907,7 +776,6 @@
   friend class ServiceIsolate;
   friend class Thread;
   friend class Timeline;
-  friend class IsolateTestHelper;
 
   DISALLOW_COPY_AND_ASSIGN(Isolate);
 };
@@ -927,9 +795,9 @@
     }
     if (saved_isolate_ != new_isolate_) {
       ASSERT(Isolate::Current() == NULL);
-      // Ensure this is not a nested 'isolate enter' with prior state.
-      ASSERT(new_isolate_->saved_stack_limit() == 0);
       Thread::EnterIsolate(new_isolate_);
+      // Ensure this is not a nested 'isolate enter' with prior state.
+      ASSERT(Thread::Current()->saved_stack_limit() == 0);
     }
   }
 
@@ -942,7 +810,7 @@
     if (saved_isolate_ != new_isolate_) {
       ASSERT(saved_isolate_ == NULL);
       // ASSERT that we have bottomed out of all Dart invocations.
-      ASSERT(new_isolate_->saved_stack_limit() == 0);
+      ASSERT(Thread::Current()->saved_stack_limit() == 0);
       Thread::ExitIsolate();
     }
   }
diff --git a/runtime/vm/isolate_test.cc b/runtime/vm/isolate_test.cc
index 6491c41..4e39113 100644
--- a/runtime/vm/isolate_test.cc
+++ b/runtime/vm/isolate_test.cc
@@ -89,21 +89,24 @@
   static const intptr_t kTaskCount;
   static const intptr_t kIterations;
 
-  InterruptChecker(Isolate* isolate,
-                   ThreadBarrier* barrier)
-    : isolate_(isolate),
+  InterruptChecker(Thread* thread, ThreadBarrier* barrier)
+    : thread_(thread),
       barrier_(barrier) {
   }
 
   virtual void Run() {
-    Thread::EnterIsolateAsHelper(isolate_);
+    Thread::EnterIsolateAsHelper(thread_->isolate(), Thread::kUnknownTask);
     // Tell main thread that we are ready.
     barrier_->Sync();
     for (intptr_t i = 0; i < kIterations; ++i) {
       // Busy wait for interrupts.
-      while (!isolate_->HasInterruptsScheduled(Isolate::kVMInterrupt)) {
-        // Do nothing.
-      }
+      uword limit = 0;
+      do {
+        limit = AtomicOperations::LoadRelaxed(
+            reinterpret_cast<uword*>(thread_->stack_limit_address()));
+      } while ((limit == thread_->saved_stack_limit_) ||
+               (((limit & Thread::kInterruptsMask) &
+                 Thread::kVMInterrupt) == 0));
       // Tell main thread that we observed the interrupt.
       barrier_->Sync();
     }
@@ -112,7 +115,7 @@
   }
 
  private:
-  Isolate* isolate_;
+  Thread* thread_;
   ThreadBarrier* barrier_;
 };
 
@@ -130,23 +133,23 @@
 // compiler and/or CPU could reorder operations to make the tasks observe the
 // round update *before* the interrupt is set.
 TEST_CASE(StackLimitInterrupts) {
-  Isolate* isolate = Thread::Current()->isolate();
+  Isolate* isolate = thread->isolate();
   ThreadBarrier barrier(InterruptChecker::kTaskCount + 1,
                         isolate->heap()->barrier(),
                         isolate->heap()->barrier_done());
   // Start all tasks. They will busy-wait until interrupted in the first round.
   for (intptr_t task = 0; task < InterruptChecker::kTaskCount; task++) {
-    Dart::thread_pool()->Run(new InterruptChecker(isolate, &barrier));
+    Dart::thread_pool()->Run(new InterruptChecker(thread, &barrier));
   }
   // Wait for all tasks to get ready for the first round.
   barrier.Sync();
   for (intptr_t i = 0; i < InterruptChecker::kIterations; ++i) {
-    isolate->ScheduleInterrupts(Isolate::kVMInterrupt);
+    thread->ScheduleInterrupts(Thread::kVMInterrupt);
     // Wait for all tasks to observe the interrupt.
     barrier.Sync();
     // Continue with next round.
-    uword interrupts = isolate->GetAndClearInterrupts();
-    EXPECT((interrupts & Isolate::kVMInterrupt) != 0);
+    uword interrupts = thread->GetAndClearInterrupts();
+    EXPECT((interrupts & Thread::kVMInterrupt) != 0);
   }
   barrier.Exit();
 }
@@ -154,17 +157,17 @@
 
 class IsolateTestHelper {
  public:
-  static uword GetStackLimit(Isolate* isolate) {
-    return isolate->stack_limit_;
+  static uword GetStackLimit(Thread* thread) {
+    return thread->stack_limit_;
   }
-  static uword GetSavedStackLimit(Isolate* isolate) {
-    return isolate->saved_stack_limit_;
+  static uword GetSavedStackLimit(Thread* thread) {
+    return thread->saved_stack_limit_;
   }
-  static uword GetDeferredInterruptsMask(Isolate* isolate) {
-    return isolate->deferred_interrupts_mask_;
+  static uword GetDeferredInterruptsMask(Thread* thread) {
+    return thread->deferred_interrupts_mask_;
   }
-  static uword GetDeferredInterrupts(Isolate* isolate) {
-    return isolate->deferred_interrupts_;
+  static uword GetDeferredInterrupts(Thread* thread) {
+    return thread->deferred_interrupts_;
   }
 };
 
@@ -172,82 +175,81 @@
 TEST_CASE(NoOOBMessageScope) {
   // EXPECT_EQ is picky about type agreement for its arguments.
   const uword kZero = 0;
-  const uword kMessageInterrupt = Isolate::kMessageInterrupt;
-  const uword kVMInterrupt = Isolate::kVMInterrupt;
+  const uword kMessageInterrupt = Thread::kMessageInterrupt;
+  const uword kVMInterrupt = Thread::kVMInterrupt;
   uword stack_limit;
   uword interrupt_bits;
 
   // Initially no interrupts are scheduled or deferred.
-  Isolate* isolate = Thread::Current()->isolate();
-  EXPECT_EQ(IsolateTestHelper::GetStackLimit(isolate),
-            IsolateTestHelper::GetSavedStackLimit(isolate));
-  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(isolate));
-  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(isolate));
+  EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+            IsolateTestHelper::GetSavedStackLimit(thread));
+  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(thread));
+  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
 
   {
     // Defer message interrupts.
-    NoOOBMessageScope no_msg_scope(Thread::Current());
-    EXPECT_EQ(IsolateTestHelper::GetStackLimit(isolate),
-              IsolateTestHelper::GetSavedStackLimit(isolate));
+    NoOOBMessageScope no_msg_scope(thread);
+    EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+              IsolateTestHelper::GetSavedStackLimit(thread));
     EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterruptsMask(isolate));
-    EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(isolate));
+              IsolateTestHelper::GetDeferredInterruptsMask(thread));
+    EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
 
     // Schedule a message, it is deferred.
-    isolate->ScheduleInterrupts(Isolate::kMessageInterrupt);
-    EXPECT_EQ(IsolateTestHelper::GetStackLimit(isolate),
-              IsolateTestHelper::GetSavedStackLimit(isolate));
+    thread->ScheduleInterrupts(Thread::kMessageInterrupt);
+    EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+              IsolateTestHelper::GetSavedStackLimit(thread));
     EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterruptsMask(isolate));
+              IsolateTestHelper::GetDeferredInterruptsMask(thread));
     EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterrupts(isolate));
+              IsolateTestHelper::GetDeferredInterrupts(thread));
 
     // Schedule a vm interrupt, it is not deferred.
-    isolate->ScheduleInterrupts(Isolate::kVMInterrupt);
-    stack_limit = IsolateTestHelper::GetStackLimit(isolate);
-    EXPECT_NE(stack_limit, IsolateTestHelper::GetSavedStackLimit(isolate));
-    EXPECT((stack_limit & Isolate::kVMInterrupt) != 0);
+    thread->ScheduleInterrupts(Thread::kVMInterrupt);
+    stack_limit = IsolateTestHelper::GetStackLimit(thread);
+    EXPECT_NE(stack_limit, IsolateTestHelper::GetSavedStackLimit(thread));
+    EXPECT((stack_limit & Thread::kVMInterrupt) != 0);
     EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterruptsMask(isolate));
+              IsolateTestHelper::GetDeferredInterruptsMask(thread));
     EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterrupts(isolate));
+              IsolateTestHelper::GetDeferredInterrupts(thread));
 
     // Clear the vm interrupt.  Message is still deferred.
-    interrupt_bits = isolate->GetAndClearInterrupts();
+    interrupt_bits = thread->GetAndClearInterrupts();
     EXPECT_EQ(kVMInterrupt, interrupt_bits);
-    EXPECT_EQ(IsolateTestHelper::GetStackLimit(isolate),
-              IsolateTestHelper::GetSavedStackLimit(isolate));
+    EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+              IsolateTestHelper::GetSavedStackLimit(thread));
     EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterruptsMask(isolate));
+              IsolateTestHelper::GetDeferredInterruptsMask(thread));
     EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterrupts(isolate));
+              IsolateTestHelper::GetDeferredInterrupts(thread));
   }
 
   // Restore message interrupts.  Message is now pending.
-  stack_limit = IsolateTestHelper::GetStackLimit(isolate);
-  EXPECT_NE(stack_limit, IsolateTestHelper::GetSavedStackLimit(isolate));
-  EXPECT((stack_limit & Isolate::kMessageInterrupt) != 0);
-  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(isolate));
-  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(isolate));
+  stack_limit = IsolateTestHelper::GetStackLimit(thread);
+  EXPECT_NE(stack_limit, IsolateTestHelper::GetSavedStackLimit(thread));
+  EXPECT((stack_limit & Thread::kMessageInterrupt) != 0);
+  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(thread));
+  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
 
   {
     // Defer message interrupts, again.  The pending interrupt is deferred.
-    NoOOBMessageScope no_msg_scope(Thread::Current());
-    EXPECT_EQ(IsolateTestHelper::GetStackLimit(isolate),
-              IsolateTestHelper::GetSavedStackLimit(isolate));
+    NoOOBMessageScope no_msg_scope(thread);
+    EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+              IsolateTestHelper::GetSavedStackLimit(thread));
     EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterruptsMask(isolate));
+              IsolateTestHelper::GetDeferredInterruptsMask(thread));
     EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterrupts(isolate));
+              IsolateTestHelper::GetDeferredInterrupts(thread));
   }
 
   // Restore, then clear interrupts.  The world is as it was.
-  interrupt_bits = isolate->GetAndClearInterrupts();
+  interrupt_bits = thread->GetAndClearInterrupts();
   EXPECT_EQ(kMessageInterrupt, interrupt_bits);
-  EXPECT_EQ(IsolateTestHelper::GetStackLimit(isolate),
-            IsolateTestHelper::GetSavedStackLimit(isolate));
-  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(isolate));
-  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(isolate));
+  EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+            IsolateTestHelper::GetSavedStackLimit(thread));
+  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(thread));
+  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
 }
 
 }  // namespace dart
diff --git a/runtime/vm/longjump.cc b/runtime/vm/longjump.cc
index 13e0133..2bc7e31 100644
--- a/runtime/vm/longjump.cc
+++ b/runtime/vm/longjump.cc
@@ -26,7 +26,7 @@
   // We do not want to jump past Dart frames.  Note that this code
   // assumes the stack grows from high to low.
   Thread* thread = Thread::Current();
-  uword jumpbuf_addr = Isolate::GetCurrentStackPointer();
+  uword jumpbuf_addr = Thread::GetCurrentStackPointer();
 #if defined(USING_SIMULATOR)
   Simulator* sim = Simulator::Current();
   // When using simulator, only mutator thread should refer to Simulator
diff --git a/runtime/vm/megamorphic_cache_table.cc b/runtime/vm/megamorphic_cache_table.cc
index 6c4ccf1..b793d35 100644
--- a/runtime/vm/megamorphic_cache_table.cc
+++ b/runtime/vm/megamorphic_cache_table.cc
@@ -61,7 +61,7 @@
   // it is considered in the search for an exception handler.
   code.set_exception_handlers(Object::empty_exception_handlers());
   const Class& cls =
-      Class::Handle(Type::Handle(Type::Function()).type_class());
+      Class::Handle(Type::Handle(Type::DartFunctionType()).type_class());
   const Function& function =
       Function::Handle(Function::New(Symbols::MegamorphicMiss(),
                                      RawFunction::kRegularFunction,
diff --git a/runtime/vm/method_recognizer.h b/runtime/vm/method_recognizer.h
index 1292b84..f4d6b06 100644
--- a/runtime/vm/method_recognizer.h
+++ b/runtime/vm/method_recognizer.h
@@ -62,87 +62,87 @@
   V(::, min, MathMin, 1115051548)                                              \
   V(::, max, MathMax, 1410473322)                                              \
   V(::, _doublePow, MathDoublePow, 562154128)                                  \
-  V(Float32x4, Float32x4., Float32x4Constructor, 1849420944)                   \
-  V(Float32x4, Float32x4.zero, Float32x4Zero, 762161262)                       \
-  V(Float32x4, Float32x4.splat, Float32x4Splat, 255855286)                     \
-  V(Float32x4, Float32x4.fromInt32x4Bits, Float32x4FromInt32x4Bits, 1718571366)\
-  V(Float32x4, Float32x4.fromFloat64x2, Float32x4FromFloat64x2, 1458098858)    \
-  V(_Float32x4, shuffle, Float32x4Shuffle, 2015957023)                         \
-  V(_Float32x4, shuffleMix, Float32x4ShuffleMix, 1099087979)                   \
-  V(_Float32x4, get:signMask, Float32x4GetSignMask, 487049875)                 \
-  V(_Float32x4, _cmpequal, Float32x4Equal, 1069901308)                         \
-  V(_Float32x4, _cmpgt, Float32x4GreaterThan, 2112381651)                      \
-  V(_Float32x4, _cmpgte, Float32x4GreaterThanOrEqual, 1088241265)              \
-  V(_Float32x4, _cmplt, Float32x4LessThan, 2001171012)                         \
-  V(_Float32x4, _cmplte, Float32x4LessThanOrEqual, 1568686387)                 \
-  V(_Float32x4, _cmpnequal, Float32x4NotEqual, 1833412828)                     \
-  V(_Float32x4, _min, Float32x4Min, 1194113943)                                \
-  V(_Float32x4, _max, Float32x4Max, 1876936155)                                \
-  V(_Float32x4, _scale, Float32x4Scale, 1176743640)                            \
-  V(_Float32x4, _sqrt, Float32x4Sqrt, 526238610)                               \
-  V(_Float32x4, _reciprocalSqrt, Float32x4ReciprocalSqrt, 860560177)           \
-  V(_Float32x4, _reciprocal, Float32x4Reciprocal, 1703468100)                  \
-  V(_Float32x4, _negate, Float32x4Negate, 1409902640)                          \
-  V(_Float32x4, _abs, Float32x4Absolute, 2116840471)                           \
-  V(_Float32x4, _clamp, Float32x4Clamp, 1789892357)                            \
-  V(_Float32x4, withX, Float32x4WithX, 1311992575)                             \
-  V(_Float32x4, withY, Float32x4WithY, 175290640)                              \
-  V(_Float32x4, withZ, Float32x4WithZ, 837367384)                              \
-  V(_Float32x4, withW, Float32x4WithW, 1625145605)                             \
-  V(Float64x2, Float64x2., Float64x2Constructor, 1428850802)                   \
-  V(Float64x2, Float64x2.zero, Float64x2Zero, 29170676)                        \
-  V(Float64x2, Float64x2.splat, Float64x2Splat, 1077183856)                    \
-  V(Float64x2, Float64x2.fromFloat32x4, Float64x2FromFloat32x4, 1752000980)    \
-  V(_Float64x2, get:x, Float64x2GetX, 1488958362)                              \
-  V(_Float64x2, get:y, Float64x2GetY, 1022688506)                              \
-  V(_Float64x2, _negate, Float64x2Negate, 960840275)                           \
-  V(_Float64x2, abs, Float64x2Abs, 52403783)                                   \
-  V(_Float64x2, sqrt, Float64x2Sqrt, 2012680669)                               \
-  V(_Float64x2, get:signMask, Float64x2GetSignMask, 668856717)                 \
-  V(_Float64x2, scale, Float64x2Scale, 646122081)                              \
-  V(_Float64x2, withX, Float64x2WithX, 489409269)                              \
-  V(_Float64x2, withY, Float64x2WithY, 943642284)                              \
-  V(_Float64x2, min, Float64x2Min, 685235702)                                  \
-  V(_Float64x2, max, Float64x2Max, 198659675)                                  \
-  V(Int32x4, Int32x4., Int32x4Constructor, 80862812)                           \
-  V(Int32x4, Int32x4.bool, Int32x4BoolConstructor, 1949580252)                 \
-  V(Int32x4, Int32x4.fromFloat32x4Bits, Int32x4FromFloat32x4Bits, 1611205288)  \
-  V(_Int32x4, get:flagX, Int32x4GetFlagX, 1446544324)                          \
-  V(_Int32x4, get:flagY, Int32x4GetFlagY, 1148149370)                          \
-  V(_Int32x4, get:flagZ, Int32x4GetFlagZ, 550901369)                           \
-  V(_Int32x4, get:flagW, Int32x4GetFlagW, 1346664620)                          \
-  V(_Int32x4, get:signMask, Int32x4GetSignMask, 740215269)                     \
-  V(_Int32x4, shuffle, Int32x4Shuffle, 549194518)                              \
-  V(_Int32x4, shuffleMix, Int32x4ShuffleMix, 1550866145)                       \
-  V(_Int32x4, select, Int32x4Select, 614943686)                                \
-  V(_Int32x4, withFlagX, Int32x4WithFlagX, 250974159)                          \
-  V(_Int32x4, withFlagY, Int32x4WithFlagY, 1686481348)                         \
-  V(_Int32x4, withFlagZ, Int32x4WithFlagZ, 645582330)                          \
-  V(_Int32x4, withFlagW, Int32x4WithFlagW, 878364277)                          \
-  V(_Float32Array, [], Float32ArrayGetIndexed, 1002307136)                     \
-  V(_Float32Array, []=, Float32ArraySetIndexed, 279546769)                     \
-  V(_Int8Array, [], Int8ArrayGetIndexed, 1141846285)                           \
-  V(_Int8Array, []=, Int8ArraySetIndexed, 1486839324)                          \
-  V(_Uint8ClampedArray, [], Uint8ClampedArrayGetIndexed, 513704632)            \
-  V(_Uint8ClampedArray, []=, Uint8ClampedArraySetIndexed, 1015846567)          \
+  V(Float32x4, Float32x4., Float32x4Constructor, 93751705)                     \
+  V(Float32x4, Float32x4.zero, Float32x4Zero, 1193954374)                      \
+  V(Float32x4, Float32x4.splat, Float32x4Splat, 12296613)                      \
+  V(Float32x4, Float32x4.fromInt32x4Bits, Float32x4FromInt32x4Bits, 1188039061)\
+  V(Float32x4, Float32x4.fromFloat64x2, Float32x4FromFloat64x2, 1750763218)    \
+  V(Float32x4, shuffle, Float32x4Shuffle, 2015957023)                          \
+  V(Float32x4, shuffleMix, Float32x4ShuffleMix, 1099087979)                    \
+  V(Float32x4, get:signMask, Float32x4GetSignMask, 487049875)                  \
+  V(Float32x4, _cmpequal, Float32x4Equal, 1069901308)                          \
+  V(Float32x4, _cmpgt, Float32x4GreaterThan, 2112381651)                       \
+  V(Float32x4, _cmpgte, Float32x4GreaterThanOrEqual, 1088241265)               \
+  V(Float32x4, _cmplt, Float32x4LessThan, 2001171012)                          \
+  V(Float32x4, _cmplte, Float32x4LessThanOrEqual, 1568686387)                  \
+  V(Float32x4, _cmpnequal, Float32x4NotEqual, 1833412828)                      \
+  V(Float32x4, _min, Float32x4Min, 1194113943)                                 \
+  V(Float32x4, _max, Float32x4Max, 1876936155)                                 \
+  V(Float32x4, _scale, Float32x4Scale, 1176743640)                             \
+  V(Float32x4, _sqrt, Float32x4Sqrt, 526238610)                                \
+  V(Float32x4, _reciprocalSqrt, Float32x4ReciprocalSqrt, 860560177)            \
+  V(Float32x4, _reciprocal, Float32x4Reciprocal, 1703468100)                   \
+  V(Float32x4, _negate, Float32x4Negate, 1409902640)                           \
+  V(Float32x4, _abs, Float32x4Absolute, 2116840471)                            \
+  V(Float32x4, _clamp, Float32x4Clamp, 1789892357)                             \
+  V(Float32x4, withX, Float32x4WithX, 1311992575)                              \
+  V(Float32x4, withY, Float32x4WithY, 175290640)                               \
+  V(Float32x4, withZ, Float32x4WithZ, 837367384)                               \
+  V(Float32x4, withW, Float32x4WithW, 1625145605)                              \
+  V(Float64x2, Float64x2., Float64x2Constructor, 423355933)                    \
+  V(Float64x2, Float64x2.zero, Float64x2Zero, 2066666975)                      \
+  V(Float64x2, Float64x2.splat, Float64x2Splat, 716962994)                     \
+  V(Float64x2, Float64x2.fromFloat32x4, Float64x2FromFloat32x4, 792974246)     \
+  V(Float64x2, get:x, Float64x2GetX, 1488958362)                               \
+  V(Float64x2, get:y, Float64x2GetY, 1022688506)                               \
+  V(Float64x2, _negate, Float64x2Negate, 960840275)                            \
+  V(Float64x2, abs, Float64x2Abs, 52403783)                                    \
+  V(Float64x2, sqrt, Float64x2Sqrt, 2012680669)                                \
+  V(Float64x2, get:signMask, Float64x2GetSignMask, 668856717)                  \
+  V(Float64x2, scale, Float64x2Scale, 646122081)                               \
+  V(Float64x2, withX, Float64x2WithX, 489409269)                               \
+  V(Float64x2, withY, Float64x2WithY, 943642284)                               \
+  V(Float64x2, min, Float64x2Min, 685235702)                                   \
+  V(Float64x2, max, Float64x2Max, 198659675)                                   \
+  V(Int32x4, Int32x4., Int32x4Constructor, 649173415)                          \
+  V(Int32x4, Int32x4.bool, Int32x4BoolConstructor, 458597857)                  \
+  V(Int32x4, Int32x4.fromFloat32x4Bits, Int32x4FromFloat32x4Bits, 2122470988)  \
+  V(Int32x4, get:flagX, Int32x4GetFlagX, 1446544324)                           \
+  V(Int32x4, get:flagY, Int32x4GetFlagY, 1148149370)                           \
+  V(Int32x4, get:flagZ, Int32x4GetFlagZ, 550901369)                            \
+  V(Int32x4, get:flagW, Int32x4GetFlagW, 1346664620)                           \
+  V(Int32x4, get:signMask, Int32x4GetSignMask, 740215269)                      \
+  V(Int32x4, shuffle, Int32x4Shuffle, 549194518)                               \
+  V(Int32x4, shuffleMix, Int32x4ShuffleMix, 1550866145)                        \
+  V(Int32x4, select, Int32x4Select, 614943686)                                 \
+  V(Int32x4, withFlagX, Int32x4WithFlagX, 250974159)                           \
+  V(Int32x4, withFlagY, Int32x4WithFlagY, 1686481348)                          \
+  V(Int32x4, withFlagZ, Int32x4WithFlagZ, 645582330)                           \
+  V(Int32x4, withFlagW, Int32x4WithFlagW, 878364277)                           \
+  V(Float32List, [], Float32ArrayGetIndexed, 1002307136)                       \
+  V(Float32List, []=, Float32ArraySetIndexed, 279546769)                       \
+  V(Int8List, [], Int8ArrayGetIndexed, 1141846285)                             \
+  V(Int8List, []=, Int8ArraySetIndexed, 1486839324)                            \
+  V(Uint8ClampedList, [], Uint8ClampedArrayGetIndexed, 513704632)              \
+  V(Uint8ClampedList, []=, Uint8ClampedArraySetIndexed, 1015846567)            \
   V(_ExternalUint8ClampedArray, [], ExternalUint8ClampedArrayGetIndexed,       \
     513704632)                                                                 \
   V(_ExternalUint8ClampedArray, []=, ExternalUint8ClampedArraySetIndexed,      \
     1015846567)                                                                \
-  V(_Int16Array, [], Int16ArrayGetIndexed, 1826359619)                         \
-  V(_Int16Array, []=, Int16ArraySetIndexed, 1108689116)                        \
-  V(_Uint16Array, [], Uint16ArrayGetIndexed, 118958722)                        \
-  V(_Uint16Array, []=, Uint16ArraySetIndexed, 658824450)                       \
-  V(_Int32Array, [], Int32ArrayGetIndexed, 681203163)                          \
-  V(_Int32Array, []=, Int32ArraySetIndexed, 1786886245)                        \
-  V(_Int64Array, [], Int64ArrayGetIndexed, 1883155004)                         \
-  V(_Int64Array, []=, Int64ArraySetIndexed, 905815059)                         \
-  V(_Float32x4Array, [], Float32x4ArrayGetIndexed, 694822356)                  \
-  V(_Float32x4Array, []=, Float32x4ArraySetIndexed, 1166109127)                \
-  V(_Int32x4Array, [], Int32x4ArrayGetIndexed, 668249259)                      \
-  V(_Int32x4Array, []=, Int32x4ArraySetIndexed, 654739449)                     \
-  V(_Float64x2Array, [], Float64x2ArrayGetIndexed, 196472005)                  \
-  V(_Float64x2Array, []=, Float64x2ArraySetIndexed, 1421858500)                \
+  V(Int16List, [], Int16ArrayGetIndexed, 1826359619)                           \
+  V(Int16List, []=, Int16ArraySetIndexed, 1108689116)                          \
+  V(Uint16List, [], Uint16ArrayGetIndexed, 118958722)                          \
+  V(Uint16List, []=, Uint16ArraySetIndexed, 658824450)                         \
+  V(Int32List, [], Int32ArrayGetIndexed, 681203163)                            \
+  V(Int32List, []=, Int32ArraySetIndexed, 1786886245)                          \
+  V(Int64List, [], Int64ArrayGetIndexed, 1883155004)                           \
+  V(Int64List, []=, Int64ArraySetIndexed, 905815059)                           \
+  V(Float32x4List, [], Float32x4ArrayGetIndexed, 694822356)                    \
+  V(Float32x4List, []=, Float32x4ArraySetIndexed, 1166109127)                  \
+  V(Int32x4List, [], Int32x4ArrayGetIndexed, 668249259)                        \
+  V(Int32x4List, []=, Int32x4ArraySetIndexed, 654739449)                       \
+  V(Float64x2List, [], Float64x2ArrayGetIndexed, 196472005)                    \
+  V(Float64x2List, []=, Float64x2ArraySetIndexed, 1421858500)                  \
   V(_Bigint, get:_neg, Bigint_getNeg, 1681019799)                              \
   V(_Bigint, get:_used, Bigint_getUsed, 1439136438)                            \
   V(_Bigint, get:_digits, Bigint_getDigits, 769722770)                         \
@@ -187,7 +187,7 @@
   V(_List, []=, ObjectArraySetIndexed, 886228780)                              \
   V(_GrowableList, .withData, GrowableArray_Allocate, 131424500)               \
   V(_GrowableList, add, GrowableArray_add, 242296201)                          \
-  V(_JSSyntaxRegExp, _ExecuteMatch, JSRegExp_ExecuteMatch, 1490503678)         \
+  V(_RegExp, _ExecuteMatch, RegExp_ExecuteMatch, 2077783530)                   \
   V(Object, ==, ObjectEquals, 291909336)                                       \
   V(Object, get:runtimeType, ObjectRuntimeType, 15188587)                      \
   V(_StringBase, get:hashCode, String_getHashCode, 2026040200)                 \
@@ -245,38 +245,38 @@
 
 
 #define TYPED_DATA_LIB_INTRINSIC_LIST(V)                                       \
-  V(_Int8Array, ., TypedData_Int8Array_factory, 1058992179)                    \
-  V(_Uint8Array, ., TypedData_Uint8Array_factory, 1807546986)                  \
-  V(_Uint8ClampedArray, ., TypedData_Uint8ClampedArray_factory, 548459853)     \
-  V(_Int16Array, ., TypedData_Int16Array_factory, 1796211480)                  \
-  V(_Uint16Array, ., TypedData_Uint16Array_factory, 1960868166)                \
-  V(_Int32Array, ., TypedData_Int32Array_factory, 372258367)                   \
-  V(_Uint32Array, ., TypedData_Uint32Array_factory, 1446612721)                \
-  V(_Int64Array, ., TypedData_Int64Array_factory, 964028713)                   \
-  V(_Uint64Array, ., TypedData_Uint64Array_factory, 721823156)                 \
-  V(_Float32Array, ., TypedData_Float32Array_factory, 392399264)               \
-  V(_Float64Array, ., TypedData_Float64Array_factory, 42503976)                \
-  V(_Float32x4Array, ., TypedData_Float32x4Array_factory, 1960198693)          \
-  V(_Int32x4Array, ., TypedData_Int32x4Array_factory, 1433742555)              \
-  V(_Float64x2Array, ., TypedData_Float64x2Array_factory, 165463437)           \
+  V(Int8List, ., TypedData_Int8Array_factory, 779569635)                       \
+  V(Uint8List, ., TypedData_Uint8Array_factory, 1790399545)                    \
+  V(Uint8ClampedList, ., TypedData_Uint8ClampedArray_factory, 405875159)       \
+  V(Int16List, ., TypedData_Int16Array_factory, 347431914)                     \
+  V(Uint16List, ., TypedData_Uint16Array_factory, 121990116)                   \
+  V(Int32List, ., TypedData_Int32Array_factory, 1540657744)                    \
+  V(Uint32List, ., TypedData_Uint32Array_factory, 1012511652)                  \
+  V(Int64List, ., TypedData_Int64Array_factory, 1473796807)                    \
+  V(Uint64List, ., TypedData_Uint64Array_factory, 738799620)                   \
+  V(Float32List, ., TypedData_Float32Array_factory, 1938690635)                \
+  V(Float64List, ., TypedData_Float64Array_factory, 1344005361)                \
+  V(Float32x4List, ., TypedData_Float32x4Array_factory, 2055067416)            \
+  V(Int32x4List, ., TypedData_Int32x4Array_factory, 504220232)                 \
+  V(Float64x2List, ., TypedData_Float64x2Array_factory, 416019673)             \
 
 #define GRAPH_TYPED_DATA_INTRINSICS_LIST(V) \
-  V(_Uint8Array, [], Uint8ArrayGetIndexed, 513704632)                          \
-  V(_Uint8Array, []=, Uint8ArraySetIndexed, 2123520783)                        \
+  V(Uint8List, [], Uint8ArrayGetIndexed, 513704632)                            \
+  V(Uint8List, []=, Uint8ArraySetIndexed, 2123520783)                          \
   V(_ExternalUint8Array, [], ExternalUint8ArrayGetIndexed, 513704632)          \
   V(_ExternalUint8Array, []=, ExternalUint8ArraySetIndexed, 2123520783)        \
-  V(_Uint32Array, [], Uint32ArrayGetIndexed, 1179675338)                       \
-  V(_Uint32Array, []=, Uint32ArraySetIndexed, 1455695417)                      \
-  V(_Float64Array, []=, Float64ArraySetIndexed, 1929239576)                    \
-  V(_Float64Array, [], Float64ArrayGetIndexed, 816943529)                      \
+  V(Uint32List, [], Uint32ArrayGetIndexed, 1179675338)                         \
+  V(Uint32List, []=, Uint32ArraySetIndexed, 1455695417)                        \
+  V(Float64List, []=, Float64ArraySetIndexed, 1929239576)                      \
+  V(Float64List, [], Float64ArrayGetIndexed, 816943529)                        \
   V(_TypedList, get:length, TypedDataLength, 546364442)                        \
-  V(_Float32x4, get:x, Float32x4ShuffleX, 1674625343)                          \
-  V(_Float32x4, get:y, Float32x4ShuffleY, 540293915)                           \
-  V(_Float32x4, get:z, Float32x4ShuffleZ, 320347578)                           \
-  V(_Float32x4, get:w, Float32x4ShuffleW, 1770606624)                          \
-  V(_Float32x4, _mul, Float32x4Mul, 861549065)                                 \
-  V(_Float32x4, _sub, Float32x4Sub, 460363214)                                 \
-  V(_Float32x4, _add, Float32x4Add, 1487592255)                                \
+  V(Float32x4, get:x, Float32x4ShuffleX, 1674625343)                           \
+  V(Float32x4, get:y, Float32x4ShuffleY, 540293915)                            \
+  V(Float32x4, get:z, Float32x4ShuffleZ, 320347578)                            \
+  V(Float32x4, get:w, Float32x4ShuffleW, 1770606624)                           \
+  V(Float32x4, _mul, Float32x4Mul, 861549065)                                  \
+  V(Float32x4, _sub, Float32x4Sub, 460363214)                                  \
+  V(Float32x4, _add, Float32x4Add, 1487592255)                                 \
 
 #define GRAPH_CORE_INTRINSICS_LIST(V)                                          \
   V(_List, get:length, ObjectArrayLength, 630471378)                           \
@@ -343,24 +343,24 @@
   V(_ImmutableList, [], ImmutableArrayGetIndexed, 360400496)                   \
   V(_GrowableList, [], GrowableArrayGetIndexed, 1957529650)                    \
   V(_GrowableList, []=, GrowableArraySetIndexed, 225246870)                    \
-  V(_Float32Array, [], Float32ArrayGetIndexed, 1002307136)                     \
-  V(_Float32Array, []=, Float32ArraySetIndexed, 279546769)                     \
-  V(_Float64Array, [], Float64ArrayGetIndexed, 816943529)                      \
-  V(_Float64Array, []=, Float64ArraySetIndexed, 1929239576)                    \
-  V(_Int8Array, [], Int8ArrayGetIndexed, 1141846285)                           \
-  V(_Int8Array, []=, Int8ArraySetIndexed, 1486839324)                          \
-  V(_Uint8Array, [], Uint8ArrayGetIndexed, 513704632)                          \
-  V(_Uint8Array, []=, Uint8ArraySetIndexed, 2123520783)                        \
-  V(_Uint8ClampedArray, [], Uint8ClampedArrayGetIndexed, 513704632)            \
-  V(_Uint8ClampedArray, []=, Uint8ClampedArraySetIndexed, 1015846567)          \
-  V(_Uint16Array, [], Uint16ArrayGetIndexed, 118958722)                        \
-  V(_Uint16Array, []=, Uint16ArraySetIndexed, 658824450)                       \
-  V(_Int16Array, [], Int16ArrayGetIndexed, 1826359619)                         \
-  V(_Int16Array, []=, Int16ArraySetIndexed, 1108689116)                        \
-  V(_Int32Array, [], Int32ArrayGetIndexed, 681203163)                          \
-  V(_Int32Array, []=, Int32ArraySetIndexed, 1786886245)                        \
-  V(_Int64Array, [], Int64ArrayGetIndexed, 1883155004)                         \
-  V(_Int64Array, []=, Int64ArraySetIndexed, 905815059)                         \
+  V(Float32List, [], Float32ArrayGetIndexed, 1002307136)                       \
+  V(Float32List, []=, Float32ArraySetIndexed, 279546769)                       \
+  V(Float64List, [], Float64ArrayGetIndexed, 816943529)                        \
+  V(Float64List, []=, Float64ArraySetIndexed, 1929239576)                      \
+  V(Int8List, [], Int8ArrayGetIndexed, 1141846285)                             \
+  V(Int8List, []=, Int8ArraySetIndexed, 1486839324)                            \
+  V(Uint8List, [], Uint8ArrayGetIndexed, 513704632)                            \
+  V(Uint8List, []=, Uint8ArraySetIndexed, 2123520783)                          \
+  V(Uint8ClampedList, [], Uint8ClampedArrayGetIndexed, 513704632)              \
+  V(Uint8ClampedList, []=, Uint8ClampedArraySetIndexed, 1015846567)            \
+  V(Uint16List, [], Uint16ArrayGetIndexed, 118958722)                          \
+  V(Uint16List, []=, Uint16ArraySetIndexed, 658824450)                         \
+  V(Int16List, [], Int16ArrayGetIndexed, 1826359619)                           \
+  V(Int16List, []=, Int16ArraySetIndexed, 1108689116)                          \
+  V(Int32List, [], Int32ArrayGetIndexed, 681203163)                            \
+  V(Int32List, []=, Int32ArraySetIndexed, 1786886245)                          \
+  V(Int64List, [], Int64ArrayGetIndexed, 1883155004)                           \
+  V(Int64List, []=, Int64ArraySetIndexed, 905815059)                           \
   V(_Uint8ArrayView, [], Uint8ArrayViewGetIndexed, 215420949)                  \
   V(_Uint8ArrayView, []=, Uint8ArrayViewSetIndexed, 1138146450)                \
   V(_Int8ArrayView, [], Int8ArrayViewGetIndexed, 1003520035)                   \
@@ -412,20 +412,6 @@
   V(_HashVMBase, set:_hashMask, LinkedHashMap_setHashMask, 340628211)          \
   V(_HashVMBase, get:_deletedKeys, LinkedHashMap_getDeletedKeys, 1340385546)   \
   V(_HashVMBase, set:_deletedKeys, LinkedHashMap_setDeletedKeys, 638315987)    \
-  V(Uint8List, ., Uint8ListFactory, 1885328419)                                \
-  V(Int8List, ., Int8ListFactory, 551286096)                                   \
-  V(Uint16List, ., Uint16ListFactory, 2018994846)                              \
-  V(Int16List, ., Int16ListFactory, 1934285336)                                \
-  V(Uint32List, ., Uint32ListFactory, 990865607)                               \
-  V(Int32List, ., Int32ListFactory, 2017670015)                                \
-  V(Uint64List, ., Uint64ListFactory, 1593070032)                              \
-  V(Int64List, ., Int64ListFactory, 1071205588)                                \
-  V(Float32List, ., Float32ListFactory, 1015272745)                            \
-  V(Float64List, ., Float64ListFactory, 626315429)                             \
-  V(Int32x4List, ., Int32x4ListFactory, 1693091079)                            \
-  V(Float32x4List, ., Float32x4ListFactory, 585154381)                         \
-  V(Float64x2List, ., Float64x2ListFactory, 874435184)
-
 
 // A list of core function that should never be inlined.
 #define INLINE_BLACK_LIST(V)                                                   \
@@ -474,7 +460,7 @@
   enum Kind {
     kUnknown,
 #define DEFINE_ENUM_LIST(class_name, function_name, enum_name, fp) k##enum_name,
-RECOGNIZED_LIST(DEFINE_ENUM_LIST)
+    RECOGNIZED_LIST(DEFINE_ENUM_LIST)
 #undef DEFINE_ENUM_LIST
     kNumRecognizedMethods
   };
@@ -504,18 +490,18 @@
   V(_ListFactory, kArrayCid, 184405219)                                        \
   V(_GrowableListWithData, kGrowableObjectArrayCid, 131424500)                 \
   V(_GrowableListFactory, kGrowableObjectArrayCid, 664918385)                  \
-  V(_Int8ArrayFactory, kTypedDataInt8ArrayCid, 1058992179)                     \
-  V(_Uint8ArrayFactory, kTypedDataUint8ArrayCid, 1807546986)                   \
-  V(_Uint8ClampedArrayFactory, kTypedDataUint8ClampedArrayCid, 548459853)      \
-  V(_Int16ArrayFactory, kTypedDataInt16ArrayCid, 1796211480)                   \
-  V(_Uint16ArrayFactory, kTypedDataUint16ArrayCid, 1960868166)                 \
-  V(_Int32ArrayFactory, kTypedDataInt32ArrayCid, 372258367)                    \
-  V(_Uint32ArrayFactory, kTypedDataUint32ArrayCid, 1446612721)                 \
-  V(_Int64ArrayFactory, kTypedDataInt64ArrayCid, 964028713)                    \
-  V(_Uint64ArrayFactory, kTypedDataUint64ArrayCid, 721823156)                  \
-  V(_Float64ArrayFactory, kTypedDataFloat64ArrayCid, 42503976)                 \
-  V(_Float32ArrayFactory, kTypedDataFloat32ArrayCid, 392399264)                \
-  V(_Float32x4ArrayFactory, kTypedDataFloat32x4ArrayCid, 1960198693)           \
+  V(_Int8ArrayFactory, kTypedDataInt8ArrayCid, 779569635)                      \
+  V(_Uint8ArrayFactory, kTypedDataUint8ArrayCid, 1790399545)                   \
+  V(_Uint8ClampedArrayFactory, kTypedDataUint8ClampedArrayCid, 405875159)      \
+  V(_Int16ArrayFactory, kTypedDataInt16ArrayCid, 347431914)                    \
+  V(_Uint16ArrayFactory, kTypedDataUint16ArrayCid, 121990116)                  \
+  V(_Int32ArrayFactory, kTypedDataInt32ArrayCid, 1540657744)                   \
+  V(_Uint32ArrayFactory, kTypedDataUint32ArrayCid, 1012511652)                 \
+  V(_Int64ArrayFactory, kTypedDataInt64ArrayCid, 1473796807)                   \
+  V(_Uint64ArrayFactory, kTypedDataUint64ArrayCid, 738799620)                  \
+  V(_Float64ArrayFactory, kTypedDataFloat64ArrayCid, 1344005361)               \
+  V(_Float32ArrayFactory, kTypedDataFloat32ArrayCid, 1938690635)               \
+  V(_Float32x4ArrayFactory, kTypedDataFloat32x4ArrayCid, 2055067416)           \
 
 
 // Class that recognizes factories and returns corresponding result cid.
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 7b84774..8922db4 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -38,6 +38,7 @@
 #include "vm/symbols.h"
 #include "vm/tags.h"
 #include "vm/thread_registry.h"
+#include "vm/timeline.h"
 #include "vm/timer.h"
 #include "vm/unicode.h"
 #include "vm/verified_memory.h"
@@ -1104,7 +1105,7 @@
   ASSERT(isolate == thread->isolate());
 NOT_IN_PRODUCT(
   TimelineDurationScope tds(thread,
-                            isolate->GetIsolateStream(),
+                            Timeline::GetIsolateStream(),
                             "Object::Init");
 )
 
@@ -1149,8 +1150,6 @@
 
   // Setup type class early in the process.
   const Class& type_cls = Class::Handle(zone, Class::New<Type>());
-  const Class& function_type_cls = Class::Handle(zone,
-                                                 Class::New<FunctionType>());
   const Class& type_ref_cls = Class::Handle(zone, Class::New<TypeRef>());
   const Class& type_parameter_cls = Class::Handle(zone,
                                                   Class::New<TypeParameter>());
@@ -1272,8 +1271,8 @@
   pending_classes.Add(stacktrace_cls);
   // Super type set below, after Object is allocated.
 
-  cls = Class::New<JSRegExp>();
-  RegisterPrivateClass(cls, Symbols::JSSyntaxRegExp(), core_lib);
+  cls = Class::New<RegExp>();
+  RegisterPrivateClass(cls, Symbols::_RegExp(), core_lib);
   pending_classes.Add(cls);
 
   // Initialize the base interfaces used by the core VM classes.
@@ -1313,9 +1312,6 @@
   RegisterPrivateClass(type_cls, Symbols::Type(), core_lib);
   pending_classes.Add(type_cls);
 
-  RegisterPrivateClass(function_type_cls, Symbols::FunctionType(), core_lib);
-  pending_classes.Add(function_type_cls);
-
   RegisterPrivateClass(type_ref_cls, Symbols::TypeRef(), core_lib);
   pending_classes.Add(type_ref_cls);
 
@@ -1437,10 +1433,10 @@
   ASSERT(!lib.IsNull());
   ASSERT(lib.raw() == Library::TypedDataLibrary());
 #define REGISTER_TYPED_DATA_CLASS(clazz)                                       \
-  cls = Class::NewTypedDataClass(kTypedData##clazz##Cid);                      \
-  RegisterPrivateClass(cls, Symbols::_##clazz(), lib);                         \
+  cls = Class::NewTypedDataClass(kTypedData##clazz##ArrayCid);                 \
+  RegisterClass(cls, Symbols::clazz##List(), lib);                             \
 
-  CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_CLASS);
+  DART_CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_CLASS);
 #undef REGISTER_TYPED_DATA_CLASS
 #define REGISTER_TYPED_DATA_VIEW_CLASS(clazz)                                  \
   cls = Class::NewTypedDataViewClass(kTypedData##clazz##ViewCid);              \
@@ -1459,46 +1455,39 @@
   cls = Class::New<Instance>(kByteBufferCid);
   cls.set_instance_size(0);
   cls.set_next_field_offset(-kWordSize);
-  RegisterPrivateClass(cls, Symbols::_ByteBuffer(), lib);
+  RegisterClass(cls, Symbols::ByteBuffer(), lib);
   pending_classes.Add(cls);
 
   CLASS_LIST_TYPED_DATA(REGISTER_EXT_TYPED_DATA_CLASS);
 #undef REGISTER_EXT_TYPED_DATA_CLASS
   // Register Float32x4 and Int32x4 in the object store.
   cls = Class::New<Float32x4>();
-  object_store->set_float32x4_class(cls);
-  RegisterPrivateClass(cls, Symbols::_Float32x4(), lib);
-  cls = Class::New<Int32x4>();
-  object_store->set_int32x4_class(cls);
-  RegisterPrivateClass(cls, Symbols::_Int32x4(), lib);
-  cls = Class::New<Float64x2>();
-  object_store->set_float64x2_class(cls);
-  RegisterPrivateClass(cls, Symbols::_Float64x2(), lib);
-
-  cls = Class::New<Instance>(kIllegalCid);
   RegisterClass(cls, Symbols::Float32x4(), lib);
   cls.set_num_type_arguments(0);
   cls.set_num_own_type_arguments(0);
   cls.set_is_prefinalized();
   pending_classes.Add(cls);
+  object_store->set_float32x4_class(cls);
   type = Type::NewNonParameterizedType(cls);
   object_store->set_float32x4_type(type);
 
-  cls = Class::New<Instance>(kIllegalCid);
+  cls = Class::New<Int32x4>();
   RegisterClass(cls, Symbols::Int32x4(), lib);
   cls.set_num_type_arguments(0);
   cls.set_num_own_type_arguments(0);
   cls.set_is_prefinalized();
   pending_classes.Add(cls);
+  object_store->set_int32x4_class(cls);
   type = Type::NewNonParameterizedType(cls);
   object_store->set_int32x4_type(type);
 
-  cls = Class::New<Instance>(kIllegalCid);
+  cls = Class::New<Float64x2>();
   RegisterClass(cls, Symbols::Float64x2(), lib);
   cls.set_num_type_arguments(0);
   cls.set_num_own_type_arguments(0);
   cls.set_is_prefinalized();
   pending_classes.Add(cls);
+  object_store->set_float64x2_class(cls);
   type = Type::NewNonParameterizedType(cls);
   object_store->set_float64x2_type(type);
 
@@ -1639,7 +1628,6 @@
 
   cls = Class::New<LibraryPrefix>();
   cls = Class::New<Type>();
-  cls = Class::New<FunctionType>();
   cls = Class::New<TypeRef>();
   cls = Class::New<TypeParameter>();
   cls = Class::New<BoundedType>();
@@ -1722,7 +1710,7 @@
   cls = Class::New<ReceivePort>();
   cls = Class::New<SendPort>();
   cls = Class::New<Stacktrace>();
-  cls = Class::New<JSRegExp>();
+  cls = Class::New<RegExp>();
   cls = Class::New<Number>();
 
   cls = Class::New<WeakProperty>();
@@ -2432,10 +2420,10 @@
       break;
     }
     sup_type = cls.super_type();
-    // A BoundedType, TypeRef, or FunctionType can appear as type argument of
+    // A BoundedType, TypeRef, or function type can appear as type argument of
     // sup_type, but not as sup_type itself.
     ASSERT(sup_type.IsType());
-    sup_type = ClassFinalizer::ResolveTypeClass(cls, Type::Cast(sup_type));
+    ClassFinalizer::ResolveTypeClass(cls, Type::Cast(sup_type));
     cls = sup_type.type_class();
     ASSERT(!cls.IsTypedefClass());
   } while (true);
@@ -3193,8 +3181,54 @@
   if (FLAG_show_internal_names) {
     return Name();
   }
-NOT_IN_PRODUCT(
   switch (id()) {
+    case kFloat32x4Cid:
+      return Symbols::Float32x4().raw();
+    case kInt32x4Cid:
+      return Symbols::Int32x4().raw();
+    case kTypedDataInt8ArrayCid:
+    case kExternalTypedDataInt8ArrayCid:
+      return Symbols::Int8List().raw();
+    case kTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+      return Symbols::Uint8List().raw();
+    case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+      return Symbols::Uint8ClampedList().raw();
+    case kTypedDataInt16ArrayCid:
+    case kExternalTypedDataInt16ArrayCid:
+      return Symbols::Int16List().raw();
+    case kTypedDataUint16ArrayCid:
+    case kExternalTypedDataUint16ArrayCid:
+      return Symbols::Uint16List().raw();
+    case kTypedDataInt32ArrayCid:
+    case kExternalTypedDataInt32ArrayCid:
+      return Symbols::Int32List().raw();
+    case kTypedDataUint32ArrayCid:
+    case kExternalTypedDataUint32ArrayCid:
+      return Symbols::Uint32List().raw();
+    case kTypedDataInt64ArrayCid:
+    case kExternalTypedDataInt64ArrayCid:
+      return Symbols::Int64List().raw();
+    case kTypedDataUint64ArrayCid:
+    case kExternalTypedDataUint64ArrayCid:
+      return Symbols::Uint64List().raw();
+    case kTypedDataInt32x4ArrayCid:
+    case kExternalTypedDataInt32x4ArrayCid:
+      return Symbols::Int32x4List().raw();
+    case kTypedDataFloat32x4ArrayCid:
+    case kExternalTypedDataFloat32x4ArrayCid:
+      return Symbols::Float32x4List().raw();
+    case kTypedDataFloat64x2ArrayCid:
+    case kExternalTypedDataFloat64x2ArrayCid:
+      return Symbols::Float64x2List().raw();
+    case kTypedDataFloat32ArrayCid:
+    case kExternalTypedDataFloat32ArrayCid:
+      return Symbols::Float32List().raw();
+    case kTypedDataFloat64ArrayCid:
+    case kExternalTypedDataFloat64ArrayCid:
+      return Symbols::Float64List().raw();
+NOT_IN_PRODUCT(
     case kNullCid:
       return Symbols::Null().raw();
     case kDynamicCid:
@@ -3279,54 +3313,8 @@
     case kImmutableArrayCid:
     case kGrowableObjectArrayCid:
       return Symbols::List().raw();
-    case kFloat32x4Cid:
-      return Symbols::Float32x4().raw();
-    case kInt32x4Cid:
-      return Symbols::Int32x4().raw();
-    case kTypedDataInt8ArrayCid:
-    case kExternalTypedDataInt8ArrayCid:
-      return Symbols::Int8List().raw();
-    case kTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-      return Symbols::Uint8List().raw();
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-      return Symbols::Uint8ClampedList().raw();
-    case kTypedDataInt16ArrayCid:
-    case kExternalTypedDataInt16ArrayCid:
-      return Symbols::Int16List().raw();
-    case kTypedDataUint16ArrayCid:
-    case kExternalTypedDataUint16ArrayCid:
-      return Symbols::Uint16List().raw();
-    case kTypedDataInt32ArrayCid:
-    case kExternalTypedDataInt32ArrayCid:
-      return Symbols::Int32List().raw();
-    case kTypedDataUint32ArrayCid:
-    case kExternalTypedDataUint32ArrayCid:
-      return Symbols::Uint32List().raw();
-    case kTypedDataInt64ArrayCid:
-    case kExternalTypedDataInt64ArrayCid:
-      return Symbols::Int64List().raw();
-    case kTypedDataUint64ArrayCid:
-    case kExternalTypedDataUint64ArrayCid:
-      return Symbols::Uint64List().raw();
-    case kTypedDataInt32x4ArrayCid:
-    case kExternalTypedDataInt32x4ArrayCid:
-      return Symbols::Int32x4List().raw();
-    case kTypedDataFloat32x4ArrayCid:
-    case kExternalTypedDataFloat32x4ArrayCid:
-      return Symbols::Float32x4List().raw();
-    case kTypedDataFloat64x2ArrayCid:
-    case kExternalTypedDataFloat64x2ArrayCid:
-      return Symbols::Float64x2List().raw();
-    case kTypedDataFloat32ArrayCid:
-    case kExternalTypedDataFloat32ArrayCid:
-      return Symbols::Float32List().raw();
-    case kTypedDataFloat64ArrayCid:
-    case kExternalTypedDataFloat64ArrayCid:
-      return Symbols::Float64List().raw();
-  }
 )
+  }
   const String& name = String::Handle(Name());
   return String::ScrubName(name);
 }
@@ -3637,8 +3625,8 @@
 }
 
 
-bool Class::IsFunctionClass() const {
-  return raw() == Type::Handle(Type::Function()).type_class();
+bool Class::IsDartFunctionClass() const {
+  return raw() == Type::Handle(Type::DartFunctionType()).type_class();
 }
 
 
@@ -3716,7 +3704,7 @@
                                      bound_trail,
                                      space);
     }
-    if (other.IsFunctionClass()) {
+    if (other.IsDartFunctionClass()) {
       // Check if type S has a call() method.
       Function& function = Function::Handle(zone,
           thsi.LookupDynamicFunctionAllowAbstract(Symbols::Call()));
@@ -5438,12 +5426,12 @@
 }
 
 
-RawFunctionType* Function::SignatureType() const {
-  FunctionType& type = FunctionType::Handle();
+RawType* Function::SignatureType() const {
+  Type& type = Type::Handle();
   const Object& obj = Object::Handle(raw_ptr()->data_);
   if (IsSignatureFunction()) {
-    ASSERT(obj.IsNull() || obj.IsFunctionType());
-    type = obj.IsNull() ? FunctionType::null() : FunctionType::Cast(obj).raw();
+    ASSERT(obj.IsNull() || Type::Cast(obj).IsFunctionType());
+    type = obj.IsNull() ? Type::null() : Type::Cast(obj).raw();
   } else {
     ASSERT(IsClosureFunction());
     ASSERT(!obj.IsNull());
@@ -5479,18 +5467,15 @@
     const TypeArguments& signature_type_arguments =
         TypeArguments::Handle(scope_class.type_parameters());
     // Return the still unfinalized signature type.
-    type = FunctionType::New(scope_class,
-                             signature_type_arguments,
-                             *this,
-                             token_pos());
-
+    type = Type::New(scope_class, signature_type_arguments, token_pos());
+    type.set_signature(*this);
     SetSignatureType(type);
   }
   return type.raw();
 }
 
 
-void Function::SetSignatureType(const FunctionType& value) const {
+void Function::SetSignatureType(const Type& value) const {
   if (IsSignatureFunction()) {
     set_data(value);
   } else {
@@ -5625,7 +5610,7 @@
 //   invoke-field dispatcher: Array arguments descriptor
 //   redirecting constructor: RedirectionData
 //   closure function:        ClosureData
-//   irregexp function:       Array[0] = JSRegExp
+//   irregexp function:       Array[0] = RegExp
 //                            Array[1] = Smi string specialization cid
 //   native function:         Array[0] = String native name
 //                            Array[1] = Function implicit closure function
@@ -5659,10 +5644,10 @@
 }
 
 
-RawJSRegExp* Function::regexp() const {
+RawRegExp* Function::regexp() const {
   ASSERT(kind() == RawFunction::kIrregexpFunction);
   const Array& pair = Array::Cast(Object::Handle(raw_ptr()->data_));
-  return JSRegExp::RawCast(pair.At(0));
+  return RegExp::RawCast(pair.At(0));
 }
 
 
@@ -5673,7 +5658,7 @@
 }
 
 
-void Function::SetRegExpData(const JSRegExp& regexp,
+void Function::SetRegExpData(const RegExp& regexp,
                              intptr_t string_specialization_cid) const {
   ASSERT(kind() == RawFunction::kIrregexpFunction);
   ASSERT(RawObject::IsStringClassId(string_specialization_cid));
@@ -6159,9 +6144,9 @@
         String::Handle(UserVisibleName()).ToCString(),
         String::Handle(other.UserVisibleSignature()).ToCString(),
         String::Handle(other.UserVisibleName()).ToCString(),
-        String::Handle(FunctionType::Handle(
+        String::Handle(Type::Handle(
             SignatureType()).EnumerateURIs()).ToCString(),
-        String::Handle(FunctionType::Handle(
+        String::Handle(Type::Handle(
             other.SignatureType()).EnumerateURIs()).ToCString());
     return false;
   }
@@ -6597,8 +6582,7 @@
     param_name = ParameterNameAt(has_receiver - kClosure + i);
     closure_function.SetParameterNameAt(i, param_name);
   }
-  const FunctionType& signature_type =
-      FunctionType::Handle(closure_function.SignatureType());
+  const Type& signature_type = Type::Handle(closure_function.SignatureType());
   if (!signature_type.IsFinalized()) {
     ClassFinalizer::FinalizeType(
         Class::Handle(Owner()), signature_type, ClassFinalizer::kCanonicalize);
@@ -6673,13 +6657,6 @@
       pieces->Add(Symbols::LBrace());
     }
     for (intptr_t i = num_fixed_params; i < num_params; i++) {
-      // The parameter name of an optional positional parameter does not need
-      // to be part of the signature, since it is not used.
-      if (num_opt_named_params > 0) {
-        name = ParameterNameAt(i);
-        pieces->Add(name);
-        pieces->Add(Symbols::ColonSpace());
-      }
       param_type = ParameterTypeAt(i);
       if (instantiate &&
           param_type.IsFinalized() &&
@@ -6690,6 +6667,13 @@
       ASSERT(!param_type.IsNull());
       name = param_type.BuildName(name_visibility);
       pieces->Add(name);
+      // The parameter name of an optional positional parameter does not need
+      // to be part of the signature, since it is not used.
+      if (num_opt_named_params > 0) {
+        name = ParameterNameAt(i);
+        pieces->Add(Symbols::Blank());
+        pieces->Add(name);
+      }
       if (i != (num_params - 1)) {
         pieces->Add(Symbols::CommaSpace());
       }
@@ -6721,7 +6705,7 @@
 
 RawInstance* Function::ImplicitInstanceClosure(const Instance& receiver) const {
   ASSERT(IsImplicitClosureFunction());
-  const FunctionType& signature_type = FunctionType::Handle(SignatureType());
+  const Type& signature_type = Type::Handle(SignatureType());
   const Class& cls = Class::Handle(signature_type.type_class());
   const Context& context = Context::Handle(Context::New(1));
   context.SetAt(0, receiver);
@@ -7051,7 +7035,6 @@
       // This output can be copied into a file, then used with sed
       // to replace the old values.
       // sed -i .bak -f /tmp/newkeys runtime/vm/method_recognizer.h
-      // sed -i .bak -f /tmp/newkeys runtime/vm/flow_graph_builder.h
       THR_Print("s/V(%s, %d)/V(%s, %d)/\n",
                 prefix, fp, prefix, SourceFingerprint());
     } else {
@@ -7133,7 +7116,7 @@
 }
 
 
-void ClosureData::set_signature_type(const FunctionType& value) const {
+void ClosureData::set_signature_type(const Type& value) const {
   StorePointer(&raw_ptr()->signature_type_, value.raw());
 }
 
@@ -8807,6 +8790,10 @@
 
 RawString* Script::GetLine(intptr_t line_number, Heap::Space space) const {
   const String& src = String::Handle(Source());
+  if (src.IsNull()) {
+    ASSERT(Dart::IsRunningPrecompiledCode());
+    return Symbols::OptimizedOut().raw();
+  }
   intptr_t relative_line_number = line_number - line_offset();
   intptr_t current_line = 1;
   intptr_t line_start_idx = -1;
@@ -12095,6 +12082,7 @@
   StorePointer(&raw_ptr()->args_descriptor_, value.raw());
 }
 
+
 void ICData::set_deopt_id(intptr_t value) const {
   ASSERT(value <= kMaxInt32);
   StoreNonPointer(&raw_ptr()->deopt_id_, value);
@@ -12329,8 +12317,18 @@
     data_pos = 0;
   }
   data.SetAt(data_pos, Smi::Handle(Smi::New(receiver_class_id)));
-  data.SetAt(data_pos + 1, target);
-  data.SetAt(data_pos + 2, Smi::Handle(Smi::New(count)));
+  if (Isolate::Current()->compilation_allowed()) {
+    data.SetAt(data_pos + 1, target);
+    data.SetAt(data_pos + 2, Smi::Handle(Smi::New(count)));
+  } else {
+    // Precompilation only, after all functions have been compiled.
+    ASSERT(target.HasCode());
+    const Code& code = Code::Handle(target.CurrentCode());
+    const Smi& entry_point =
+        Smi::Handle(Smi::FromAlignedAddress(code.EntryPoint()));
+    data.SetAt(data_pos + 1, code);
+    data.SetAt(data_pos + 2, entry_point);
+  }
   // Multithreaded access to ICData requires setting of array to be the last
   // operation.
   set_ic_data_array(data);
@@ -12404,6 +12402,7 @@
 
 
 RawFunction* ICData::GetTargetAt(intptr_t index) const {
+  ASSERT(Isolate::Current()->compilation_allowed());
   const intptr_t data_pos = index * TestEntryLength() + NumArgsTested();
   ASSERT(Object::Handle(Array::Handle(ic_data()).At(data_pos)).IsFunction());
 
@@ -12413,6 +12412,15 @@
 }
 
 
+RawObject* ICData::GetTargetOrCodeAt(intptr_t index) const {
+  const intptr_t data_pos = index * TestEntryLength() + NumArgsTested();
+
+  NoSafepointScope no_safepoint;
+  RawArray* raw_data = ic_data();
+  return raw_data->ptr()->data()[data_pos];
+}
+
+
 void ICData::IncrementCountAt(intptr_t index, intptr_t value) const {
   ASSERT(0 <= value);
   ASSERT(value <= Smi::kMaxValue);
@@ -12432,6 +12440,7 @@
 
 
 intptr_t ICData::GetCountAt(intptr_t index) const {
+  ASSERT(Isolate::Current()->compilation_allowed());
   const Array& data = Array::Handle(ic_data());
   const intptr_t data_pos = index * TestEntryLength() +
       CountIndexFor(NumArgsTested());
@@ -12450,6 +12459,24 @@
 }
 
 
+void ICData::SetCodeAt(intptr_t index, const Code& value) const {
+  ASSERT(!Isolate::Current()->compilation_allowed());
+  const Array& data = Array::Handle(ic_data());
+  const intptr_t data_pos = index * TestEntryLength() +
+      CodeIndexFor(NumArgsTested());
+  data.SetAt(data_pos, value);
+}
+
+
+void ICData::SetEntryPointAt(intptr_t index, const Smi& value) const {
+  ASSERT(!Isolate::Current()->compilation_allowed());
+  const Array& data = Array::Handle(ic_data());
+  const intptr_t data_pos = index * TestEntryLength() +
+      EntryPointIndexFor(NumArgsTested());
+  data.SetAt(data_pos, value);
+}
+
+
 RawFunction* ICData::GetTargetForReceiverClassId(intptr_t class_id) const {
   const intptr_t len = NumberOfChecks();
   for (intptr_t i = 0; i < len; i++) {
@@ -14575,8 +14602,8 @@
   if (cls.IsClosureClass()) {
     const Function& signature =
         Function::Handle(Closure::Cast(*this).function());
-    FunctionType& type = FunctionType::Handle(signature.SignatureType());
-    if (type.scope_class() == cls.raw()) {
+    Type& type = Type::Handle(signature.SignatureType());
+    if (type.type_class() == cls.raw()) {
       // Type is not parameterized.
       if (!type.IsCanonical()) {
         type ^= type.Canonicalize();
@@ -14584,11 +14611,11 @@
       }
       return type.raw();
     }
-    const Class& scope_cls = Class::Handle(type.scope_class());
+    const Class& scope_cls = Class::Handle(type.type_class());
     ASSERT(scope_cls.NumTypeArguments() > 0);
     TypeArguments& type_arguments = TypeArguments::Handle(GetTypeArguments());
-    type = FunctionType::New(
-        scope_cls, type_arguments, signature, TokenPosition::kNoSource);
+    type = Type::New(scope_cls, type_arguments, TokenPosition::kNoSource);
+    type.set_signature(signature);
     type.SetIsFinalized();
     type ^= type.Canonicalize();
     return type.raw();
@@ -14668,13 +14695,13 @@
       if (!instantiated_other.IsFunctionType()) {
         return false;
       }
-      other_signature = FunctionType::Cast(instantiated_other).signature();
+      other_signature = Type::Cast(instantiated_other).signature();
       other_type_arguments = instantiated_other.arguments();
     } else {
       if (!other.IsFunctionType()) {
         return false;
       }
-      other_signature = FunctionType::Cast(other).signature();
+      other_signature = Type::Cast(other).signature();
       other_type_arguments = other.arguments();
     }
     const Function& signature =
@@ -14739,7 +14766,7 @@
         return true;
       }
       const Function& other_signature = Function::Handle(
-          zone, FunctionType::Cast(instantiated_other).signature());
+          zone, Type::Cast(instantiated_other).signature());
       if (call.IsSubtypeOf(type_arguments,
                            other_signature,
                            other_type_arguments,
@@ -15236,7 +15263,7 @@
   if (IsFunctionType()) {
     cls = type_class();
     const Function& signature_function = Function::Handle(
-        zone, FunctionType::Cast(*this).signature());
+        zone, Type::Cast(*this).signature());
     if (!cls.IsTypedefClass() ||
         (cls.signature_function() != signature_function.raw())) {
       if (!IsFinalized() || IsBeingFinalized() || IsMalformed()) {
@@ -15341,6 +15368,7 @@
 
 
 RawString* AbstractType::ClassName() const {
+  ASSERT(!IsFunctionType());
   if (HasResolvedTypeClass()) {
     return Class::Handle(type_class()).Name();
   } else {
@@ -15350,68 +15378,79 @@
 
 
 bool AbstractType::IsNullType() const {
-  return HasResolvedTypeClass() &&
+  return !IsFunctionType() &&
+      HasResolvedTypeClass() &&
       (type_class() == Isolate::Current()->object_store()->null_class());
 }
 
 
 bool AbstractType::IsBoolType() const {
-  return HasResolvedTypeClass() &&
+  return !IsFunctionType() &&
+      HasResolvedTypeClass() &&
       (type_class() == Isolate::Current()->object_store()->bool_class());
 }
 
 
 bool AbstractType::IsIntType() const {
-  return HasResolvedTypeClass() &&
+  return !IsFunctionType() &&
+      HasResolvedTypeClass() &&
       (type_class() == Type::Handle(Type::IntType()).type_class());
 }
 
 
 bool AbstractType::IsDoubleType() const {
-  return HasResolvedTypeClass() &&
+  return !IsFunctionType() &&
+      HasResolvedTypeClass() &&
       (type_class() == Type::Handle(Type::Double()).type_class());
 }
 
 
 bool AbstractType::IsFloat32x4Type() const {
-  return HasResolvedTypeClass() &&
+  return !IsFunctionType() &&
+      HasResolvedTypeClass() &&
       (type_class() == Type::Handle(Type::Float32x4()).type_class());
 }
 
 
 bool AbstractType::IsFloat64x2Type() const {
-  return HasResolvedTypeClass() &&
+  return !IsFunctionType() &&
+      HasResolvedTypeClass() &&
       (type_class() == Type::Handle(Type::Float64x2()).type_class());
 }
 
 
 bool AbstractType::IsInt32x4Type() const {
-  return HasResolvedTypeClass() &&
+  return !IsFunctionType() &&
+      HasResolvedTypeClass() &&
       (type_class() == Type::Handle(Type::Int32x4()).type_class());
 }
 
 
 bool AbstractType::IsNumberType() const {
-  return HasResolvedTypeClass() &&
+  return !IsFunctionType() &&
+      HasResolvedTypeClass() &&
       (type_class() == Type::Handle(Type::Number()).type_class());
 }
 
 
 bool AbstractType::IsSmiType() const {
-  return HasResolvedTypeClass() &&
+  return !IsFunctionType() &&
+      HasResolvedTypeClass() &&
       (type_class() == Type::Handle(Type::SmiType()).type_class());
 }
 
 
 bool AbstractType::IsStringType() const {
-  return HasResolvedTypeClass() &&
+  return !IsFunctionType() &&
+      HasResolvedTypeClass() &&
       (type_class() == Type::Handle(Type::StringType()).type_class());
 }
 
 
 bool AbstractType::IsDartFunctionType() const {
-  return HasResolvedTypeClass() &&
-      (type_class() == Type::Handle(Type::Function()).type_class());
+  return !IsFunctionType() &&
+      HasResolvedTypeClass() &&
+      (type_class() == Type::Handle(Type::DartFunctionType()).type_class());
 }
 
 
@@ -15509,7 +15548,7 @@
     // We may be checking bounds at finalization time and can encounter
     // a still unfinalized bound. Finalizing the bound here may lead to cycles.
     if (!bound.IsFinalized()) {
-      return false;    // TODO(regis): Return "maybe after instantiation".
+      return false;  // TODO(regis): Return "maybe after instantiation".
     }
     // The current bound_trail cannot be used, because operands are swapped and
     // the test is different anyway (more specific vs. subtype).
@@ -15530,10 +15569,10 @@
         return true;
       }
       const Function& other_fun =
-          Function::Handle(zone, FunctionType::Cast(other).signature());
+          Function::Handle(zone, Type::Cast(other).signature());
       // Check for two function types.
       const Function& fun =
-          Function::Handle(zone, FunctionType::Cast(*this).signature());
+          Function::Handle(zone, Type::Cast(*this).signature());
       return fun.TypeTest(test_kind,
                           TypeArguments::Handle(zone, arguments()),
                           other_fun,
@@ -15557,7 +15596,7 @@
           function.TypeTest(test_kind,
                             TypeArguments::Handle(zone, arguments()),
                             Function::Handle(
-                                zone, FunctionType::Cast(other).signature()),
+                                zone, Type::Cast(other).signature()),
                             TypeArguments::Handle(zone, other.arguments()),
                             bound_error,
                             space)) {
@@ -15667,7 +15706,7 @@
 }
 
 
-RawType* Type::Function() {
+RawType* Type::DartFunctionType() {
   return Isolate::Current()->object_store()->function_type();
 }
 
@@ -15699,6 +15738,13 @@
 }
 
 
+void Type::ResetIsFinalized() const {
+  ASSERT(IsFinalized());
+  set_type_state(RawType::kBeingFinalized);
+  SetIsFinalized();
+}
+
+
 void Type::SetIsBeingFinalized() const {
   ASSERT(IsResolved() && !IsFinalized() && !IsBeingFinalized());
   set_type_state(RawType::kBeingFinalized);
@@ -15706,31 +15752,40 @@
 
 
 bool Type::IsMalformed() const {
-  if (raw_ptr()->error_ == LanguageError::null()) {
-    return false;
+  if (raw_ptr()->sig_or_err_.error_ == LanguageError::null()) {
+    return false;  // Valid type, but not a function type.
   }
   const LanguageError& type_error = LanguageError::Handle(error());
+  if (type_error.IsNull()) {
+    return false;  // Valid function type.
+  }
   return type_error.kind() == Report::kMalformedType;
 }
 
 
 bool Type::IsMalbounded() const {
+  if (raw_ptr()->sig_or_err_.error_ == LanguageError::null()) {
+    return false;  // Valid type, but not a function type.
+  }
   if (!Isolate::Current()->type_checks()) {
     return false;
   }
-  if (raw_ptr()->error_ == LanguageError::null()) {
-    return false;
-  }
   const LanguageError& type_error = LanguageError::Handle(error());
+  if (type_error.IsNull()) {
+    return false;  // Valid function type.
+  }
   return type_error.kind() == Report::kMalboundedType;
 }
 
 
 bool Type::IsMalformedOrMalbounded() const {
-  if (raw_ptr()->error_ == LanguageError::null()) {
-    return false;
+  if (raw_ptr()->sig_or_err_.error_ == LanguageError::null()) {
+    return false;  // Valid type, but not a function type.
   }
   const LanguageError& type_error = LanguageError::Handle(error());
+  if (type_error.IsNull()) {
+    return false;  // Valid function type.
+  }
   if (type_error.kind() == Report::kMalformedType) {
     return true;
   }
@@ -15739,15 +15794,40 @@
 }
 
 
+RawLanguageError* Type::error() const {
+  const Object& type_error = Object::Handle(raw_ptr()->sig_or_err_.error_);
+  if (type_error.IsLanguageError()) {
+    return LanguageError::RawCast(type_error.raw());
+  }
+  return LanguageError::null();
+}
+
+
 void Type::set_error(const LanguageError& value) const {
-  StorePointer(&raw_ptr()->error_, value.raw());
+  StorePointer(&raw_ptr()->sig_or_err_.error_, value.raw());
+}
+
+
+RawFunction* Type::signature() const {
+  if (raw_ptr()->sig_or_err_.signature_ == Function::null()) {
+    return Function::null();
+  }
+  const Object& obj = Object::Handle(raw_ptr()->sig_or_err_.signature_);
+  if (obj.IsFunction()) {
+    return Function::RawCast(obj.raw());
+  }
+  ASSERT(obj.IsLanguageError());  // Type is malformed or malbounded.
+  return Function::null();
+}
+
+
+void Type::set_signature(const Function& value) const {
+  StorePointer(&raw_ptr()->sig_or_err_.signature_, value.raw());
 }
 
 
 void Type::SetIsResolved() const {
   ASSERT(!IsResolved());
-  // A Typedef is a FunctionType, not a type.
-  ASSERT(!Class::Handle(type_class()).IsTypedefClass());
   set_type_state(RawType::kResolved);
 }
 
@@ -15848,6 +15928,18 @@
   // with different instantiators. Allocate a new instantiated version of it.
   const Type& instantiated_type =
       Type::Handle(zone, Type::New(cls, type_arguments, token_pos(), space));
+  // Preserve the bound error if any.
+  if (IsMalbounded()) {
+    const LanguageError& bound_error = LanguageError::Handle(zone, error());
+    instantiated_type.set_error(bound_error);
+  }
+  // Preserve the signature if this type represents a function type.
+  // Note that the types in the signature remain unchanged. They get indirectly
+  // instantiated by instantiating the type arguments above.
+  const Function& sig_fun = Function::Handle(zone, signature());
+  if (!sig_fun.IsNull()) {
+    instantiated_type.set_signature(sig_fun);
+  }
   if (IsFinalized()) {
     instantiated_type.SetIsFinalized();
   } else {
@@ -15874,488 +15966,82 @@
     return false;
   }
   const Type& other_type = Type::Cast(other);
+  if (IsFunctionType() != other_type.IsFunctionType()) {
+    return false;
+  }
   ASSERT(IsResolved() && other_type.IsResolved());
   if (IsMalformed() || other_type.IsMalformed()) {
-    return false;
+    return false;  // Malformed types do not get canonicalized.
+  }
+  if (IsMalbounded() != other_type.IsMalbounded()) {
+    return false;  // Do not drop bound error.
   }
   if (type_class() != other_type.type_class()) {
     return false;
   }
   if (!IsFinalized() || !other_type.IsFinalized()) {
-    return false;
-  }
-  if (arguments() == other_type.arguments()) {
-    return true;
-  }
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-  const Class& cls = Class::Handle(zone, type_class());
-  const intptr_t num_type_params = cls.NumTypeParameters(thread);
-  if (num_type_params == 0) {
-    // Shortcut unnecessary handle allocation below.
-    return true;
-  }
-  const intptr_t num_type_args = cls.NumTypeArguments();
-  const intptr_t from_index = num_type_args - num_type_params;
-  const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
-  const TypeArguments& other_type_args = TypeArguments::Handle(
-      zone, other_type.arguments());
-  if (type_args.IsNull()) {
-    // Ignore from_index.
-    return other_type_args.IsRaw(0, num_type_args);
-  }
-  if (other_type_args.IsNull()) {
-    // Ignore from_index.
-    return type_args.IsRaw(0, num_type_args);
-  }
-  if (!type_args.IsSubvectorEquivalent(other_type_args,
-                                       from_index,
-                                       num_type_params)) {
-    return false;
-  }
-#ifdef DEBUG
-  if (from_index > 0) {
-    // Verify that the type arguments of the super class match, since they
-    // depend solely on the type parameters that were just verified to match.
-    ASSERT(type_args.Length() >= (from_index + num_type_params));
-    ASSERT(other_type_args.Length() >= (from_index + num_type_params));
-    AbstractType& type_arg = AbstractType::Handle(zone);
-    AbstractType& other_type_arg = AbstractType::Handle(zone);
-    for (intptr_t i = 0; i < from_index; i++) {
-      type_arg = type_args.TypeAt(i);
-      other_type_arg = other_type_args.TypeAt(i);
-      // Ignore bounds of bounded types.
-      while (type_arg.IsBoundedType()) {
-        type_arg = BoundedType::Cast(type_arg).type();
-      }
-      while (other_type_arg.IsBoundedType()) {
-        other_type_arg = BoundedType::Cast(other_type_arg).type();
-      }
-      ASSERT(type_arg.IsEquivalent(other_type_arg, trail));
-    }
-  }
-#endif
-  return true;
-}
-
-
-bool Type::IsRecursive() const {
-  return TypeArguments::Handle(arguments()).IsRecursive();
-}
-
-
-RawAbstractType* Type::CloneUnfinalized() const {
-  ASSERT(IsResolved());
-  if (IsFinalized()) {
-    return raw();
-  }
-  ASSERT(!IsMalformed());  // Malformed types are finalized.
-  ASSERT(!IsBeingFinalized());  // Cloning must occur prior to finalization.
-  TypeArguments& type_args = TypeArguments::Handle(arguments());
-  type_args = type_args.CloneUnfinalized();
-  const Type& clone = Type::Handle(
-      Type::New(Class::Handle(type_class()), type_args, token_pos()));
-  clone.SetIsResolved();
-  return clone.raw();
-}
-
-
-RawAbstractType* Type::CloneUninstantiated(const Class& new_owner,
-                                           TrailPtr trail) const {
-  ASSERT(IsFinalized());
-  ASSERT(!IsMalformed());
-  if (IsInstantiated()) {
-    return raw();
-  }
-  // We may recursively encounter a type already being cloned, because we clone
-  // the upper bounds of its uninstantiated type arguments in the same pass.
-  Type& clone = Type::Handle();
-  clone ^= OnlyBuddyInTrail(trail);
-  if (!clone.IsNull()) {
-    return clone.raw();
-  }
-  const Class& type_cls = Class::Handle(type_class());
-  clone = Type::New(type_cls, TypeArguments::Handle(), token_pos());
-  TypeArguments& type_args = TypeArguments::Handle(arguments());
-  // Upper bounds of uninstantiated type arguments may form a cycle.
-  if (type_args.IsRecursive() || !type_args.IsInstantiated()) {
-    AddOnlyBuddyToTrail(&trail, clone);
-  }
-  type_args = type_args.CloneUninstantiated(new_owner, trail);
-  clone.set_arguments(type_args);
-  clone.SetIsFinalized();
-  return clone.raw();
-}
-
-
-RawAbstractType* Type::Canonicalize(TrailPtr trail) const {
-  ASSERT(IsFinalized());
-  if (IsCanonical() || IsMalformed()) {
-    ASSERT(IsMalformed() || TypeArguments::Handle(arguments()).IsOld());
-    return this->raw();
-  }
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-  AbstractType& type = Type::Handle(zone);
-  const Class& cls = Class::Handle(zone, type_class());
-  ASSERT(!cls.IsTypedefClass());  // This type should be a FunctionType.
-  if (cls.raw() == Object::dynamic_class() && (isolate != Dart::vm_isolate())) {
-    return Object::dynamic_type().raw();
-  }
-  // Fast canonical lookup/registry for simple types.
-  if (!cls.IsGeneric() && !cls.IsClosureClass()) {
-    type = cls.CanonicalType();
-    if (type.IsNull()) {
-      ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate()));
-      // Canonicalize the type arguments of the supertype, if any.
-      TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
-      type_args = type_args.Canonicalize(trail);
-      if (IsCanonical()) {
-        // Canonicalizing type_args canonicalized this type.
-        ASSERT(IsRecursive());
-        return this->raw();
-      }
-      set_arguments(type_args);
-      type = cls.CanonicalType();  // May be set while canonicalizing type args.
-      if (type.IsNull()) {
-        MutexLocker ml(isolate->type_canonicalization_mutex());
-        // Recheck if type exists.
-        type = cls.CanonicalType();
-        if (type.IsNull()) {
-          SetCanonical();
-          cls.set_canonical_types(*this);
-          return this->raw();
-        }
-      }
-    }
-    ASSERT(this->Equals(type));
-    ASSERT(type.IsCanonical());
-    return type.raw();
-  }
-
-  Array& canonical_types = Array::Handle(zone);
-  canonical_types ^= cls.canonical_types();
-  if (canonical_types.IsNull()) {
-    canonical_types = empty_array().raw();
-  }
-  intptr_t length = canonical_types.Length();
-  // Linear search to see whether this type is already present in the
-  // list of canonicalized types.
-  // TODO(asiva): Try to re-factor this lookup code to make sharing
-  // easy between the 4 versions of this loop.
-  intptr_t index = 1;  // Slot 0 is reserved for CanonicalType().
-  while (index < length) {
-    type ^= canonical_types.At(index);
-    if (type.IsNull()) {
-      break;
-    }
-    ASSERT(type.IsFinalized());
-    if (this->Equals(type)) {
-      ASSERT(type.IsCanonical());
-      return type.raw();
-    }
-    index++;
-  }
-  // The type was not found in the table. It is not canonical yet.
-
-  // Canonicalize the type arguments.
-  TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
-  // In case the type is first canonicalized at runtime, its type argument
-  // vector may be longer than necessary. This is not an issue.
-  ASSERT(type_args.IsNull() || (type_args.Length() >= cls.NumTypeArguments()));
-  type_args = type_args.Canonicalize(trail);
-  if (IsCanonical()) {
-    // Canonicalizing type_args canonicalized this type as a side effect.
-    ASSERT(IsRecursive());
-    return this->raw();
-  }
-  set_arguments(type_args);
-  ASSERT(type_args.IsNull() || type_args.IsOld());
-
-  return cls.LookupOrAddCanonicalType(*this, index);
-}
-
-
-RawString* Type::EnumerateURIs() const {
-  if (IsDynamicType() || IsVoidType()) {
-    return Symbols::Empty().raw();
-  }
-  Zone* zone = Thread::Current()->zone();
-  GrowableHandlePtrArray<const String> pieces(zone, 6);
-  const Class& cls = Class::Handle(zone, type_class());
-  pieces.Add(Symbols::TwoSpaces());
-  pieces.Add(String::Handle(zone, cls.UserVisibleName()));
-  pieces.Add(Symbols::SpaceIsFromSpace());
-  const Library& library = Library::Handle(zone, cls.library());
-  pieces.Add(String::Handle(zone, library.url()));
-  pieces.Add(Symbols::NewLine());
-  const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
-  pieces.Add(String::Handle(zone, type_args.EnumerateURIs()));
-  return Symbols::FromConcatAll(pieces);
-}
-
-
-intptr_t Type::Hash() const {
-  ASSERT(IsFinalized());
-  uint32_t result = 1;
-  if (IsMalformed()) return result;
-  result = CombineHashes(result, Class::Handle(type_class()).id());
-  result = CombineHashes(result, TypeArguments::Handle(arguments()).Hash());
-  return FinalizeHash(result);
-}
-
-
-void Type::set_type_class(const Object& value) const {
-  ASSERT(!value.IsNull() && (value.IsClass() || value.IsUnresolvedClass()));
-  StorePointer(&raw_ptr()->type_class_, value.raw());
-}
-
-
-void Type::set_arguments(const TypeArguments& value) const {
-  ASSERT(!IsCanonical());
-  StorePointer(&raw_ptr()->arguments_, value.raw());
-}
-
-
-RawType* Type::New(Heap::Space space) {
-  RawObject* raw = Object::Allocate(Type::kClassId,
-                                    Type::InstanceSize(),
-                                    space);
-  return reinterpret_cast<RawType*>(raw);
-}
-
-
-RawType* Type::New(const Object& clazz,
-                   const TypeArguments& arguments,
-                   TokenPosition token_pos,
-                   Heap::Space space) {
-  const Type& result = Type::Handle(Type::New(space));
-  result.set_type_class(clazz);
-  result.set_arguments(arguments);
-  result.set_token_pos(token_pos);
-  result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated);
-  return result.raw();
-}
-
-
-void Type::set_token_pos(TokenPosition token_pos) const {
-  ASSERT(!token_pos.IsClassifying());
-  StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
-}
-
-
-void Type::set_type_state(int8_t state) const {
-  ASSERT((state >= RawType::kAllocated) &&
-         (state <= RawType::kFinalizedUninstantiated));
-  StoreNonPointer(&raw_ptr()->type_state_, state);
-}
-
-
-const char* Type::ToCString() const {
-  const char* unresolved = IsResolved() ? "" : "Unresolved ";
-  const TypeArguments& type_arguments = TypeArguments::Handle(arguments());
-  const char* class_name;
-  if (HasResolvedTypeClass()) {
-    class_name = String::Handle(
-        Class::Handle(type_class()).Name()).ToCString();
-  } else {
-    class_name = UnresolvedClass::Handle(unresolved_class()).ToCString();
-  }
-  if (type_arguments.IsNull()) {
-    return OS::SCreate(Thread::Current()->zone(),
-        "%sType: class '%s'", unresolved, class_name);
-  } else if (IsResolved() && IsFinalized() && IsRecursive()) {
-    const intptr_t hash = Hash();
-    const char* args_cstr = TypeArguments::Handle(arguments()).ToCString();
-    return OS::SCreate(Thread::Current()->zone(),
-        "Type: (@%p H%" Px ") class '%s', args:[%s]",
-        raw(), hash, class_name, args_cstr);
-  } else {
-    const char* args_cstr = TypeArguments::Handle(arguments()).ToCString();
-    return OS::SCreate(Thread::Current()->zone(),
-        "%sType: class '%s', args:[%s]", unresolved, class_name, args_cstr);
-  }
-}
-
-
-void FunctionType::SetIsFinalized() const {
-  ASSERT(!IsFinalized());
-  if (IsInstantiated()) {
-    set_type_state(RawFunctionType::kFinalizedInstantiated);
-  } else {
-    set_type_state(RawFunctionType::kFinalizedUninstantiated);
-  }
-}
-
-
-void FunctionType::ResetIsFinalized() const {
-  ASSERT(IsFinalized());
-  set_type_state(RawFunctionType::kBeingFinalized);
-  SetIsFinalized();
-}
-
-
-void FunctionType::SetIsBeingFinalized() const {
-  ASSERT(IsResolved() && !IsFinalized() && !IsBeingFinalized());
-  set_type_state(RawFunctionType::kBeingFinalized);
-}
-
-
-bool FunctionType::IsMalformed() const {
-  if (raw_ptr()->error_ == LanguageError::null()) {
-    return false;
-  }
-  const LanguageError& type_error = LanguageError::Handle(error());
-  return type_error.kind() == Report::kMalformedType;
-}
-
-
-bool FunctionType::IsMalbounded() const {
-  if (!Isolate::Current()->type_checks()) {
-    return false;
-  }
-  if (raw_ptr()->error_ == LanguageError::null()) {
-    return false;
-  }
-  const LanguageError& type_error = LanguageError::Handle(error());
-  return type_error.kind() == Report::kMalboundedType;
-}
-
-
-bool FunctionType::IsMalformedOrMalbounded() const {
-  if (raw_ptr()->error_ == LanguageError::null()) {
-    return false;
-  }
-  const LanguageError& type_error = LanguageError::Handle(error());
-  if (type_error.kind() == Report::kMalformedType) {
-    return true;
-  }
-  ASSERT(type_error.kind() == Report::kMalboundedType);
-  return Isolate::Current()->type_checks();
-}
-
-
-void FunctionType::set_error(const LanguageError& value) const {
-  StorePointer(&raw_ptr()->error_, value.raw());
-}
-
-
-void FunctionType::SetIsResolved() const {
-  ASSERT(!IsResolved());
-  set_type_state(RawFunctionType::kResolved);
-}
-
-
-bool FunctionType::IsInstantiated(TrailPtr trail) const {
-  if (raw_ptr()->type_state_ == RawFunctionType::kFinalizedInstantiated) {
-    return true;
-  }
-  if (raw_ptr()->type_state_ == RawFunctionType::kFinalizedUninstantiated) {
-    return false;
-  }
-  if (arguments() == TypeArguments::null()) {
-    return true;
-  }
-  const Class& scope_cls = Class::Handle(scope_class());
-  if (!scope_cls.IsGeneric()) {
-    ASSERT(scope_cls.IsClosureClass() || scope_cls.IsTypedefClass());
-    ASSERT(arguments() == TypeArguments::null());
-    return true;
-  }
-  const TypeArguments& type_arguments = TypeArguments::Handle(arguments());
-  const intptr_t num_type_args = scope_cls.NumTypeArguments();
-  const intptr_t num_type_params = scope_cls.NumTypeParameters();
-  // The vector may be longer than necessary. An empty vector is handled above.
-  ASSERT(type_arguments.Length() >= num_type_args);
-  return
-      (num_type_params == 0) ||
-      type_arguments.IsSubvectorInstantiated(num_type_args - num_type_params,
-                                             num_type_params);
-}
-
-
-RawAbstractType* FunctionType::InstantiateFrom(
-    const TypeArguments& instantiator_type_arguments,
-    Error* bound_error,
-    TrailPtr instantiation_trail,
-    TrailPtr bound_trail,
-    Heap::Space space) const {
-  Zone* zone = Thread::Current()->zone();
-  ASSERT(IsFinalized() || IsBeingFinalized());
-  ASSERT(!IsInstantiated());
-  ASSERT(!IsMalformed());  // FunctionType cannot be malformed.
-  // Instantiating this type with its own type arguments as instantiator can
-  // occur during finalization and bounds checking. Return the type unchanged.
-  if (arguments() == instantiator_type_arguments.raw()) {
-    return raw();
-  }
-  // Note that the scope class has to be resolved at this time, but not
-  // necessarily finalized yet. We may be checking bounds at compile time or
-  // finalizing the type argument vector of a recursive type.
-  const Class& cls = Class::Handle(zone, scope_class());
-  TypeArguments& type_arguments = TypeArguments::Handle(zone, arguments());
-  ASSERT(type_arguments.Length() == cls.NumTypeArguments());
-  type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments,
-                                                  bound_error,
-                                                  instantiation_trail,
-                                                  bound_trail,
-                                                  space);
-  // This uninstantiated type is not modified, as it can be instantiated
-  // with different instantiators. Allocate a new instantiated version of it.
-  const FunctionType& instantiated_type = FunctionType::Handle(zone,
-      FunctionType::New(cls,
-                        type_arguments,
-                        Function::Handle(zone, signature()),
-                        token_pos(),
-                        space));
-  if (IsFinalized()) {
-    instantiated_type.SetIsFinalized();
-  } else {
-    instantiated_type.SetIsResolved();
-  }
-  // Canonicalization is not part of instantiation.
-  return instantiated_type.raw();
-}
-
-
-bool FunctionType::IsEquivalent(const Instance& other, TrailPtr trail) const {
-  ASSERT(!IsNull());
-  if (raw() == other.raw()) {
-    return true;
-  }
-  if (!other.IsFunctionType()) {
-    return false;
-  }
-  const FunctionType& other_type = FunctionType::Cast(other);
-  ASSERT(IsResolved() && other_type.IsResolved());
-  if (IsMalformed() || other_type.IsMalformed()) {
-    return false;
-  }
-  if (scope_class() != other_type.scope_class()) {
-    return false;
+    return false;  // Too early to decide if equal.
   }
   if ((arguments() == other_type.arguments()) &&
       (signature() == other_type.signature())) {
     return true;
   }
-  if (!IsFinalized() || !other_type.IsFinalized()) {
-    return false;
-  }
-
-  // We do not instantiate the types of the signature. This happens on demand
-  // at runtime during a type test.
-  // Therefore, equal function types must have equal type arguments.
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
-  const TypeArguments& other_type_args = TypeArguments::Handle(
-      zone, other_type.arguments());
-  if (!type_args.Equals(other_type_args)) {
-    return false;
+  if (arguments() != other_type.arguments()) {
+  const Class& cls = Class::Handle(zone, type_class());
+    const intptr_t num_type_params = cls.NumTypeParameters(thread);
+    // Shortcut unnecessary handle allocation below if non-generic.
+    if (num_type_params > 0) {
+      const intptr_t num_type_args = cls.NumTypeArguments();
+      const intptr_t from_index = num_type_args - num_type_params;
+      const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
+      const TypeArguments& other_type_args = TypeArguments::Handle(
+          zone, other_type.arguments());
+      if (type_args.IsNull()) {
+        // Ignore from_index.
+        if (!other_type_args.IsRaw(0, num_type_args)) {
+          return false;
+        }
+      } else if (other_type_args.IsNull()) {
+        // Ignore from_index.
+        if (!type_args.IsRaw(0, num_type_args)) {
+          return false;
+        }
+      } else if (!type_args.IsSubvectorEquivalent(other_type_args,
+                                                  from_index,
+                                                  num_type_params)) {
+        return false;
+      }
+#ifdef DEBUG
+      if (from_index > 0) {
+        // Verify that the type arguments of the super class match, since they
+        // depend solely on the type parameters that were just verified to
+        // match.
+        ASSERT(type_args.Length() >= (from_index + num_type_params));
+        ASSERT(other_type_args.Length() >= (from_index + num_type_params));
+        AbstractType& type_arg = AbstractType::Handle(zone);
+        AbstractType& other_type_arg = AbstractType::Handle(zone);
+        for (intptr_t i = 0; i < from_index; i++) {
+          type_arg = type_args.TypeAt(i);
+          other_type_arg = other_type_args.TypeAt(i);
+          // Ignore bounds of bounded types.
+          while (type_arg.IsBoundedType()) {
+            type_arg = BoundedType::Cast(type_arg).type();
+          }
+          while (other_type_arg.IsBoundedType()) {
+            other_type_arg = BoundedType::Cast(other_type_arg).type();
+          }
+          ASSERT(type_arg.IsEquivalent(other_type_arg, trail));
+        }
+      }
+#endif
+    }
   }
-
-  // Type arguments are equal.
+  if (!IsFunctionType()) {
+    return true;
+  }
+  ASSERT(Type::Cast(other).IsFunctionType());
   // Equal function types must have equal signature types and equal optional
   // named arguments.
   if (signature() == other_type.signature()) {
@@ -16420,32 +16106,62 @@
 }
 
 
-bool FunctionType::IsRecursive() const {
+bool Type::IsRecursive() const {
   return TypeArguments::Handle(arguments()).IsRecursive();
 }
 
 
-RawAbstractType* FunctionType::CloneUnfinalized() const {
+RawAbstractType* Type::CloneUnfinalized() const {
   ASSERT(IsResolved());
   if (IsFinalized()) {
     return raw();
   }
   ASSERT(!IsMalformed());  // Malformed types are finalized.
   ASSERT(!IsBeingFinalized());  // Cloning must occur prior to finalization.
-  TypeArguments& type_args = TypeArguments::Handle(arguments());
-  type_args = type_args.CloneUnfinalized();
-  const FunctionType& clone = FunctionType::Handle(
-      FunctionType::New(Class::Handle(scope_class()),
-                        type_args,
-                        Function::Handle(signature()),
-                        token_pos()));
+  Zone* zone = Thread::Current()->zone();
+  const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
+  const TypeArguments& type_args_clone =
+      TypeArguments::Handle(zone, type_args.CloneUnfinalized());
+  if (type_args_clone.raw() == type_args.raw()) {
+    return raw();
+  }
+  const Type& clone = Type::Handle(zone,
+      Type::New(Class::Handle(zone, type_class()), type_args, token_pos()));
+  // Preserve the bound error if any.
+  if (IsMalbounded()) {
+    const LanguageError& bound_error = LanguageError::Handle(zone, error());
+    clone.set_error(bound_error);
+  }
+  // Clone the signature if this type represents a function type.
+  Function& fun = Function::Handle(zone, signature());
+  if (!fun.IsNull()) {
+    const Class& owner = Class::Handle(zone, fun.Owner());
+    Function& fun_clone = Function::Handle(zone,
+        Function::NewSignatureFunction(owner, TokenPosition::kNoSource));
+    AbstractType& type = AbstractType::Handle(zone, fun.result_type());
+    type = type.CloneUnfinalized();
+    fun_clone.set_result_type(type);
+    const intptr_t num_params = fun.NumParameters();
+    fun_clone.set_num_fixed_parameters(fun.num_fixed_parameters());
+    fun_clone.SetNumOptionalParameters(fun.NumOptionalParameters(),
+                                       fun.HasOptionalPositionalParameters());
+    fun_clone.set_parameter_types(Array::Handle(Array::New(num_params,
+                                                           Heap::kOld)));
+    for (intptr_t i = 0; i < num_params; i++) {
+      type = fun.ParameterTypeAt(i);
+      type = type.CloneUnfinalized();
+      fun_clone.SetParameterTypeAt(i, type);
+    }
+    fun_clone.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
+    clone.set_signature(fun_clone);
+  }
   clone.SetIsResolved();
   return clone.raw();
 }
 
 
-RawAbstractType* FunctionType::CloneUninstantiated(const Class& new_owner,
-                                                   TrailPtr trail) const {
+RawAbstractType* Type::CloneUninstantiated(const Class& new_owner,
+                                           TrailPtr trail) const {
   ASSERT(IsFinalized());
   ASSERT(!IsMalformed());
   if (IsInstantiated()) {
@@ -16453,16 +16169,42 @@
   }
   // We may recursively encounter a type already being cloned, because we clone
   // the upper bounds of its uninstantiated type arguments in the same pass.
-  FunctionType& clone = FunctionType::Handle();
+  Zone* zone = Thread::Current()->zone();
+  Type& clone = Type::Handle(zone);
   clone ^= OnlyBuddyInTrail(trail);
   if (!clone.IsNull()) {
     return clone.raw();
   }
-  clone = FunctionType::New(Class::Handle(scope_class()),
-                            TypeArguments::Handle(),
-                            Function::Handle(signature()),
-                            token_pos());
-  TypeArguments& type_args = TypeArguments::Handle(arguments());
+  const Class& type_cls = Class::Handle(zone, type_class());
+  clone = Type::New(type_cls, TypeArguments::Handle(zone), token_pos());
+  // Preserve the bound error if any.
+  if (IsMalbounded()) {
+    const LanguageError& bound_error = LanguageError::Handle(zone, error());
+    clone.set_error(bound_error);
+  }
+  // Clone the signature if this type represents a function type.
+  const Function& fun = Function::Handle(zone, signature());
+  if (!fun.IsNull()) {
+    Function& fun_clone = Function::Handle(zone,
+        Function::NewSignatureFunction(new_owner, TokenPosition::kNoSource));
+    AbstractType& type = AbstractType::Handle(zone, fun.result_type());
+    type = type.CloneUninstantiated(new_owner, trail);
+    fun_clone.set_result_type(type);
+    const intptr_t num_params = fun.NumParameters();
+    fun_clone.set_num_fixed_parameters(fun.num_fixed_parameters());
+    fun_clone.SetNumOptionalParameters(fun.NumOptionalParameters(),
+                                       fun.HasOptionalPositionalParameters());
+    fun_clone.set_parameter_types(Array::Handle(Array::New(num_params,
+                                                           Heap::kOld)));
+    for (intptr_t i = 0; i < num_params; i++) {
+      type = fun.ParameterTypeAt(i);
+      type = type.CloneUninstantiated(new_owner, trail);
+      fun_clone.SetParameterTypeAt(i, type);
+    }
+    fun_clone.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
+    clone.set_signature(fun_clone);
+  }
+  TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
   // Upper bounds of uninstantiated type arguments may form a cycle.
   if (type_args.IsRecursive() || !type_args.IsInstantiated()) {
     AddOnlyBuddyToTrail(&trail, clone);
@@ -16474,7 +16216,7 @@
 }
 
 
-RawAbstractType* FunctionType::Canonicalize(TrailPtr trail) const {
+RawAbstractType* Type::Canonicalize(TrailPtr trail) const {
   ASSERT(IsFinalized());
   if (IsCanonical() || IsMalformed()) {
     ASSERT(IsMalformed() || TypeArguments::Handle(arguments()).IsOld());
@@ -16482,10 +16224,46 @@
   }
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
+  Isolate* isolate = thread->isolate();
   AbstractType& type = Type::Handle(zone);
-  const Class& scope_cls = Class::Handle(zone, type_class());
+  const Class& cls = Class::Handle(zone, type_class());
+  if (cls.raw() == Object::dynamic_class() && (isolate != Dart::vm_isolate())) {
+    return Object::dynamic_type().raw();
+  }
+  // Fast canonical lookup/registry for simple types.
+  if (!cls.IsGeneric() && !cls.IsClosureClass()) {
+    ASSERT(!IsFunctionType() || cls.IsTypedefClass());
+    type = cls.CanonicalType();
+    if (type.IsNull()) {
+      ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate()));
+      // Canonicalize the type arguments of the supertype, if any.
+      TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
+      type_args = type_args.Canonicalize(trail);
+      if (IsCanonical()) {
+        // Canonicalizing type_args canonicalized this type.
+        ASSERT(IsRecursive());
+        return this->raw();
+      }
+      set_arguments(type_args);
+      type = cls.CanonicalType();  // May be set while canonicalizing type args.
+      if (type.IsNull()) {
+        MutexLocker ml(isolate->type_canonicalization_mutex());
+        // Recheck if type exists.
+        type = cls.CanonicalType();
+        if (type.IsNull()) {
+          SetCanonical();
+          cls.set_canonical_types(*this);
+          return this->raw();
+        }
+      }
+    }
+    ASSERT(this->Equals(type));
+    ASSERT(type.IsCanonical());
+    return type.raw();
+  }
+
   Array& canonical_types = Array::Handle(zone);
-  canonical_types ^= scope_cls.canonical_types();
+  canonical_types ^= cls.canonical_types();
   if (canonical_types.IsNull()) {
     canonical_types = empty_array().raw();
   }
@@ -16513,8 +16291,7 @@
   TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
   // In case the type is first canonicalized at runtime, its type argument
   // vector may be longer than necessary. This is not an issue.
-  ASSERT(type_args.IsNull() ||
-         (type_args.Length() >= scope_cls.NumTypeArguments()));
+  ASSERT(type_args.IsNull() || (type_args.Length() >= cls.NumTypeArguments()));
   type_args = type_args.Canonicalize(trail);
   if (IsCanonical()) {
     // Canonicalizing type_args canonicalized this type as a side effect.
@@ -16524,161 +16301,187 @@
     return this->raw();
   }
   set_arguments(type_args);
-
-  // Replace the actual function by a signature function.
-  const Function& fun = Function::Handle(zone, signature());
-  if (!fun.IsSignatureFunction()) {
-    Function& sig_fun = Function::Handle(zone,
-        Function::NewSignatureFunction(scope_cls, TokenPosition::kNoSource));
-    type = fun.result_type();
-    type = type.Canonicalize(trail);
-    sig_fun.set_result_type(type);
-    const intptr_t num_params = fun.NumParameters();
-    sig_fun.set_num_fixed_parameters(fun.num_fixed_parameters());
-    sig_fun.SetNumOptionalParameters(fun.NumOptionalParameters(),
-                                     fun.HasOptionalPositionalParameters());
-    sig_fun.set_parameter_types(Array::Handle(Array::New(num_params,
-                                                         Heap::kOld)));
-    for (intptr_t i = 0; i < num_params; i++) {
-      type = fun.ParameterTypeAt(i);
-      type = type.Canonicalize(trail);
-      sig_fun.SetParameterTypeAt(i, type);
-    }
-    sig_fun.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
-    set_signature(sig_fun);
-  }
   ASSERT(type_args.IsNull() || type_args.IsOld());
 
-  return scope_cls.LookupOrAddCanonicalType(*this, index);
+  // In case of a function type, replace the actual function by a signature
+  // function.
+  if (IsFunctionType()) {
+    const Function& fun = Function::Handle(zone, signature());
+    if (!fun.IsSignatureFunction()) {
+      Function& sig_fun = Function::Handle(zone,
+          Function::NewSignatureFunction(cls, TokenPosition::kNoSource));
+      type = fun.result_type();
+      type = type.Canonicalize(trail);
+      sig_fun.set_result_type(type);
+      const intptr_t num_params = fun.NumParameters();
+      sig_fun.set_num_fixed_parameters(fun.num_fixed_parameters());
+      sig_fun.SetNumOptionalParameters(fun.NumOptionalParameters(),
+                                       fun.HasOptionalPositionalParameters());
+      sig_fun.set_parameter_types(Array::Handle(Array::New(num_params,
+                                                           Heap::kOld)));
+      for (intptr_t i = 0; i < num_params; i++) {
+        type = fun.ParameterTypeAt(i);
+        type = type.Canonicalize(trail);
+        sig_fun.SetParameterTypeAt(i, type);
+      }
+      sig_fun.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
+      set_signature(sig_fun);
+    }
+  }
+  return cls.LookupOrAddCanonicalType(*this, index);
 }
 
 
-RawString* FunctionType::EnumerateURIs() const {
-  Zone* zone = Thread::Current()->zone();
-  // The scope class and type arguments do not appear explicitly in the user
-  // visible name. The type arguments were used to instantiate the function type
-  // prior to this call.
-  const Function& sig_fun = Function::Handle(zone, signature());
-  AbstractType& type = AbstractType::Handle(zone);
-  const intptr_t num_params = sig_fun.NumParameters();
-  GrowableHandlePtrArray<const String> pieces(zone, num_params + 1);
-  for (intptr_t i = 0; i < num_params; i++) {
-    type = sig_fun.ParameterTypeAt(i);
-    pieces.Add(String::Handle(zone, type.EnumerateURIs()));
+RawString* Type::EnumerateURIs() const {
+  if (IsDynamicType() || IsVoidType()) {
+    return Symbols::Empty().raw();
   }
-  // Handle result type last, since it appears last in the user visible name.
-  type = sig_fun.result_type();
-  pieces.Add(String::Handle(zone, type.EnumerateURIs()));
+  Zone* zone = Thread::Current()->zone();
+  GrowableHandlePtrArray<const String> pieces(zone, 6);
+  if (IsFunctionType()) {
+    // The scope class and type arguments do not appear explicitly in the user
+    // visible name. The type arguments were used to instantiate the function
+    // type prior to this call.
+    const Function& sig_fun = Function::Handle(zone, signature());
+    AbstractType& type = AbstractType::Handle(zone);
+    const intptr_t num_params = sig_fun.NumParameters();
+    GrowableHandlePtrArray<const String> pieces(zone, num_params + 1);
+    for (intptr_t i = 0; i < num_params; i++) {
+      type = sig_fun.ParameterTypeAt(i);
+      pieces.Add(String::Handle(zone, type.EnumerateURIs()));
+    }
+    // Handle result type last, since it appears last in the user visible name.
+    type = sig_fun.result_type();
+    pieces.Add(String::Handle(zone, type.EnumerateURIs()));
+  } else {
+    const Class& cls = Class::Handle(zone, type_class());
+    pieces.Add(Symbols::TwoSpaces());
+    pieces.Add(String::Handle(zone, cls.UserVisibleName()));
+    pieces.Add(Symbols::SpaceIsFromSpace());
+    const Library& library = Library::Handle(zone, cls.library());
+    pieces.Add(String::Handle(zone, library.url()));
+    pieces.Add(Symbols::NewLine());
+    const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
+    pieces.Add(String::Handle(zone, type_args.EnumerateURIs()));
+  }
   return Symbols::FromConcatAll(pieces);
 }
 
 
-intptr_t FunctionType::Hash() const {
+intptr_t Type::Hash() const {
   ASSERT(IsFinalized());
   uint32_t result = 1;
   if (IsMalformed()) return result;
-  result = CombineHashes(result, Class::Handle(scope_class()).id());
+  result = CombineHashes(result, Class::Handle(type_class()).id());
   result = CombineHashes(result, TypeArguments::Handle(arguments()).Hash());
-  const Function& sig_fun = Function::Handle(signature());
-  AbstractType& type = AbstractType::Handle(sig_fun.result_type());
-  result = CombineHashes(result, type.Hash());
-  result = CombineHashes(result, sig_fun.NumOptionalPositionalParameters());
-  const intptr_t num_params = sig_fun.NumParameters();
-  for (intptr_t i = 0; i < num_params; i++) {
-    type = sig_fun.ParameterTypeAt(i);
+  if (IsFunctionType()) {
+    const Function& sig_fun = Function::Handle(signature());
+    AbstractType& type = AbstractType::Handle(sig_fun.result_type());
     result = CombineHashes(result, type.Hash());
-  }
-  if (sig_fun.NumOptionalNamedParameters() > 0) {
-    String& param_name = String::Handle();
-    for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) {
-      param_name = sig_fun.ParameterNameAt(i);
-      result = CombineHashes(result, param_name.Hash());
+    result = CombineHashes(result, sig_fun.NumOptionalPositionalParameters());
+    const intptr_t num_params = sig_fun.NumParameters();
+    for (intptr_t i = 0; i < num_params; i++) {
+      type = sig_fun.ParameterTypeAt(i);
+      result = CombineHashes(result, type.Hash());
+    }
+    if (sig_fun.NumOptionalNamedParameters() > 0) {
+      String& param_name = String::Handle();
+      for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) {
+        param_name = sig_fun.ParameterNameAt(i);
+        result = CombineHashes(result, param_name.Hash());
+      }
     }
   }
   return FinalizeHash(result);
 }
 
 
-void FunctionType::set_scope_class(const Class& value) const {
-  ASSERT(!value.IsNull());
-  StorePointer(&raw_ptr()->scope_class_, value.raw());
+void Type::set_type_class(const Object& value) const {
+  ASSERT(!value.IsNull() && (value.IsClass() || value.IsUnresolvedClass()));
+  StorePointer(&raw_ptr()->type_class_, value.raw());
 }
 
 
-void FunctionType::set_arguments(const TypeArguments& value) const {
+void Type::set_arguments(const TypeArguments& value) const {
   ASSERT(!IsCanonical());
   StorePointer(&raw_ptr()->arguments_, value.raw());
 }
 
 
-void FunctionType::set_signature(const Function& value) const {
-  StorePointer(&raw_ptr()->signature_, value.raw());
-}
-
-
-RawFunctionType* FunctionType::New(Heap::Space space) {
-  RawObject* raw = Object::Allocate(FunctionType::kClassId,
-                                    FunctionType::InstanceSize(),
+RawType* Type::New(Heap::Space space) {
+  RawObject* raw = Object::Allocate(Type::kClassId,
+                                    Type::InstanceSize(),
                                     space);
-  return reinterpret_cast<RawFunctionType*>(raw);
+  return reinterpret_cast<RawType*>(raw);
 }
 
 
-RawFunctionType* FunctionType::New(const Class& clazz,
-                                   const TypeArguments& arguments,
-                                   const Function& signature,
-                                   TokenPosition token_pos,
-                                   Heap::Space space) {
-  const FunctionType& result = FunctionType::Handle(FunctionType::New(space));
-  result.set_scope_class(clazz);
+RawType* Type::New(const Object& clazz,
+                   const TypeArguments& arguments,
+                   TokenPosition token_pos,
+                   Heap::Space space) {
+  const Type& result = Type::Handle(Type::New(space));
+  result.set_type_class(clazz);
   result.set_arguments(arguments);
-  result.set_signature(signature);
   result.set_token_pos(token_pos);
-  result.StoreNonPointer(&result.raw_ptr()->type_state_,
-                         RawFunctionType::kAllocated);
+  result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated);
   return result.raw();
 }
 
 
-void FunctionType::set_token_pos(TokenPosition token_pos) const {
+void Type::set_token_pos(TokenPosition token_pos) const {
   ASSERT(!token_pos.IsClassifying());
   StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
 }
 
 
-void FunctionType::set_type_state(int8_t state) const {
-  ASSERT((state >= RawFunctionType::kAllocated) &&
-         (state <= RawFunctionType::kFinalizedUninstantiated));
+void Type::set_type_state(int8_t state) const {
+  ASSERT((state >= RawType::kAllocated) &&
+         (state <= RawType::kFinalizedUninstantiated));
   StoreNonPointer(&raw_ptr()->type_state_, state);
 }
 
 
-const char* FunctionType::ToCString() const {
+const char* Type::ToCString() const {
+  Zone* zone = Thread::Current()->zone();
   const char* unresolved = IsResolved() ? "" : "Unresolved ";
-  const Class& scope_cls = Class::Handle(scope_class());
-  const TypeArguments& type_arguments = TypeArguments::Handle(arguments());
-  const Function& signature_function = Function::Handle(signature());
-  const String& signature_string = IsFinalized() ?
-      String::Handle(
-          signature_function.InstantiatedSignatureFrom(type_arguments,
-                                                       kInternalName)) :
-      String::Handle(signature_function.Signature());
-  if (scope_cls.IsClosureClass()) {
-    ASSERT(arguments() == TypeArguments::null());
-    return OS::SCreate(
-        Thread::Current()->zone(),
-        "%sFunctionType: %s", unresolved, signature_string.ToCString());
+  const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
+  const char* args_cstr = type_args.IsNull() ? "null" : type_args.ToCString();
+  Class& cls = Class::Handle(zone);
+  const char* class_name;
+  if (HasResolvedTypeClass()) {
+    cls = type_class();
+    class_name = String::Handle(zone, cls.Name()).ToCString();
+  } else {
+    class_name = UnresolvedClass::Handle(zone, unresolved_class()).ToCString();
   }
-  const char* class_name = String::Handle(scope_cls.Name()).ToCString();
-  const char* args_cstr =
-      type_arguments.IsNull() ? "null" : type_arguments.ToCString();
-  return OS::SCreate(
-      Thread::Current()->zone(),
-      "%s FunctionType: %s (scope_cls: %s, args: %s)",
-      unresolved,
-      signature_string.ToCString(),
-      class_name,
-      args_cstr);
+  if (IsFunctionType()) {
+    const Function& sig_fun = Function::Handle(zone, signature());
+    const String& sig = IsFinalized() ?
+        String::Handle(zone, sig_fun.InstantiatedSignatureFrom(type_args,
+                                                               kInternalName)) :
+        String::Handle(zone, sig_fun.Signature());
+    if (cls.IsClosureClass()) {
+      ASSERT(type_args.IsNull());
+      return OS::SCreate(zone, "%sFunction Type: %s",
+                         unresolved, sig.ToCString());
+    }
+    return OS::SCreate(zone, "%s Function Type: %s (class: %s, args: %s)",
+                       unresolved,
+                       sig.ToCString(),
+                       class_name,
+                       args_cstr);
+  }
+  if (type_args.IsNull()) {
+    return OS::SCreate(zone, "%sType: class '%s'", unresolved, class_name);
+  } else if (IsResolved() && IsFinalized() && IsRecursive()) {
+    const intptr_t hash = Hash();
+    return OS::SCreate(zone, "Type: (@%p H%" Px ") class '%s', args:[%s]",
+                       raw(), hash, class_name, args_cstr);
+  } else {
+    return OS::SCreate(zone, "%sType: class '%s', args:[%s]",
+                       unresolved, class_name, args_cstr);
+  }
 }
 
 
@@ -17253,9 +17056,12 @@
   if (IsFinalized()) {
     return raw();
   }
-  AbstractType& bounded_type = AbstractType::Handle(type());
-
-  bounded_type = bounded_type.CloneUnfinalized();
+  const AbstractType& bounded_type = AbstractType::Handle(type());
+  const AbstractType& bounded_type_clone =
+      AbstractType::Handle(bounded_type.CloneUnfinalized());
+  if (bounded_type_clone.raw() == bounded_type.raw()) {
+    return raw();
+  }
   // No need to clone bound or type parameter, as they are not part of the
   // finalization state of this bounded type.
   return BoundedType::New(bounded_type,
@@ -21612,17 +21418,17 @@
 }
 
 
-void JSRegExp::set_pattern(const String& pattern) const {
+void RegExp::set_pattern(const String& pattern) const {
   StorePointer(&raw_ptr()->pattern_, pattern.raw());
 }
 
 
-void JSRegExp::set_function(intptr_t cid, const Function& value) const {
+void RegExp::set_function(intptr_t cid, const Function& value) const {
   StorePointer(FunctionAddr(cid), value.raw());
 }
 
 
-void JSRegExp::set_bytecode(bool is_one_byte, const TypedData& bytecode) const {
+void RegExp::set_bytecode(bool is_one_byte, const TypedData& bytecode) const {
   if (is_one_byte) {
     StorePointer(&raw_ptr()->one_byte_bytecode_, bytecode.raw());
   } else {
@@ -21631,16 +21437,16 @@
 }
 
 
-void JSRegExp::set_num_bracket_expressions(intptr_t value) const {
+void RegExp::set_num_bracket_expressions(intptr_t value) const {
   StoreSmi(&raw_ptr()->num_bracket_expressions_, Smi::New(value));
 }
 
 
-RawJSRegExp* JSRegExp::New(Heap::Space space) {
-  JSRegExp& result = JSRegExp::Handle();
+RawRegExp* RegExp::New(Heap::Space space) {
+  RegExp& result = RegExp::Handle();
   {
-    RawObject* raw = Object::Allocate(JSRegExp::kClassId,
-                                      JSRegExp::InstanceSize(),
+    RawObject* raw = Object::Allocate(RegExp::kClassId,
+                                      RegExp::InstanceSize(),
                                       space);
     NoSafepointScope no_safepoint;
     result ^= raw;
@@ -21652,21 +21458,21 @@
 }
 
 
-void* JSRegExp::GetDataStartAddress() const {
+void* RegExp::GetDataStartAddress() const {
   intptr_t addr = reinterpret_cast<intptr_t>(raw_ptr());
-  return reinterpret_cast<void*>(addr + sizeof(RawJSRegExp));
+  return reinterpret_cast<void*>(addr + sizeof(RawRegExp));
 }
 
 
-RawJSRegExp* JSRegExp::FromDataStartAddress(void* data) {
-  JSRegExp& regexp = JSRegExp::Handle();
-  intptr_t addr = reinterpret_cast<intptr_t>(data) - sizeof(RawJSRegExp);
+RawRegExp* RegExp::FromDataStartAddress(void* data) {
+  RegExp& regexp = RegExp::Handle();
+  intptr_t addr = reinterpret_cast<intptr_t>(data) - sizeof(RawRegExp);
   regexp ^= RawObject::FromAddr(addr);
   return regexp.raw();
 }
 
 
-const char* JSRegExp::Flags() const {
+const char* RegExp::Flags() const {
   switch (flags()) {
     case kGlobal | kIgnoreCase | kMultiLine :
     case kIgnoreCase | kMultiLine :
@@ -21684,14 +21490,14 @@
 }
 
 
-bool JSRegExp::CanonicalizeEquals(const Instance& other) const {
+bool RegExp::CanonicalizeEquals(const Instance& other) const {
   if (this->raw() == other.raw()) {
     return true;  // "===".
   }
-  if (other.IsNull() || !other.IsJSRegExp()) {
+  if (other.IsNull() || !other.IsRegExp()) {
     return false;
   }
-  const JSRegExp& other_js = JSRegExp::Cast(other);
+  const RegExp& other_js = RegExp::Cast(other);
   // Match the pattern.
   const String& str1 = String::Handle(pattern());
   const String& str2 = String::Handle(other_js.pattern());
@@ -21708,10 +21514,10 @@
 }
 
 
-const char* JSRegExp::ToCString() const {
+const char* RegExp::ToCString() const {
   const String& str = String::Handle(pattern());
   return OS::SCreate(Thread::Current()->zone(),
-      "JSRegExp: pattern=%s flags=%s", str.ToCString(), Flags());
+      "RegExp: pattern=%s flags=%s", str.ToCString(), Flags());
 }
 
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 78794a9..1ed09f7 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1102,7 +1102,7 @@
   bool IsObjectClass() const { return id() == kInstanceCid; }
 
   // Check if this class represents the 'Function' class.
-  bool IsFunctionClass() const;
+  bool IsDartFunctionClass() const;
 
   // Check if this class represents the 'Closure' class.
   bool IsClosureClass() const  { return id() == kClosureCid; }
@@ -1514,7 +1514,6 @@
   friend class Instance;
   friend class Object;
   friend class Type;
-  friend class FunctionType;
   friend class Intrinsifier;
   friend class Precompiler;
 };
@@ -1926,6 +1925,10 @@
   RawFunction* GetTargetAt(intptr_t index) const;
   RawFunction* GetTargetForReceiverClassId(intptr_t class_id) const;
 
+  RawObject* GetTargetOrCodeAt(intptr_t index) const;
+  void SetCodeAt(intptr_t index, const Code& value) const;
+  void SetEntryPointAt(intptr_t index, const Smi& value) const;
+
   void IncrementCountAt(intptr_t index, intptr_t value) const;
   void SetCountAt(intptr_t index, intptr_t value) const;
   intptr_t GetCountAt(intptr_t index) const;
@@ -1962,10 +1965,16 @@
   static intptr_t TargetIndexFor(intptr_t num_args) {
     return num_args;
   }
+  static intptr_t CodeIndexFor(intptr_t num_args) {
+    return num_args;
+  }
 
   static intptr_t CountIndexFor(intptr_t num_args) {
     return (num_args + 1);
   }
+  static intptr_t EntryPointIndexFor(intptr_t num_args) {
+    return (num_args + 1);
+  }
 
   bool IsUsedAt(intptr_t i) const;
 
@@ -2137,16 +2146,16 @@
 
   // Return the type of this function's signature. It may not be canonical yet.
   // For example, if this function has a signature of the form
-  // '(T, [b: B, c: C]) => R', where 'T' and 'R' are type parameters of the
+  // '(T, [B, C]) => R', where 'T' and 'R' are type parameters of the
   // owner class of this function, then its signature type is a parameterized
-  // FunctionType with uninstantiated type arguments 'T' and 'R' as elements of
+  // function type with uninstantiated type arguments 'T' and 'R' as elements of
   // its type argument vector.
-  RawFunctionType* SignatureType() const;
+  RawType* SignatureType() const;
 
   // Update the signature type (with a canonical version).
-  void SetSignatureType(const FunctionType& value) const;
+  void SetSignatureType(const Type& value) const;
 
-  // Build a string of the form 'C<T, R>(T, {b: B, c: C}) => R' representing the
+  // Build a string of the form 'C<T, R>(T, {B b, C c}) => R' representing the
   // internal signature of the given function. In this example, T and R are
   // type parameters of class C, the owner of the function.
   RawString* Signature() const {
@@ -2154,7 +2163,7 @@
     return BuildSignature(instantiate, kInternalName, TypeArguments::Handle());
   }
 
-  // Build a string of the form '(T, {b: B, c: C}) => R' representing the
+  // Build a string of the form '(T, {B b, C c}) => R' representing the
   // user visible signature of the given function. In this example, T and R are
   // type parameters of class C, the owner of the function, also called the
   // scope class of the function type.
@@ -2166,9 +2175,9 @@
         instantiate, kUserVisibleName, TypeArguments::Handle());
   }
 
-  // Build a string of the form '(A, {b: B, c: C}) => D' representing the
+  // Build a string of the form '(A, {B b, C c}) => D' representing the
   // signature of the given function, where all generic types (e.g. '<T, R>' in
-  // 'C<T, R>(T, {b: B, c: C}) => R') are instantiated using the given
+  // 'C<T, R>(T, {B b, C c}) => R') are instantiated using the given
   // instantiator type argument vector of a C instance (e.g. '<A, D>').
   RawString* InstantiatedSignatureFrom(const TypeArguments& instantiator,
                                        NameVisibility name_visibility) const {
@@ -2180,7 +2189,7 @@
   // does not involve generic parameter types or generic result type.
   bool HasInstantiatedSignature() const;
 
-  // Build a string of the form 'T, {b: B, c: C} representing the user
+  // Build a string of the form 'T, {B b, C c}' representing the user
   // visible formal parameters of the function.
   RawString* UserVisibleFormalParameters() const;
 
@@ -2189,9 +2198,9 @@
   RawScript* script() const;
   RawObject* RawOwner() const { return raw_ptr()->owner_; }
 
-  RawJSRegExp* regexp() const;
+  RawRegExp* regexp() const;
   intptr_t string_specialization_cid() const;
-  void SetRegExpData(const JSRegExp& regexp,
+  void SetRegExpData(const RegExp& regexp,
                      intptr_t string_specialization_cid) const;
 
   RawString* native_name() const;
@@ -2858,8 +2867,8 @@
   void set_parent_function(const Function& value) const;
 
   // Signature type of this closure function.
-  RawFunctionType* signature_type() const { return raw_ptr()->signature_type_; }
-  void set_signature_type(const FunctionType& value) const;
+  RawType* signature_type() const { return raw_ptr()->signature_type_; }
+  void set_signature_type(const Type& value) const;
 
   RawInstance* implicit_static_closure() const {
     return raw_ptr()->closure_;
@@ -5225,7 +5234,7 @@
   friend class Class;
   friend class Closure;
   friend class DeferredObject;
-  friend class JSRegExp;
+  friend class RegExp;
   friend class SnapshotWriter;
   friend class StubCode;
   friend class TypedDataView;
@@ -5320,6 +5329,9 @@
   virtual bool IsEquivalent(const Instance& other, TrailPtr trail = NULL) const;
   virtual bool IsRecursive() const;
 
+  // Check if this type represents a function type.
+  virtual bool IsFunctionType() const { return false; }
+
   // Instantiate this type using the given type argument vector.
   // Return a new type, or return 'this' if it is already instantiated.
   // If bound_error is not NULL, it may be set to reflect a bound error.
@@ -5395,7 +5407,9 @@
 
   // Check if this type represents the 'dynamic' type.
   bool IsDynamicType() const {
-    return HasResolvedTypeClass() && (type_class() == Object::dynamic_class());
+    return !IsFunctionType() &&
+        HasResolvedTypeClass() &&
+        (type_class() == Object::dynamic_class());
   }
 
   // Check if this type represents the 'Null' type.
@@ -5403,12 +5417,15 @@
 
   // Check if this type represents the 'void' type.
   bool IsVoidType() const {
-    return HasResolvedTypeClass() && (type_class() == Object::void_class());
+    return !IsFunctionType() &&
+        HasResolvedTypeClass() &&
+        (type_class() == Object::void_class());
   }
 
   bool IsObjectType() const {
-    return HasResolvedTypeClass() &&
-    Class::Handle(type_class()).IsObjectClass();
+    return !IsFunctionType() &&
+        HasResolvedTypeClass() &&
+        Class::Handle(type_class()).IsObjectClass();
   }
 
   // Check if this type represents the 'bool' type.
@@ -5496,6 +5513,7 @@
         (raw_ptr()->type_state_ == RawType::kFinalizedUninstantiated);
   }
   virtual void SetIsFinalized() const;
+  void ResetIsFinalized() const;  // Ignore current state and set again.
   virtual bool IsBeingFinalized() const {
     return raw_ptr()->type_state_ == RawType::kBeingFinalized;
   }
@@ -5503,7 +5521,7 @@
   virtual bool IsMalformed() const;
   virtual bool IsMalbounded() const;
   virtual bool IsMalformedOrMalbounded() const;
-  virtual RawLanguageError* error() const { return raw_ptr()->error_; }
+  virtual RawLanguageError* error() const;
   virtual void set_error(const LanguageError& value) const;
   virtual bool IsResolved() const {
     return raw_ptr()->type_state_ >= RawType::kResolved;
@@ -5519,6 +5537,12 @@
   virtual bool IsInstantiated(TrailPtr trail = NULL) const;
   virtual bool IsEquivalent(const Instance& other, TrailPtr trail = NULL) const;
   virtual bool IsRecursive() const;
+  // If signature is not null, this type represents a function type.
+  RawFunction* signature() const;
+  void set_signature(const Function& value) const;
+  virtual bool IsFunctionType() const {
+    return signature() != Function::null();
+  }
   virtual RawAbstractType* InstantiateFrom(
       const TypeArguments& instantiator_type_arguments,
       Error* bound_error,
@@ -5584,7 +5608,7 @@
   static RawType* ArrayType();
 
   // The 'Function' type.
-  static RawType* Function();
+  static RawType* DartFunctionType();
 
   // The finalized type of the given non-parameterized class.
   static RawType* NewNonParameterizedType(const Class& type_class);
@@ -5606,106 +5630,6 @@
 };
 
 
-// TODO(regis): FunctionType is very similar to Type. Instead of a separate
-// class FunctionType, we could consider an object of class Type as representing
-// a function type if it has a non-null function (signature) field.
-// In order to save space, we could reuse the error_ field? A malformed or
-// malbounded function type would lose its function reference, but the error
-// string would contain relevant info.
-
-// A FunctionType describes the signature of a function, i.e. the result type
-// and formal parameter types of the function, as well as the names of optional
-// named formal parameters.
-// If these types refer to type parameters of a class in scope, the function
-// type is generic. A generic function type may be instantiated by a type
-// argument vector.
-// Therefore, a FunctionType consists of a scope class, a type argument vector,
-// and a signature.
-// The scope class is either a generic class (or generic typedef) declaring the
-// type parameters referred to by the signature, or class _Closure in the
-// non-generic case (including the non-generic typedef case).
-// The type arguments specify an instantiation of the generic signature (null in
-// the non-generic case).
-// The signature is a reference to an actual closure function (kClosureFunction)
-// or to a signature function (kSignatureFunction).
-// Since typedefs cannot refer to themselves, directly or indirectly, a
-// FunctionType cannot be recursive. Only individual formal parameter types can.
-class FunctionType : public AbstractType {
- public:
-  virtual bool IsFinalized() const {
-    return
-        (raw_ptr()->type_state_ == RawFunctionType::kFinalizedInstantiated) ||
-        (raw_ptr()->type_state_ == RawFunctionType::kFinalizedUninstantiated);
-  }
-  virtual void SetIsFinalized() const;
-  void ResetIsFinalized() const;  // Ignore current state and set again.
-  virtual bool IsBeingFinalized() const {
-    return raw_ptr()->type_state_ == RawFunctionType::kBeingFinalized;
-  }
-  virtual void SetIsBeingFinalized() const;
-  virtual bool IsMalformed() const;
-  virtual bool IsMalbounded() const;
-  virtual bool IsMalformedOrMalbounded() const;
-  virtual RawLanguageError* error() const { return raw_ptr()->error_; }
-  virtual void set_error(const LanguageError& value) const;
-  virtual bool IsResolved() const {
-    return raw_ptr()->type_state_ >= RawFunctionType::kResolved;
-  }
-  virtual void SetIsResolved() const;
-  // The scope class of a FunctionType is always resolved. It has no actual
-  // type class. Returning false is important for the type testers to work, e.g.
-  // IsDynamicType(), IsBoolType(), etc...
-  virtual bool HasResolvedTypeClass() const { return false; }
-  // Return scope_class from virtual type_class() to factorize finalization
-  // with Type, also a parameterized type.
-  virtual RawClass* type_class() const { return scope_class(); }
-  RawClass* scope_class() const { return raw_ptr()->scope_class_; }
-  void set_scope_class(const Class& value) const;
-  virtual RawTypeArguments* arguments() const { return raw_ptr()->arguments_; }
-  virtual void set_arguments(const TypeArguments& value) const;
-  RawFunction* signature() const { return raw_ptr()->signature_; }
-  virtual TokenPosition token_pos() const { return raw_ptr()->token_pos_; }
-  virtual bool IsInstantiated(TrailPtr trail = NULL) const;
-  virtual bool IsEquivalent(const Instance& other, TrailPtr trail = NULL) const;
-  virtual bool IsRecursive() const;
-  virtual RawAbstractType* InstantiateFrom(
-      const TypeArguments& instantiator_type_arguments,
-      Error* malformed_error,
-      TrailPtr instantiation_trail,
-      TrailPtr bound_trail,
-      Heap::Space space) const;
-  virtual RawAbstractType* CloneUnfinalized() const;
-  virtual RawAbstractType* CloneUninstantiated(
-      const Class& new_owner,
-      TrailPtr trail = NULL) const;
-  virtual RawAbstractType* Canonicalize(TrailPtr trail = NULL) const;
-  virtual RawString* EnumerateURIs() const;
-
-  virtual intptr_t Hash() const;
-
-  static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(RawFunctionType));
-  }
-
-  static RawFunctionType* New(const Class& scope_class,
-                              const TypeArguments& arguments,
-                              const Function& signature,
-                              TokenPosition token_pos,
-                              Heap::Space space = Heap::kOld);
-
- private:
-  void set_signature(const Function& value) const;
-  void set_token_pos(TokenPosition token_pos) const;
-  void set_type_state(int8_t state) const;
-
-  static RawFunctionType* New(Heap::Space space = Heap::kOld);
-
-  FINAL_HEAP_OBJECT_IMPLEMENTATION(FunctionType, AbstractType);
-  friend class Class;
-  friend class TypeArguments;
-};
-
-
 // A TypeRef is used to break cycles in the representation of recursive types.
 // Its only field is the recursive AbstractType it refers to.
 // Note that the cycle always involves type arguments.
@@ -5728,7 +5652,6 @@
   }
   virtual bool IsResolved() const { return true; }
   virtual bool HasResolvedTypeClass() const {
-    // Returns false if the ref type is a function type.
     return AbstractType::Handle(type()).HasResolvedTypeClass();
   }
   RawAbstractType* type() const { return raw_ptr()->type_; }
@@ -6094,6 +6017,11 @@
     return reinterpret_cast<RawSmi*>(raw_smi);
   }
 
+  static RawSmi* FromAlignedAddress(uword address) {
+    ASSERT((address & kSmiTagMask) == kSmiTag);
+    return reinterpret_cast<RawSmi*>(address);
+  }
+
   static RawClass* Class();
 
   static intptr_t Value(const RawSmi* raw_smi) {
@@ -8110,7 +8038,7 @@
 
 
 // Internal JavaScript regular expression object.
-class JSRegExp : public Instance {
+class RegExp : public Instance {
  public:
   // Meaning of RegExType:
   // kUninitialized: the type of th regexp has not been initialized yet.
@@ -8164,13 +8092,13 @@
   static intptr_t function_offset(intptr_t cid) {
     switch (cid) {
       case kOneByteStringCid:
-        return OFFSET_OF(RawJSRegExp, one_byte_function_);
+        return OFFSET_OF(RawRegExp, one_byte_function_);
       case kTwoByteStringCid:
-        return OFFSET_OF(RawJSRegExp, two_byte_function_);
+        return OFFSET_OF(RawRegExp, two_byte_function_);
       case kExternalOneByteStringCid:
-         return OFFSET_OF(RawJSRegExp, external_one_byte_function_);
+         return OFFSET_OF(RawRegExp, external_one_byte_function_);
       case kExternalTwoByteStringCid:
-        return OFFSET_OF(RawJSRegExp, external_two_byte_function_);
+        return OFFSET_OF(RawRegExp, external_two_byte_function_);
     }
 
     UNREACHABLE();
@@ -8201,16 +8129,16 @@
   }
 
   void* GetDataStartAddress() const;
-  static RawJSRegExp* FromDataStartAddress(void* data);
+  static RawRegExp* FromDataStartAddress(void* data);
   const char* Flags() const;
 
   virtual bool CanonicalizeEquals(const Instance& other) const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(RawJSRegExp));
+    return RoundedAllocationSize(sizeof(RawRegExp));
   }
 
-  static RawJSRegExp* New(Heap::Space space = Heap::kNew);
+  static RawRegExp* New(Heap::Space space = Heap::kNew);
 
  private:
   void set_type(RegExType type) const {
@@ -8229,7 +8157,7 @@
     return FlagsBits::decode(raw_ptr()->type_flags_);
   }
 
-  FINAL_HEAP_OBJECT_IMPLEMENTATION(JSRegExp, Instance);
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(RegExp, Instance);
   friend class Class;
 };
 
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index 6c46997..145b84e 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -511,9 +511,13 @@
 };
 
 
-intptr_t ObjectGraph::Serialize(WriteStream* stream) {
+intptr_t ObjectGraph::Serialize(WriteStream* stream, bool collect_garbage) {
+  if (collect_garbage) {
+    isolate()->heap()->CollectAllGarbage();
+  }
   // Current encoding assumes objects do not move, so promote everything to old.
   isolate()->heap()->new_space()->Evacuate();
+
   WriteGraphVisitor visitor(isolate(), stream);
   stream->WriteUnsigned(kObjectAlignment);
   stream->WriteUnsigned(0);
diff --git a/runtime/vm/object_graph.h b/runtime/vm/object_graph.h
index 5187d5e..70091d6 100644
--- a/runtime/vm/object_graph.h
+++ b/runtime/vm/object_graph.h
@@ -94,8 +94,10 @@
 
   // Write the isolate's object graph to 'stream'. Smis and nulls are omitted.
   // Returns the number of nodes in the stream, including the root.
+  // If collect_garabage is false, the graph will include weakly-reachable
+  // objects.
   // TODO(koda): Document format; support streaming/chunking.
-  intptr_t Serialize(WriteStream* stream);
+  intptr_t Serialize(WriteStream* stream, bool collect_garbage);
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(ObjectGraph);
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index ba63134..d93391f 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -101,10 +101,19 @@
   jsobj.AddProperty("_implemented", is_implemented());
   jsobj.AddProperty("_patch", is_patch());
   jsobj.AddProperty("_traceAllocations", TraceAllocation(isolate));
+
   const Class& superClass = Class::Handle(SuperClass());
   if (!superClass.IsNull()) {
     jsobj.AddProperty("super", superClass);
   }
+  const AbstractType& superType = AbstractType::Handle(super_type());
+  if (!superType.IsNull()) {
+    jsobj.AddProperty("superType", superType);
+  }
+  const Type& mix = Type::Handle(mixin());
+  if (!mix.IsNull()) {
+    jsobj.AddProperty("mixin", mix);
+  }
   jsobj.AddProperty("library", Object::Handle(library()));
   const Script& script = Script::Handle(this->script());
   if (!script.IsNull()) {
@@ -1135,33 +1144,6 @@
 }
 
 
-void FunctionType::PrintJSONImpl(JSONStream* stream, bool ref) const {
-  JSONObject jsobj(stream);
-  PrintSharedInstanceJSON(&jsobj, ref);
-  jsobj.AddProperty("kind", "FunctionType");
-  if (IsCanonical()) {
-    const Class& scope_cls = Class::Handle(scope_class());
-    intptr_t id = scope_cls.FindCanonicalTypeIndex(*this);
-    ASSERT(id >= 0);
-    intptr_t cid = scope_cls.id();
-    jsobj.AddFixedServiceId("classes/%" Pd "/types/%" Pd "", cid, id);
-    jsobj.AddProperty("scopeClass", scope_cls);
-  } else {
-    jsobj.AddServiceId(*this);
-  }
-  const String& user_name = String::Handle(UserVisibleName());
-  const String& vm_name = String::Handle(Name());
-  AddNameProperties(&jsobj, user_name, vm_name);
-  if (ref) {
-    return;
-  }
-  const TypeArguments& typeArgs = TypeArguments::Handle(arguments());
-  if (!typeArgs.IsNull()) {
-    jsobj.AddProperty("typeArguments", typeArgs);
-  }
-}
-
-
 void TypeRef::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
   PrintSharedInstanceJSON(&jsobj, ref);
@@ -1536,7 +1518,7 @@
 }
 
 
-void JSRegExp::PrintJSONImpl(JSONStream* stream, bool ref) const {
+void RegExp::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
   PrintSharedInstanceJSON(&jsobj, ref);
   jsobj.AddProperty("kind", "RegExp");
diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc
index 5975735..03540bb 100644
--- a/runtime/vm/os_android.cc
+++ b/runtime/vm/os_android.cc
@@ -37,7 +37,7 @@
 class PerfCodeObserver : public CodeObserver {
  public:
   PerfCodeObserver() : out_file_(NULL) {
-    Dart_FileOpenCallback file_open = Isolate::file_open_callback();
+    Dart_FileOpenCallback file_open = Dart::file_open_callback();
     if (file_open == NULL) {
       return;
     }
@@ -48,7 +48,7 @@
   }
 
   ~PerfCodeObserver() {
-    Dart_FileCloseCallback file_close = Isolate::file_close_callback();
+    Dart_FileCloseCallback file_close = Dart::file_close_callback();
     if ((file_close == NULL) || (out_file_ == NULL)) {
       return;
     }
@@ -64,7 +64,7 @@
                       uword prologue_offset,
                       uword size,
                       bool optimized) {
-    Dart_FileWriteCallback file_write = Isolate::file_write_callback();
+    Dart_FileWriteCallback file_write = Dart::file_write_callback();
     if ((file_write == NULL) || (out_file_ == NULL)) {
       return;
     }
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index d97a3a7..edfb890 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -40,7 +40,7 @@
 class PerfCodeObserver : public CodeObserver {
  public:
   PerfCodeObserver() : out_file_(NULL) {
-    Dart_FileOpenCallback file_open = Isolate::file_open_callback();
+    Dart_FileOpenCallback file_open = Dart::file_open_callback();
     if (file_open == NULL) {
       return;
     }
@@ -51,7 +51,7 @@
   }
 
   ~PerfCodeObserver() {
-    Dart_FileCloseCallback file_close = Isolate::file_close_callback();
+    Dart_FileCloseCallback file_close = Dart::file_close_callback();
     if ((file_close == NULL) || (out_file_ == NULL)) {
       return;
     }
@@ -67,7 +67,7 @@
                       uword prologue_offset,
                       uword size,
                       bool optimized) {
-    Dart_FileWriteCallback file_write = Isolate::file_write_callback();
+    Dart_FileWriteCallback file_write = Dart::file_write_callback();
     if ((file_write == NULL) || (out_file_ == NULL)) {
       return;
     }
diff --git a/runtime/vm/os_thread.cc b/runtime/vm/os_thread.cc
index 0303161..b381692 100644
--- a/runtime/vm/os_thread.cc
+++ b/runtime/vm/os_thread.cc
@@ -8,6 +8,7 @@
 #include "vm/lockers.h"
 #include "vm/log.h"
 #include "vm/thread_interrupter.h"
+#include "vm/timeline.h"
 
 namespace dart {
 
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 9c4d714..315d5a1 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -35,6 +35,7 @@
 #include "vm/stack_frame.h"
 #include "vm/symbols.h"
 #include "vm/tags.h"
+#include "vm/timeline.h"
 #include "vm/timer.h"
 #include "vm/zone.h"
 
@@ -498,7 +499,7 @@
   VMTagScope tagScope(thread, VMTag::kCompileTopLevelTagId);
 #ifndef PRODUCT
   TimelineDurationScope tds(thread,
-                            thread->isolate()->GetCompilerStream(),
+                            Timeline::GetCompilerStream(),
                             "CompileTopLevel");
   if (tds.enabled()) {
     tds.SetNumArguments(1);
@@ -856,7 +857,7 @@
   const int64_t num_tokes_before = STAT_VALUE(thread, num_tokens_consumed);
 #ifndef PRODUCT
   TimelineDurationScope tds(thread,
-                            thread->isolate()->GetCompilerStream(),
+                            Timeline::GetCompilerStream(),
                             "ParseClass");
   if (tds.enabled()) {
     tds.SetNumArguments(1);
@@ -973,7 +974,7 @@
                       FLAG_profile_vm);
 #ifndef PRODUCT
   TimelineDurationScope tds(thread,
-                            thread->isolate()->GetCompilerStream(),
+                            Timeline::GetCompilerStream(),
                             "ParseFunction");
 #endif  // !PRODUCT
   ASSERT(thread->long_jump_base()->IsSafeToJump());
@@ -1926,8 +1927,8 @@
                                          TokenPosition::kNoSource));
       signature_function.set_result_type(result_type);
       AddFormalParamsToFunction(&func_params, signature_function);
-      FunctionType& signature_type =
-          FunctionType::ZoneHandle(Z, signature_function.SignatureType());
+      Type& signature_type =
+          Type::ZoneHandle(Z, signature_function.SignatureType());
       if (!is_top_level_) {
         signature_type ^= ClassFinalizer::FinalizeType(
             current_class(), signature_type, ClassFinalizer::kCanonicalize);
@@ -2317,7 +2318,7 @@
     // parameterized class, make sure that the receiver is captured as
     // instantiator.
     if (current_block_->scope->function_level() > 0) {
-      const FunctionType& signature_type = FunctionType::Handle(Z,
+      const Type& signature_type = Type::Handle(Z,
           implicit_closure_function.SignatureType());
       const Class& scope_class = Class::Handle(Z, signature_type.type_class());
       if (scope_class.IsGeneric()) {
@@ -6118,7 +6119,7 @@
 
 
 void Parser::CheckStack() {
-  volatile uword c_stack_pos = Isolate::GetCurrentStackPointer();
+  volatile uword c_stack_pos = Thread::GetCurrentStackPointer();
   volatile uword c_stack_base = OSThread::Current()->stack_base();
   volatile uword c_stack_limit =
       c_stack_base - OSThread::GetSpecifiedStackSize();
@@ -6579,8 +6580,7 @@
     AddFormalParamsToFunction(&closure_params, body);
 
     // Finalize function type.
-    FunctionType& signature_type =
-        FunctionType::Handle(Z, body.SignatureType());
+    Type& signature_type = Type::Handle(Z, body.SignatureType());
     signature_type ^= ClassFinalizer::FinalizeType(
         current_class(), signature_type, ClassFinalizer::kCanonicalize);
     body.SetSignatureType(signature_type);
@@ -6712,8 +6712,7 @@
     AddFormalParamsToFunction(&closure_params, closure);
 
     // Finalize function type.
-    FunctionType& signature_type =
-        FunctionType::Handle(Z, closure.SignatureType());
+    Type& signature_type = Type::Handle(Z, closure.SignatureType());
     signature_type ^= ClassFinalizer::FinalizeType(
         current_class(), signature_type, ClassFinalizer::kCanonicalize);
     closure.SetSignatureType(signature_type);
@@ -6848,8 +6847,7 @@
     AddFormalParamsToFunction(&closure_params, closure);
 
     // Finalize function type.
-    FunctionType& signature_type =
-        FunctionType::Handle(Z, closure.SignatureType());
+    Type& signature_type = Type::Handle(Z, closure.SignatureType());
     signature_type ^= ClassFinalizer::FinalizeType(
         current_class(), signature_type, ClassFinalizer::kCanonicalize);
     closure.SetSignatureType(signature_type);
@@ -7597,7 +7595,7 @@
   // passed as a function argument, or returned as a function result.
 
   LocalVariable* function_variable = NULL;
-  FunctionType& function_type = FunctionType::ZoneHandle(Z);
+  Type& function_type = Type::ZoneHandle(Z);
   if (variable_name != NULL) {
     // Since the function type depends on the signature of the closure function,
     // it cannot be determined before the formal parameter list of the closure
@@ -7606,10 +7604,10 @@
     // We temporarily use the Closure class as scope class.
     const Class& unknown_scope_class = Class::Handle(Z,
         I->object_store()->closure_class());
-    function_type = FunctionType::New(unknown_scope_class,
-                                      TypeArguments::Handle(Z),
-                                      function,
-                                      function_pos);
+    function_type = Type::New(unknown_scope_class,
+                              TypeArguments::Handle(Z),
+                              function_pos);
+    function_type.set_signature(function);
     function_type.SetIsFinalized();  // No finalization needed.
 
     // Add the function variable to the scope before parsing the function in
@@ -7637,8 +7635,7 @@
   INC_STAT(thread(), num_functions_parsed, 1);
 
   // Now that the local function has formal parameters, lookup the signature
-  FunctionType& signature_type =
-      FunctionType::ZoneHandle(Z, function.SignatureType());
+  Type& signature_type = Type::ZoneHandle(Z, function.SignatureType());
   signature_type ^= ClassFinalizer::FinalizeType(
       current_class(), signature_type, ClassFinalizer::kCanonicalize);
   function.SetSignatureType(signature_type);
@@ -7655,15 +7652,15 @@
     CaptureInstantiator();
   }
 
-  // A signature type itself cannot be malformed or malbounded, only its
+  // A local signature type itself cannot be malformed or malbounded, only its
   // signature function's result type or parameter types may be.
   ASSERT(!signature_type.IsMalformed());
   ASSERT(!signature_type.IsMalbounded());
 
   if (variable_name != NULL) {
     // Patch the function type of the variable now that the signature is known.
-    function_type.set_scope_class(
-        Class::Handle(Z, signature_type.scope_class()));
+    function_type.set_type_class(
+        Class::Handle(Z, signature_type.type_class()));
     function_type.set_arguments(
         TypeArguments::Handle(Z, signature_type.arguments()));
     ASSERT(function_type.signature() == function.raw());
@@ -13183,8 +13180,7 @@
   AddFormalParamsToFunction(&params, closure);
 
   // Finalize function type.
-  FunctionType& signature_type =
-      FunctionType::Handle(Z, closure.SignatureType());
+  Type& signature_type = Type::Handle(Z, closure.SignatureType());
   signature_type ^= ClassFinalizer::FinalizeType(
       current_class(), signature_type, ClassFinalizer::kCanonicalize);
   closure.SetSignatureType(signature_type);
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index 1d111dd..d357839 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -39,6 +39,7 @@
 #include "vm/resolver.h"
 #include "vm/symbols.h"
 #include "vm/tags.h"
+#include "vm/timeline.h"
 #include "vm/timer.h"
 
 namespace dart {
@@ -213,6 +214,7 @@
     DropLibraries();
 
     BindStaticCalls();
+    SwitchICCalls();
 
     DedupStackmaps();
     DedupStackmapLists();
@@ -311,7 +313,7 @@
     { "dart:isolate", "_SendPortImpl", "send" },
     { "dart:typed_data", "ByteData", "ByteData." },
     { "dart:typed_data", "ByteData", "ByteData._view" },
-    { "dart:typed_data", "_ByteBuffer", "_ByteBuffer._New" },
+    { "dart:typed_data", "ByteBuffer", "ByteBuffer._New" },
     { "dart:_vmservice", "::", "_registerIsolate" },
     { "dart:_vmservice", "::", "boot" },
     { "dart:developer", "Metrics", "_printMetrics" },
@@ -619,14 +621,10 @@
     AddTypesOf(cls);
     const TypeArguments& vector = TypeArguments::Handle(Z, abstype.arguments());
     AddTypeArguments(vector);
-  } else if (abstype.IsFunctionType()) {
-    const FunctionType& func_type = FunctionType::Cast(abstype);
-    const Class& cls = Class::Handle(Z, func_type.scope_class());
-    AddTypesOf(cls);
-    const Function& func = Function::Handle(Z, func_type.signature());
-    AddTypesOf(func);
-    const TypeArguments& vector = TypeArguments::Handle(Z, abstype.arguments());
-    AddTypeArguments(vector);
+    if (type.IsFunctionType()) {
+      const Function& func = Function::Handle(Z, type.signature());
+      AddTypesOf(func);
+    }
   } else if (abstype.IsBoundedType()) {
     AbstractType& type = AbstractType::Handle(Z);
     type = BoundedType::Cast(abstype).type();
@@ -845,7 +843,7 @@
         false,  // not abstract
         false,  // not external
         false,  // not native
-        Class::Handle(Type::Handle(Type::Function()).type_class()),
+        Class::Handle(Type::Handle(Type::DartFunctionType()).type_class()),
         fragment->token_pos()));
 
     func.set_result_type(Object::dynamic_type());
@@ -1655,6 +1653,84 @@
 }
 
 
+void Precompiler::SwitchICCalls() {
+  // 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
+  // array. Iterate all the object pools and rewrite the ic data from
+  // (cid, target function, count) to (cid, target code, entry point), and
+  // replace the ICLookupThroughFunction stub with ICLookupThroughCode.
+
+  class SwitchICCallsVisitor : public FunctionVisitor {
+   public:
+    explicit SwitchICCallsVisitor(Zone* zone) :
+        code_(Code::Handle(zone)),
+        pool_(ObjectPool::Handle(zone)),
+        entry_(Object::Handle(zone)),
+        ic_(ICData::Handle(zone)),
+        target_(Function::Handle(zone)),
+        target_code_(Code::Handle(zone)),
+        entry_point_(Smi::Handle(zone)) {
+    }
+
+    void VisitFunction(const Function& function) {
+      if (!function.HasCode()) {
+        ASSERT(function.HasImplicitClosureFunction());
+        return;
+      }
+
+      code_ = function.CurrentCode();
+      pool_ = code_.object_pool();
+      for (intptr_t i = 0; i < pool_.Length(); i++) {
+        if (pool_.InfoAt(i) != ObjectPool::kTaggedObject) continue;
+        entry_ = pool_.ObjectAt(i);
+        if (entry_.IsICData()) {
+          ic_ ^= entry_.raw();
+
+          // Only single check ICs are SwitchableCalls that use the ICLookup
+          // stubs. Some operators like + have ICData that check the types of
+          // arguments in addition to the receiver and use special stubs
+          // with fast paths for Smi operations.
+          if (ic_.NumArgsTested() != 1) continue;
+
+          for (intptr_t j = 0; j < ic_.NumberOfChecks(); j++) {
+            entry_ = ic_.GetTargetOrCodeAt(j);
+            if (entry_.IsFunction()) {
+              target_ ^= entry_.raw();
+              ASSERT(target_.HasCode());
+              target_code_ = target_.CurrentCode();
+              entry_point_ = Smi::FromAlignedAddress(target_code_.EntryPoint());
+              ic_.SetCodeAt(j, target_code_);
+              ic_.SetEntryPointAt(j, entry_point_);
+            } else {
+              // We've already seen and switched this ICData.
+              ASSERT(entry_.IsCode());
+            }
+          }
+        } else if (entry_.raw() ==
+                   StubCode::ICLookupThroughFunction_entry()->code()) {
+          target_code_ = StubCode::ICLookupThroughCode_entry()->code();
+          pool_.SetObjectAt(i, target_code_);
+        }
+      }
+    }
+
+   private:
+    Code& code_;
+    ObjectPool& pool_;
+    Object& entry_;
+    ICData& ic_;
+    Function& target_;
+    Code& target_code_;
+    Smi& entry_point_;
+  };
+
+  ASSERT(!I->compilation_allowed());
+  SwitchICCallsVisitor visitor(Z);
+  VisitFunctions(&visitor);
+}
+
+
 void Precompiler::DedupStackmaps() {
   class DedupStackmapsVisitor : public FunctionVisitor {
    public:
@@ -1981,7 +2057,7 @@
   bool is_compiled = false;
   Zone* const zone = thread()->zone();
 #ifndef PRODUCT
-  TimelineStream* compiler_timeline = isolate()->GetCompilerStream();
+  TimelineStream* compiler_timeline = Timeline::GetCompilerStream();
 #endif  // !PRODUCT
   CSTAT_TIMER_SCOPE(thread(), codegen_timer);
   HANDLESCOPE(thread());
@@ -2590,7 +2666,7 @@
 RawError* Precompiler::CompileFunction(Thread* thread,
                                        const Function& function) {
   VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId);
-  TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "Function", function);
+  TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "CompileFunction", function);
 
   CompilationPipeline* pipeline =
       CompilationPipeline::New(thread->zone(), function);
diff --git a/runtime/vm/precompiler.h b/runtime/vm/precompiler.h
index 31465f2..319eb34 100644
--- a/runtime/vm/precompiler.h
+++ b/runtime/vm/precompiler.h
@@ -318,6 +318,7 @@
   void DropLibraries();
 
   void BindStaticCalls();
+  void SwitchICCalls();
   void DedupStackmaps();
   void DedupStackmapLists();
   void DedupInstructions();
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 0d1ad84..f0014f4 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -307,6 +307,12 @@
 }
 
 
+bool SampleFilter::TaskFilterSample(Sample* sample) {
+  const intptr_t task = static_cast<intptr_t>(sample->thread_task());
+  return (task & thread_task_mask_) != 0;
+}
+
+
 ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate)
     : SampleVisitor(isolate) {
 }
@@ -844,6 +850,7 @@
 #endif
   sample->set_vm_tag(vm_tag);
   sample->set_user_tag(isolate->user_tag());
+  sample->set_thread_task(thread->task_kind());
   return sample;
 }
 
@@ -887,7 +894,7 @@
   }
 
   if (FLAG_profile_vm) {
-    uintptr_t sp = Isolate::GetCurrentStackPointer();
+    uintptr_t sp = Thread::GetCurrentStackPointer();
     uintptr_t fp = 0;
     uintptr_t pc = GetProgramCounter();
 
@@ -945,6 +952,11 @@
   ASSERT(os_thread != NULL);
   Isolate* isolate = thread->isolate();
 
+  // Thread is not doing VM work.
+  if (thread->task_kind() == Thread::kUnknownTask) {
+    return;
+  }
+
   if (StubCode::HasBeenInitialized() &&
       StubCode::InJumpToExceptionHandlerStub(state.pc)) {
     // The JumpToExceptionHandler stub manually adjusts the stack pointer,
@@ -985,9 +997,7 @@
     return;
   }
 
-  if (!thread->IsMutatorThread()) {
-    // Not a mutator thread.
-    // TODO(johnmccutchan): Profile all threads with an isolate.
+  if (thread->IsMutatorThread() && isolate->IsDeoptimizing()) {
     return;
   }
 
@@ -1015,7 +1025,9 @@
   // Increment counter for vm tag.
   VMTagCounters* counters = isolate->vm_tag_counters();
   ASSERT(counters != NULL);
-  counters->Increment(sample->vm_tag());
+  if (thread->IsMutatorThread()) {
+    counters->Increment(sample->vm_tag());
+  }
 
   ProfilerNativeStackWalker native_stack_walker(isolate,
                                                 sample,
@@ -1223,6 +1235,10 @@
       // Did not pass time filter.
       continue;
     }
+    if (!filter->TaskFilterSample(sample)) {
+      // Did not pass task filter.
+      continue;
+    }
     if (!filter->FilterSample(sample)) {
       // Did not pass filter.
       continue;
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index 0b1207f..1f65c91 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -91,11 +91,14 @@
 class SampleFilter : public ValueObject {
  public:
   SampleFilter(Isolate* isolate,
+               intptr_t thread_task_mask,
                int64_t time_origin_micros,
                int64_t time_extent_micros)
       : isolate_(isolate),
+        thread_task_mask_(thread_task_mask),
         time_origin_micros_(time_origin_micros),
         time_extent_micros_(time_extent_micros) {
+    ASSERT(thread_task_mask != 0);
     ASSERT(time_origin_micros_ >= -1);
     ASSERT(time_extent_micros_ >= -1);
   }
@@ -114,9 +117,12 @@
   // Returns |true| if |sample| passes the time filter.
   bool TimeFilterSample(Sample* sample);
 
+  // Returns |true| if |sample| passes the thread task filter.
+  bool TaskFilterSample(Sample* sample);
+
  private:
   Isolate* isolate_;
-
+  intptr_t thread_task_mask_;
   int64_t time_origin_micros_;
   int64_t time_extent_micros_;
 };
@@ -274,6 +280,14 @@
     state_ = ClassAllocationSampleBit::update(allocation_sample, state_);
   }
 
+  Thread::TaskKind thread_task() const {
+    return ThreadTaskBit::decode(state_);
+  }
+
+  void set_thread_task(Thread::TaskKind task) {
+    state_ = ThreadTaskBit::update(task, state_);
+  }
+
   bool is_continuation_sample() const {
     return ContinuationSampleBit::decode(state_);
   }
@@ -338,6 +352,8 @@
     kTruncatedTraceBit = 5,
     kClassAllocationSampleBit = 6,
     kContinuationSampleBit = 7,
+    kThreadTaskBit = 8,  // 4 bits.
+    kNextFreeBit = 12,
   };
   class HeadSampleBit : public BitField<uword, bool, kHeadSampleBit, 1> {};
   class LeafFrameIsDart :
@@ -352,6 +368,8 @@
       : public BitField<uword, bool, kClassAllocationSampleBit, 1> {};
   class ContinuationSampleBit
       : public BitField<uword, bool, kContinuationSampleBit, 1> {};
+  class ThreadTaskBit
+      : public BitField<uword, Thread::TaskKind, kThreadTaskBit, 4> {};
 
   int64_t timestamp_;
   ThreadId tid_;
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index 35fd771..09d4d43 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -2497,9 +2497,11 @@
 class NoAllocationSampleFilter : public SampleFilter {
  public:
   NoAllocationSampleFilter(Isolate* isolate,
+                           intptr_t thread_task_mask,
                            int64_t time_origin_micros,
                            int64_t time_extent_micros)
       : SampleFilter(isolate,
+                     thread_task_mask,
                      time_origin_micros,
                      time_extent_micros) {
   }
@@ -2518,6 +2520,7 @@
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
   NoAllocationSampleFilter filter(isolate,
+                                  Thread::kMutatorTask,
                                   time_origin_micros,
                                   time_extent_micros);
   const bool as_timeline = false;
@@ -2529,9 +2532,11 @@
  public:
   ClassAllocationSampleFilter(Isolate* isolate,
                               const Class& cls,
+                              intptr_t thread_task_mask,
                               int64_t time_origin_micros,
                               int64_t time_extent_micros)
       : SampleFilter(isolate,
+                     thread_task_mask,
                      time_origin_micros,
                      time_extent_micros),
         cls_(Class::Handle(cls.raw())) {
@@ -2557,6 +2562,7 @@
   Isolate* isolate = thread->isolate();
   ClassAllocationSampleFilter filter(isolate,
                                      cls,
+                                     Thread::kMutatorTask,
                                      time_origin_micros,
                                      time_extent_micros);
   const bool as_timeline = false;
@@ -2570,7 +2576,12 @@
                                         int64_t time_extent_micros) {
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
+  const intptr_t thread_task_mask = Thread::kMutatorTask |
+                                    Thread::kCompilerTask |
+                                    Thread::kSweeperTask |
+                                    Thread::kMarkerTask;
   NoAllocationSampleFilter filter(isolate,
+                                  thread_task_mask,
                                   time_origin_micros,
                                   time_extent_micros);
   const bool as_timeline = true;
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index 6f4e0ad..e1b28fe 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -201,6 +201,7 @@
                    int64_t time_origin_micros = -1,
                    int64_t time_extent_micros = -1)
       : SampleFilter(isolate,
+                     Thread::kMutatorTask,
                      time_origin_micros,
                      time_extent_micros),
         cid_(cid),
@@ -958,7 +959,7 @@
       Library::Handle(isolate->object_store()->typed_data_library());
 
   const Class& float32_list_class =
-      Class::Handle(GetClass(typed_data_library, "_Float32Array"));
+      Class::Handle(GetClass(typed_data_library, "Float32List"));
   EXPECT(!float32_list_class.IsNull());
 
   Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
@@ -990,8 +991,6 @@
 
     walker.Reset(Profile::kExclusiveCode);
     EXPECT(walker.Down());
-    EXPECT_STREQ("_Float32Array._Float32Array", walker.CurrentName());
-    EXPECT(walker.Down());
     EXPECT_STREQ("Float32List.Float32List", walker.CurrentName());
     EXPECT(walker.Down());
     EXPECT_STREQ("foo", walker.CurrentName());
@@ -2310,6 +2309,7 @@
   sample->Init(isolate,
                OS::GetCurrentMonotonicMicros(),
                OSThread::Current()->trace_id());
+  sample->set_thread_task(Thread::kMutatorTask);
 
   intptr_t i = 0;
   while (pc_offsets[i] != 0) {
@@ -2324,7 +2324,7 @@
     sample->SetAt(i, pc_offsets[i] + return_address_offset);
     i++;
   }
-  sample->SetAt(i, NULL);
+  sample->SetAt(i, 0);
 }
 
 
diff --git a/runtime/vm/random.cc b/runtime/vm/random.cc
index 6f1b6eb..5153ffe 100644
--- a/runtime/vm/random.cc
+++ b/runtime/vm/random.cc
@@ -3,8 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/random.h"
+#include "vm/dart.h"
 #include "vm/flags.h"
-#include "vm/isolate.h"
+#include "vm/os.h"
 
 namespace dart {
 
@@ -13,7 +14,7 @@
 Random::Random() {
   uint64_t seed = FLAG_random_seed;
   if (seed == 0) {
-    Dart_EntropySource callback = Isolate::entropy_source_callback();
+    Dart_EntropySource callback = Dart::entropy_source_callback();
     if (callback != NULL) {
       if (!callback(reinterpret_cast<uint8_t*>(&seed), sizeof(seed))) {
         // Callback failed. Reset the seed to 0.
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index d32b5ab..437ab7e 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -343,13 +343,6 @@
 }
 
 
-intptr_t RawFunctionType::VisitFunctionTypePointers(
-    RawFunctionType* raw_obj, ObjectPointerVisitor* visitor) {
-  visitor->VisitPointers(raw_obj->from(), raw_obj->to());
-  return FunctionType::InstanceSize();
-}
-
-
 intptr_t RawTypeRef::VisitTypeRefPointers(
     RawTypeRef* raw_obj, ObjectPointerVisitor* visitor) {
   visitor->VisitPointers(raw_obj->from(), raw_obj->to());
@@ -931,12 +924,12 @@
 }
 
 
-intptr_t RawJSRegExp::VisitJSRegExpPointers(RawJSRegExp* raw_obj,
-                                            ObjectPointerVisitor* visitor) {
+intptr_t RawRegExp::VisitRegExpPointers(RawRegExp* raw_obj,
+                                        ObjectPointerVisitor* visitor) {
   // Make sure that we got here with the tagged pointer as this.
   ASSERT(raw_obj->IsHeapObject());
   visitor->VisitPointers(raw_obj->from(), raw_obj->to());
-  return JSRegExp::InstanceSize();
+  return RegExp::InstanceSize();
 }
 
 
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index f438fc9..561011c 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -52,7 +52,6 @@
     V(LibraryPrefix)                                                           \
     V(AbstractType)                                                            \
       V(Type)                                                                  \
-      V(FunctionType)                                                          \
       V(TypeRef)                                                               \
       V(TypeParameter)                                                         \
       V(BoundedType)                                                           \
@@ -75,7 +74,7 @@
     V(ReceivePort)                                                             \
     V(SendPort)                                                                \
     V(Stacktrace)                                                              \
-    V(JSRegExp)                                                                \
+    V(RegExp)                                                                  \
     V(WeakProperty)                                                            \
     V(MirrorReference)                                                         \
     V(LinkedHashMap)                                                           \
@@ -108,6 +107,22 @@
   V(Int32x4Array)                                                              \
   V(Float64x2Array)                                                            \
 
+#define DART_CLASS_LIST_TYPED_DATA(V)                                          \
+  V(Int8)                                                                      \
+  V(Uint8)                                                                     \
+  V(Uint8Clamped)                                                              \
+  V(Int16)                                                                     \
+  V(Uint16)                                                                    \
+  V(Int32)                                                                     \
+  V(Uint32)                                                                    \
+  V(Int64)                                                                     \
+  V(Uint64)                                                                    \
+  V(Float32)                                                                   \
+  V(Float64)                                                                   \
+  V(Float32x4)                                                                 \
+  V(Int32x4)                                                                   \
+  V(Float64x2)
+
 #define CLASS_LIST_FOR_HANDLES(V)                                              \
   CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(V)                                 \
   V(Array)                                                                     \
@@ -852,7 +867,7 @@
   }
   RawContextScope* context_scope_;
   RawFunction* parent_function_;  // Enclosing function of this local function.
-  RawFunctionType* signature_type_;
+  RawType* signature_type_;
   RawInstance* closure_;  // Closure object for static implicit closures.
   RawObject** to() {
     return reinterpret_cast<RawObject**>(&ptr()->closure_);
@@ -1601,28 +1616,18 @@
   }
   RawObject* type_class_;  // Either resolved class or unresolved class.
   RawTypeArguments* arguments_;
-  RawLanguageError* error_;  // Error object if type is malformed or malbounded.
+  // This type object represents a function type if its signature field is a
+  // non-null function object.
+  // If this type is malformed or malbounded, the signature field gets
+  // overwritten by the error object in order to save space. If the type is a
+  // function type, its signature is lost, but the message in the error object
+  // can describe the issue without needing the signature.
+  union {
+    RawFunction* signature_;  // If not null, this type is a function type.
+    RawLanguageError* error_;  // If not null, type is malformed or malbounded.
+  } sig_or_err_;
   RawObject** to() {
-    return reinterpret_cast<RawObject**>(&ptr()->error_);
-  }
-  TokenPosition token_pos_;
-  int8_t type_state_;
-};
-
-
-class RawFunctionType : public RawAbstractType {
- private:
-  RAW_HEAP_OBJECT_IMPLEMENTATION(FunctionType);
-
-  RawObject** from() {
-    return reinterpret_cast<RawObject**>(&ptr()->scope_class_);
-  }
-  RawClass* scope_class_;
-  RawTypeArguments* arguments_;
-  RawFunction* signature_;
-  RawLanguageError* error_;  // Error object if type is malformed or malbounded.
-  RawObject** to() {
-    return reinterpret_cast<RawObject**>(&ptr()->error_);
+    return reinterpret_cast<RawObject**>(&ptr()->sig_or_err_.error_);
   }
   TokenPosition token_pos_;
   int8_t type_state_;
@@ -2059,8 +2064,8 @@
 
 
 // VM type for capturing JS regular expressions.
-class RawJSRegExp : public RawInstance {
-  RAW_HEAP_OBJECT_IMPLEMENTATION(JSRegExp);
+class RawRegExp : public RawInstance {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(RegExp);
 
   RawObject** from() {
     return reinterpret_cast<RawObject**>(&ptr()->num_bracket_expressions_);
@@ -2337,7 +2342,7 @@
          (index == kCodeCid) ||
          (index == kContextScopeCid) ||
          (index == kInstanceCid) ||
-         (index == kJSRegExpCid);
+         (index == kRegExpCid);
 }
 
 
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index d02909c..194317f 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -281,83 +281,6 @@
 }
 
 
-RawFunctionType* FunctionType::ReadFrom(SnapshotReader* reader,
-                                        intptr_t object_id,
-                                        intptr_t tags,
-                                        Snapshot::Kind kind,
-                                        bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Determine if the scope class of this function type is in the full snapshot.
-  bool scopeclass_is_in_fullsnapshot = reader->Read<bool>();
-
-  // Allocate function type object.
-  FunctionType& function_type =
-      FunctionType::ZoneHandle(reader->zone(), NEW_OBJECT(FunctionType));
-  bool is_canonical = RawObject::IsCanonical(tags);
-  bool defer_canonicalization = is_canonical &&
-      (kind != Snapshot::kFull && scopeclass_is_in_fullsnapshot);
-  reader->AddBackRef(object_id,
-                     &function_type,
-                     kIsDeserialized,
-                     defer_canonicalization);
-
-  // Set all non object fields.
-  function_type.set_token_pos(
-      TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
-  function_type.set_type_state(reader->Read<int8_t>());
-
-  // Set all the object fields.
-  READ_OBJECT_FIELDS(function_type,
-                     function_type.raw()->from(), function_type.raw()->to(),
-                     kAsReference);
-
-  // Set the canonical bit.
-  if (!defer_canonicalization && is_canonical) {
-    function_type.SetCanonical();
-  }
-
-  return function_type.raw();
-}
-
-
-void RawFunctionType::WriteTo(SnapshotWriter* writer,
-                              intptr_t object_id,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Only resolved and finalized function types should be written to a snapshot.
-  ASSERT((ptr()->type_state_ == RawFunctionType::kFinalizedInstantiated) ||
-         (ptr()->type_state_ == RawFunctionType::kFinalizedUninstantiated));
-  ASSERT(ptr()->scope_class_ != Object::null());
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kFunctionTypeCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out scopeclass_is_in_fullsnapshot first as this will
-  // help the reader decide on how to canonicalize the type object.
-  intptr_t tags = writer->GetObjectTags(ptr()->scope_class_);
-  bool scopeclass_is_in_fullsnapshot =
-      (ClassIdTag::decode(tags) == kClassCid) &&
-      Class::IsInFullSnapshot(reinterpret_cast<RawClass*>(ptr()->scope_class_));
-  writer->Write<bool>(scopeclass_is_in_fullsnapshot);
-
-  // Write out all the non object pointer fields.
-  writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());
-  writer->Write<int8_t>(ptr()->type_state_);
-
-  // Write out all the object pointer fields.
-  ASSERT(ptr()->scope_class_ != Object::null());
-  SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitPointers(from(), to());
-}
-
-
 RawTypeRef* TypeRef::ReadFrom(SnapshotReader* reader,
                               intptr_t object_id,
                               intptr_t tags,
@@ -3590,15 +3513,15 @@
 }
 
 
-RawJSRegExp* JSRegExp::ReadFrom(SnapshotReader* reader,
-                                intptr_t object_id,
-                                intptr_t tags,
-                                Snapshot::Kind kind,
-                                bool as_reference) {
+RawRegExp* RegExp::ReadFrom(SnapshotReader* reader,
+                            intptr_t object_id,
+                            intptr_t tags,
+                            Snapshot::Kind kind,
+                            bool as_reference) {
   ASSERT(reader != NULL);
 
-  // Allocate JSRegExp object.
-  JSRegExp& regex = JSRegExp::ZoneHandle(reader->zone(), NEW_OBJECT(JSRegExp));
+  // Allocate RegExp object.
+  RegExp& regex = RegExp::ZoneHandle(reader->zone(), NEW_OBJECT(RegExp));
   reader->AddBackRef(object_id, &regex, kIsDeserialized);
 
   // Read and Set all the other fields.
@@ -3626,17 +3549,17 @@
 }
 
 
-void RawJSRegExp::WriteTo(SnapshotWriter* writer,
-                          intptr_t object_id,
-                          Snapshot::Kind kind,
-                          bool as_reference) {
+void RawRegExp::WriteTo(SnapshotWriter* writer,
+                        intptr_t object_id,
+                        Snapshot::Kind kind,
+                        bool as_reference) {
   ASSERT(writer != NULL);
 
   // Write out the serialization header value for this object.
   writer->WriteInlinedObjectHeader(object_id);
 
   // Write out the class and tags information.
-  writer->WriteIndexedObject(kJSRegExpCid);
+  writer->WriteIndexedObject(kRegExpCid);
   writer->WriteTags(writer->GetObjectTags(this));
 
   // Write out all the other fields.
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index e49c3d8..62fab5a 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -5018,7 +5018,7 @@
   const intptr_t specialization_cid = function.string_specialization_cid();
   const bool is_one_byte = (specialization_cid == kOneByteStringCid ||
                             specialization_cid == kExternalOneByteStringCid);
-  JSRegExp& regexp = JSRegExp::Handle(zone, function.regexp());
+  RegExp& regexp = RegExp::Handle(zone, function.regexp());
   const String& pattern = String::Handle(zone, regexp.pattern());
 
   ASSERT(!regexp.IsNull());
@@ -5132,7 +5132,7 @@
 
 RegExpEngine::CompilationResult RegExpEngine::CompileBytecode(
     RegExpCompileData* data,
-    const JSRegExp& regexp,
+    const RegExp& regexp,
     bool is_one_byte,
     Zone* zone) {
   ASSERT(FLAG_interpret_irregexp);
@@ -5245,7 +5245,7 @@
 
 
 static void CreateSpecializedFunction(Zone* zone,
-                                      const JSRegExp& regexp,
+                                      const RegExp& regexp,
                                       intptr_t specialization_cid,
                                       const Object& owner) {
   const intptr_t kParamCount = RegExpMacroAssembler::kParamCount;
@@ -5255,7 +5255,7 @@
       String::Handle(zone, Symbols::New(
           String::Handle(zone, String::Concat(
               String::Handle(zone, String::Concat(
-                  Symbols::Irregexp(),
+                  Symbols::ColonMatcher(),
                   Symbols::ColonSpace(), Heap::kOld)),
               String::Handle(regexp.pattern()), Heap::kOld)))),
       RawFunction::kIrregexpFunction,
@@ -5297,11 +5297,11 @@
 }
 
 
-RawJSRegExp* RegExpEngine::CreateJSRegExp(Zone* zone,
+RawRegExp* RegExpEngine::CreateRegExp(Zone* zone,
                                           const String& pattern,
                                           bool multi_line,
                                           bool ignore_case) {
-  const JSRegExp& regexp = JSRegExp::Handle(JSRegExp::New());
+  const RegExp& regexp = RegExp::Handle(RegExp::New());
 
   regexp.set_pattern(pattern);
 
@@ -5317,14 +5317,16 @@
   regexp.set_is_complex();
   regexp.set_is_global();   // All dart regexps are global.
 
-  const Library& lib = Library::Handle(zone, Library::CoreLibrary());
-  const Class& owner = Class::Handle(
-      zone, lib.LookupClass(Symbols::RegExp()));
+  if (!FLAG_interpret_irregexp) {
+    const Library& lib = Library::Handle(zone, Library::CoreLibrary());
+    const Class& owner = Class::Handle(
+        zone, lib.LookupClass(Symbols::RegExp()));
 
-  CreateSpecializedFunction(zone, regexp, kOneByteStringCid, owner);
-  CreateSpecializedFunction(zone, regexp, kTwoByteStringCid, owner);
-  CreateSpecializedFunction(zone, regexp, kExternalOneByteStringCid, owner);
-  CreateSpecializedFunction(zone, regexp, kExternalTwoByteStringCid, owner);
+    CreateSpecializedFunction(zone, regexp, kOneByteStringCid, owner);
+    CreateSpecializedFunction(zone, regexp, kTwoByteStringCid, owner);
+    CreateSpecializedFunction(zone, regexp, kExternalOneByteStringCid, owner);
+    CreateSpecializedFunction(zone, regexp, kExternalTwoByteStringCid, owner);
+  }
 
   return regexp.raw();
 }
diff --git a/runtime/vm/regexp.h b/runtime/vm/regexp.h
index 394279d..49aef37 100644
--- a/runtime/vm/regexp.h
+++ b/runtime/vm/regexp.h
@@ -1420,11 +1420,11 @@
 
   static CompilationResult CompileBytecode(
       RegExpCompileData* data,
-      const JSRegExp& regexp,
+      const RegExp& regexp,
       bool is_one_byte,
       Zone* zone);
 
-  static RawJSRegExp* CreateJSRegExp(
+  static RawRegExp* CreateRegExp(
       Zone* zone,
       const String& pattern,
       bool multi_line,
diff --git a/runtime/vm/regexp_assembler_bytecode.cc b/runtime/vm/regexp_assembler_bytecode.cc
index 193616c..9586aea 100644
--- a/runtime/vm/regexp_assembler_bytecode.cc
+++ b/runtime/vm/regexp_assembler_bytecode.cc
@@ -452,7 +452,7 @@
 }
 
 
-static intptr_t Prepare(const JSRegExp& regexp,
+static intptr_t Prepare(const RegExp& regexp,
                         const String& subject,
                         Zone* zone) {
   bool is_one_byte = subject.IsOneByteString() ||
@@ -464,7 +464,7 @@
     const bool multiline = regexp.is_multi_line();
     RegExpCompileData* compile_data = new(zone) RegExpCompileData();
     if (!RegExpParser::ParseRegExp(pattern, multiline, compile_data)) {
-      // Parsing failures are handled in the JSRegExp factory constructor.
+      // Parsing failures are handled in the RegExp factory constructor.
       UNREACHABLE();
     }
 
@@ -491,7 +491,7 @@
 }
 
 
-static IrregexpInterpreter::IrregexpResult ExecRaw(const JSRegExp& regexp,
+static IrregexpInterpreter::IrregexpResult ExecRaw(const RegExp& regexp,
                                                    const String& subject,
                                                    intptr_t index,
                                                    int32_t* output,
@@ -537,7 +537,7 @@
 }
 
 
-RawInstance* BytecodeRegExpMacroAssembler::Interpret(const JSRegExp& regexp,
+RawInstance* BytecodeRegExpMacroAssembler::Interpret(const RegExp& regexp,
                                                      const String& subject,
                                                      const Smi& start_index,
                                                      Zone* zone) {
diff --git a/runtime/vm/regexp_assembler_bytecode.h b/runtime/vm/regexp_assembler_bytecode.h
index 2de00d0..da2a6d7 100644
--- a/runtime/vm/regexp_assembler_bytecode.h
+++ b/runtime/vm/regexp_assembler_bytecode.h
@@ -105,7 +105,7 @@
   virtual void PrintBlocks() { UNIMPLEMENTED(); }
   /////
 
-  static RawInstance* Interpret(const JSRegExp& regexp,
+  static RawInstance* Interpret(const RegExp& regexp,
                                 const String& str,
                                 const Smi& start_index,
                                 Zone* zone);
diff --git a/runtime/vm/regexp_assembler_ir.cc b/runtime/vm/regexp_assembler_ir.cc
index bd04d7f..6f656db 100644
--- a/runtime/vm/regexp_assembler_ir.cc
+++ b/runtime/vm/regexp_assembler_ir.cc
@@ -311,7 +311,7 @@
 
 
 RawArray* IRRegExpMacroAssembler::Execute(
-    const JSRegExp& regexp,
+    const RegExp& regexp,
     const String& input,
     const Smi& start_offset,
     Zone* zone) {
@@ -429,7 +429,7 @@
 ConstantInstr* IRRegExpMacroAssembler::WordCharacterMapConstant() const {
   const Library& lib = Library::Handle(Z, Library::CoreLibrary());
   const Class& regexp_class = Class::Handle(Z,
-        lib.LookupClassAllowPrivate(Symbols::JSSyntaxRegExp()));
+        lib.LookupClassAllowPrivate(Symbols::_RegExp()));
   const Field& word_character_field = Field::ZoneHandle(Z,
       regexp_class.LookupStaticField(Symbols::_wordCharacterMap()));
   ASSERT(!word_character_field.IsNull());
diff --git a/runtime/vm/regexp_assembler_ir.h b/runtime/vm/regexp_assembler_ir.h
index eeb9f26..f898346 100644
--- a/runtime/vm/regexp_assembler_ir.h
+++ b/runtime/vm/regexp_assembler_ir.h
@@ -37,7 +37,7 @@
 
   virtual bool CanReadUnaligned();
 
-  static RawArray* Execute(const JSRegExp& regexp,
+  static RawArray* Execute(const RegExp& regexp,
                            const String& input,
                            const Smi& start_offset,
                            Zone* zone);
diff --git a/runtime/vm/regexp_parser.cc b/runtime/vm/regexp_parser.cc
index 7b0e01a..c4d471a 100644
--- a/runtime/vm/regexp_parser.cc
+++ b/runtime/vm/regexp_parser.cc
@@ -220,14 +220,14 @@
   VMTagScope tagScope(parsed_function->thread(),
                       VMTag::kCompileParseRegExpTagId);
   Zone* zone = parsed_function->zone();
-  JSRegExp& regexp = JSRegExp::Handle(parsed_function->function().regexp());
+  RegExp& regexp = RegExp::Handle(parsed_function->function().regexp());
 
   const String& pattern = String::Handle(regexp.pattern());
   const bool multiline = regexp.is_multi_line();
 
   RegExpCompileData* compile_data = new(zone) RegExpCompileData();
   if (!RegExpParser::ParseRegExp(pattern, multiline, compile_data)) {
-    // Parsing failures are handled in the JSRegExp factory constructor.
+    // Parsing failures are handled in the RegExp factory constructor.
     UNREACHABLE();
   }
 
diff --git a/runtime/vm/regexp_test.cc b/runtime/vm/regexp_test.cc
index d75dac4..e7c5ba8 100644
--- a/runtime/vm/regexp_test.cc
+++ b/runtime/vm/regexp_test.cc
@@ -14,8 +14,8 @@
 
 static RawArray* Match(const String& pat, const String& str) {
   Zone* zone = Thread::Current()->zone();
-  const JSRegExp& regexp = JSRegExp::Handle(
-      RegExpEngine::CreateJSRegExp(zone, pat, false, false));
+  const RegExp& regexp = RegExp::Handle(
+      RegExpEngine::CreateRegExp(zone, pat, false, false));
   const Smi& idx = Smi::Handle(Smi::New(0));
   return IRRegExpMacroAssembler::Execute(regexp, str, idx, zone);
 }
diff --git a/runtime/vm/safepoint.cc b/runtime/vm/safepoint.cc
index 47ef257..fcf2872 100644
--- a/runtime/vm/safepoint.cc
+++ b/runtime/vm/safepoint.cc
@@ -82,7 +82,7 @@
           // get it to a safepoint and wait for it to check in.
           if (current->IsMutatorThread()) {
             ASSERT(T->isolate() != NULL);
-            T->isolate()->ScheduleInterrupts(Isolate::kVMInterrupt);
+            current->ScheduleInterruptsLocked(Thread::kVMInterrupt);
           }
           MonitorLocker sl(safepoint_lock_);
           ++number_threads_not_at_safepoint_;
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index fb7a5db..d346361 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -35,6 +35,7 @@
 #include "vm/source_report.h"
 #include "vm/stack_frame.h"
 #include "vm/symbols.h"
+#include "vm/timeline.h"
 #include "vm/unicode.h"
 #include "vm/version.h"
 
@@ -2870,9 +2871,8 @@
   "all",
 #define DEFINE_NAME(name, unused)                                              \
   #name,
-ISOLATE_TIMELINE_STREAM_LIST(DEFINE_NAME)
+TIMELINE_STREAM_LIST(DEFINE_NAME)
 #undef DEFINE_NAME
-  "VM",
   NULL
 };
 
@@ -2915,9 +2915,8 @@
 
 #define SET_ENABLE_STREAM(name, unused)                                        \
   Timeline::SetStream##name##Enabled(HasStream(recorded_streams, #name));
-ISOLATE_TIMELINE_STREAM_LIST(SET_ENABLE_STREAM);
+TIMELINE_STREAM_LIST(SET_ENABLE_STREAM);
 #undef SET_ENABLE_STREAM
-  Timeline::SetVMStreamEnabled(HasStream(recorded_streams, "VM"));
 
   PrintSuccess(js);
 
@@ -3270,13 +3269,16 @@
 
 static const MethodParameter* request_heap_snapshot_params[] = {
   RUNNABLE_ISOLATE_PARAMETER,
+  new BoolParameter("collectGarbage", false /* not required */),
   NULL,
 };
 
 
 static bool RequestHeapSnapshot(Thread* thread, JSONStream* js) {
+  const bool collect_garbage =
+      BoolParameter::Parse(js->LookupParam("collectGarbage"), true);
   if (Service::graph_stream.enabled()) {
-    Service::SendGraphEvent(thread);
+    Service::SendGraphEvent(thread, collect_garbage);
   }
   // TODO(koda): Provide some id that ties this request to async response(s).
   JSONObject jsobj(js);
@@ -3285,11 +3287,11 @@
 }
 
 
-void Service::SendGraphEvent(Thread* thread) {
+void Service::SendGraphEvent(Thread* thread, bool collect_garbage) {
   uint8_t* buffer = NULL;
   WriteStream stream(&buffer, &allocator, 1 * MB);
   ObjectGraph graph(thread);
-  intptr_t node_count = graph.Serialize(&stream);
+  intptr_t node_count = graph.Serialize(&stream, collect_garbage);
 
   // Chrome crashes receiving a single tens-of-megabytes blob, so send the
   // snapshot in megabyte-sized chunks instead.
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index b7917ec..f38f7f83 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -105,7 +105,7 @@
       Dart_GetVMServiceAssetsArchive get_service_assets);
 
   static void SendEchoEvent(Isolate* isolate, const char* text);
-  static void SendGraphEvent(Thread* thread);
+  static void SendGraphEvent(Thread* thread, bool collect_garbage);
   static void SendInspectEvent(Isolate* isolate, const Object& inspectee);
 
   static void SendEmbedderEvent(Isolate* isolate,
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 7e6c7f0..68d134f 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -971,11 +971,21 @@
   // The superclass of this class, if any.
   @Class super [optional];
 
-  // A list of interface types for this class.
+  // The supertype for this class, if any.
   //
   // The value will be of the kind: Type.
+  @Instance superType [optional];
+
+  // A list of interface types for this class.
+  //
+  // The values will be of the kind: Type.
   @Instance[] interfaces;
 
+  // The mixin type for this class, if any.
+  //
+  // The value will be of the kind: Type.
+  @Instance mixin [optional];
+
   // A list of fields in this class. Does not include fields from
   // superclasses.
   @Field[] fields;
@@ -2508,5 +2518,5 @@
 3.1 | Add the getSourceReport RPC.  The getObject RPC now accepts offset and count for string objects.  String objects now contain length, offset, and count properties.
 3.2 | Isolate objects now include the runnable bit and many debugger related RPCs will return an error if executed on an isolate before it is runnable.
 3.3 | Pause event now indicates if the isolate is paused at an await, yield, or yield* suspension point via the 'atAsyncSuspension' field. Resume command now supports the step parameter 'OverAsyncSuspension'. A Breakpoint added synthetically by an 'OverAsyncSuspension' resume command identifies itself as such via the 'isSyntheticAsyncContinuation' field.
-
+3.4 | Add the superType and mixin fields to Class.
 [discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service_event.cc b/runtime/vm/service_event.cc
index 502a38b..d34f439 100644
--- a/runtime/vm/service_event.cc
+++ b/runtime/vm/service_event.cc
@@ -51,8 +51,13 @@
       bytes_(NULL),
       bytes_length_(0),
       timestamp_(OS::GetCurrentTimeMillis()) {
-  if ((event_kind == ServiceEvent::kPauseStart) ||
-      (event_kind == ServiceEvent::kPauseExit)) {
+  if ((event_kind == ServiceEvent::kPauseStart) &&
+      !isolate->message_handler()->is_paused_on_start()) {
+    // We will pause on start but the message handler lacks a valid
+    // paused timestamp because we haven't paused yet. Use the current time.
+    timestamp_ = OS::GetCurrentTimeMillis();
+  } else if ((event_kind == ServiceEvent::kPauseStart) ||
+             (event_kind == ServiceEvent::kPauseExit)) {
     timestamp_ = isolate->message_handler()->paused_timestamp();
   } else if (event_kind == ServiceEvent::kResume) {
     timestamp_ = isolate->last_resume_timestamp();
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index 86c8aab..a75c2fd 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -19,6 +19,7 @@
 #include "vm/service.h"
 #include "vm/symbols.h"
 #include "vm/thread_pool.h"
+#include "vm/timeline.h"
 
 namespace dart {
 
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index e5d06c8..1fcb66b 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -1137,7 +1137,7 @@
 void Simulator::ClearExclusive() {
   MutexLocker ml(exclusive_access_lock_);
   // Remove the reservation for this thread.
-  SetExclusiveAccess(NULL);
+  SetExclusiveAccess(0);
 }
 
 
@@ -1539,7 +1539,7 @@
             (redirection->call_kind() == kBootstrapNativeCall) ||
             (redirection->call_kind() == kNativeCall)) {
           // Set the top_exit_frame_info of this simulator to the native stack.
-          set_top_exit_frame_info(Isolate::GetCurrentStackPointer());
+          set_top_exit_frame_info(Thread::GetCurrentStackPointer());
         }
         if (redirection->call_kind() == kRuntimeCall) {
           NativeArguments arguments;
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index a19311d..cef6aa2 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -1611,7 +1611,7 @@
         (redirection->call_kind() == kBootstrapNativeCall) ||
         (redirection->call_kind() == kNativeCall)) {
       // Set the top_exit_frame_info of this simulator to the native stack.
-      set_top_exit_frame_info(Isolate::GetCurrentStackPointer());
+      set_top_exit_frame_info(Thread::GetCurrentStackPointer());
     }
     if (redirection->call_kind() == kRuntimeCall) {
       NativeArguments* arguments =
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index a828752..244b331 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -1250,7 +1250,7 @@
           (redirection->call_kind() == kBootstrapNativeCall) ||
           (redirection->call_kind() == kNativeCall)) {
         // Set the top_exit_frame_info of this simulator to the native stack.
-        set_top_exit_frame_info(Isolate::GetCurrentStackPointer());
+        set_top_exit_frame_info(Thread::GetCurrentStackPointer());
       }
       if (redirection->call_kind() == kRuntimeCall) {
         NativeArguments arguments;
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 294a90b..ea0dce3 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -627,6 +627,27 @@
       }
     }
 
+    if (snapshot_code()) {
+      ICData& ic = ICData::Handle(thread->zone());
+      Object& funcOrCode = Object::Handle(thread->zone());
+      Code& code = Code::Handle(thread->zone());
+      Smi& entry_point = Smi::Handle(thread->zone());
+      for (intptr_t i = 0; i < backward_references_->length(); i++) {
+        if ((*backward_references_)[i].reference()->IsICData()) {
+          ic ^= (*backward_references_)[i].reference()->raw();
+          for (intptr_t j = 0; j < ic.NumberOfChecks(); j++) {
+            funcOrCode = ic.GetTargetOrCodeAt(j);
+            if (funcOrCode.IsCode()) {
+              code ^= funcOrCode.raw();
+              entry_point = Smi::FromAlignedAddress(code.EntryPoint());
+              ic.SetEntryPointAt(j, entry_point);
+            }
+          }
+        }
+      }
+    }
+
+
     // Validate the class table.
 #if defined(DEBUG)
     isolate->ValidateClassTable();
@@ -939,11 +960,6 @@
 }
 
 
-RawFunctionType* SnapshotReader::NewFunctionType() {
-  ALLOC_NEW_OBJECT(FunctionType);
-}
-
-
 RawTypeRef* SnapshotReader::NewTypeRef() {
   ALLOC_NEW_OBJECT(TypeRef);
 }
@@ -1049,8 +1065,8 @@
 }
 
 
-RawJSRegExp* SnapshotReader::NewJSRegExp() {
-  ALLOC_NEW_OBJECT(JSRegExp);
+RawRegExp* SnapshotReader::NewRegExp() {
+  ALLOC_NEW_OBJECT(RegExp);
 }
 
 
@@ -1157,19 +1173,19 @@
 
 
 void InstructionsWriter::WriteAssembly() {
-  Zone* Z = Thread::Current()->zone();
+  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(Z, data.raw_insns_);
+    data.insns_ = &Instructions::Handle(zone, data.raw_insns_);
     ASSERT(data.raw_code_ != NULL);
-    data.code_ = &Code::Handle(Z, data.raw_code_);
+    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(Z, data.raw_obj_);
+    data.obj_ = &Object::Handle(zone, data.raw_obj_);
   }
 
   stream_.Print(".text\n");
@@ -1188,8 +1204,8 @@
     WriteWordLiteral(0);
   }
 
-  Object& owner = Object::Handle(Z);
-  String& str = String::Handle(Z);
+  Object& owner = Object::Handle(zone);
+  String& str = String::Handle(zone);
 
   for (intptr_t i = 0; i < instructions_.length(); i++) {
     const Instructions& insns = *instructions_[i].insns_;
@@ -1483,20 +1499,16 @@
 
 void SnapshotReader::ProcessDeferredCanonicalizations() {
   Type& typeobj = Type::Handle();
-  FunctionType& funtypeobj = FunctionType::Handle();
   TypeArguments& typeargs = TypeArguments::Handle();
   Object& newobj = Object::Handle();
   for (intptr_t i = 0; i < backward_references_->length(); i++) {
     BackRefNode& backref = (*backward_references_)[i];
     if (backref.defer_canonicalization()) {
       Object* objref = backref.reference();
-      // Object should either be a type, a function type, or a type argument.
+      // Object should either be a type or a type argument.
       if (objref->IsType()) {
         typeobj ^= objref->raw();
         newobj = typeobj.Canonicalize();
-      } else if (objref->IsFunctionType()) {
-        funtypeobj ^= objref->raw();
-        newobj = funtypeobj.Canonicalize();
       } else {
         ASSERT(objref->IsTypeArguments());
         typeargs ^= objref->raw();
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 978dbd1..7f6436b 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -52,13 +52,12 @@
 class RawFloat32x4;
 class RawFloat64x2;
 class RawFunction;
-class RawFunctionType;
 class RawGrowableObjectArray;
 class RawICData;
 class RawImmutableArray;
 class RawInstructions;
 class RawInt32x4;
-class RawJSRegExp;
+class RawRegExp;
 class RawLanguageError;
 class RawLibrary;
 class RawLibraryPrefix;
@@ -445,7 +444,6 @@
   RawDouble* NewDouble(double value);
   RawUnresolvedClass* NewUnresolvedClass();
   RawType* NewType();
-  RawFunctionType* NewFunctionType();
   RawTypeRef* NewTypeRef();
   RawTypeParameter* NewTypeParameter();
   RawBoundedType* NewBoundedType();
@@ -483,7 +481,7 @@
   RawObject* NewInteger(int64_t value);
   RawStacktrace* NewStacktrace();
   RawWeakProperty* NewWeakProperty();
-  RawJSRegExp* NewJSRegExp();
+  RawRegExp* NewRegExp();
 
   RawInstructions* GetInstructionsAt(int32_t offset, uword expected_tags) {
     return instructions_reader_->GetInstructionsAt(offset, expected_tags);
@@ -612,7 +610,7 @@
   friend class ICData;
   friend class ImmutableArray;
   friend class Instructions;
-  friend class JSRegExp;
+  friend class RegExp;
   friend class LanguageError;
   friend class Library;
   friend class LibraryPrefix;
@@ -631,7 +629,6 @@
   friend class SubtypeTestCache;
   friend class TokenStream;
   friend class Type;
-  friend class FunctionType;
   friend class TypeArguments;
   friend class TypeParameter;
   friend class TypeRef;
@@ -1058,7 +1055,7 @@
   friend class RawGrowableObjectArray;
   friend class RawImmutableArray;
   friend class RawInstructions;
-  friend class RawJSRegExp;
+  friend class RawRegExp;
   friend class RawLibrary;
   friend class RawLinkedHashMap;
   friend class RawLiteralToken;
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 494ac53..1d3e818 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -43,7 +43,9 @@
   next_script_index_ = 0;
   if (IsReportRequested(kProfile)) {
     // Build the profile.
-    SampleFilter samplesForIsolate(thread_->isolate(), -1, -1);
+    SampleFilter samplesForIsolate(thread_->isolate(),
+                                   Thread::kMutatorTask,
+                                   -1, -1);
     profile_.Build(thread, &samplesForIsolate, Profile::kNoTags);
   }
 }
diff --git a/runtime/vm/store_buffer.cc b/runtime/vm/store_buffer.cc
index cc0a816..b257c0a 100644
--- a/runtime/vm/store_buffer.cc
+++ b/runtime/vm/store_buffer.cc
@@ -100,12 +100,13 @@
   BlockStack<Block::kSize>::PushBlockImpl(block);
   if ((policy == kCheckThreshold) && Overflowed()) {
     MutexLocker ml(mutex_);
-    Isolate* isolate = Isolate::Current();
+    Thread* thread = Thread::Current();
     // Sanity check: it makes no sense to schedule the GC in another isolate.
     // (If Isolate ever gets multiple store buffers, we should avoid this
     // coupling by passing in an explicit callback+parameter at construction.)
-    ASSERT(isolate->store_buffer() == this);
-    isolate->ScheduleInterrupts(Isolate::kVMInterrupt);
+    ASSERT(thread->isolate()->mutator_thread() == thread);
+    ASSERT(thread->isolate()->store_buffer() == this);
+    thread->ScheduleInterrupts(Thread::kVMInterrupt);
   }
 }
 
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index f451638..d90a3ab 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -35,7 +35,8 @@
   V(OptimizeFunction)                                                          \
   V(InvokeDartCode)                                                            \
   V(DebugStepCheck)                                                            \
-  V(ICLookup)                                                                  \
+  V(ICLookupThroughFunction)                                                   \
+  V(ICLookupThroughCode)                                                       \
   V(MegamorphicLookup)                                                         \
   V(FixAllocationStubTarget)                                                   \
   V(Deoptimize)                                                                \
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 6b8812e..9a31d42 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -2110,7 +2110,7 @@
 //  R1: target entry point
 //  CODE_REG: target Code object
 //  R4: arguments descriptor
-void StubCode::GenerateICLookupStub(Assembler* assembler) {
+void StubCode::GenerateICLookupThroughFunctionStub(Assembler* assembler) {
   Label loop, found, miss;
   __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset()));
   __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset()));
@@ -2144,6 +2144,41 @@
   __ Ret();
 }
 
+
+void StubCode::GenerateICLookupThroughCodeStub(Assembler* assembler) {
+  Label loop, found, miss;
+  __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset()));
+  __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset()));
+  __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag);
+  // R8: first IC entry
+  __ LoadTaggedClassIdMayBeSmi(R1, R0);
+  // R1: receiver cid as Smi
+
+  __ Bind(&loop);
+  __ ldr(R2, Address(R8, 0));
+  __ cmp(R1, Operand(R2));
+  __ b(&found, EQ);
+  __ CompareImmediate(R2, Smi::RawValue(kIllegalCid));
+  __ b(&miss, EQ);
+
+  const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize;
+  __ AddImmediate(R8, entry_length);  // Next entry.
+  __ b(&loop);
+
+  __ Bind(&found);
+  const intptr_t code_offset = ICData::CodeIndexFor(1) * kWordSize;
+  const intptr_t entry_offset = ICData::EntryPointIndexFor(1) * kWordSize;
+  __ ldr(R1, Address(R8, entry_offset));
+  __ ldr(CODE_REG, Address(R8, code_offset));
+  __ Ret();
+
+  __ Bind(&miss);
+  __ LoadIsolate(R2);
+  __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset()));
+  __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ Ret();
+}
+
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_ARM
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index 61c3a4b..22ee31f 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -2163,7 +2163,7 @@
 //  R1: target entry point
 //  CODE_REG: target Code object
 //  R4: arguments descriptor
-void StubCode::GenerateICLookupStub(Assembler* assembler) {
+void StubCode::GenerateICLookupThroughFunctionStub(Assembler* assembler) {
   Label loop, found, miss;
   __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset()));
   __ ldr(R8, FieldAddress(R5, ICData::ic_data_offset()));
@@ -2197,6 +2197,41 @@
   __ ret();
 }
 
+
+void StubCode::GenerateICLookupThroughCodeStub(Assembler* assembler) {
+  Label loop, found, miss;
+  __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset()));
+  __ ldr(R8, FieldAddress(R5, ICData::ic_data_offset()));
+  __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag);
+  // R8: first IC entry
+  __ LoadTaggedClassIdMayBeSmi(R1, R0);
+  // R1: receiver cid as Smi
+
+  __ Bind(&loop);
+  __ ldr(R2, Address(R8, 0));
+  __ cmp(R1, Operand(R2));
+  __ b(&found, EQ);
+  __ CompareImmediate(R2, Smi::RawValue(kIllegalCid));
+  __ b(&miss, EQ);
+
+  const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize;
+  __ AddImmediate(R8, R8, entry_length);  // Next entry.
+  __ b(&loop);
+
+  __ Bind(&found);
+  const intptr_t code_offset = ICData::CodeIndexFor(1) * kWordSize;
+  const intptr_t entry_offset = ICData::EntryPointIndexFor(1) * kWordSize;
+  __ ldr(R1, Address(R8, entry_offset));
+  __ ldr(CODE_REG, Address(R8, code_offset));
+  __ ret();
+
+  __ Bind(&miss);
+  __ LoadIsolate(R2);
+  __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset()));
+  __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ ret();
+}
+
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_ARM64
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 640f0ec..57820c8 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -2084,7 +2084,12 @@
 // Result:
 //  EBX: target entry point
 //  EDX: arguments descriptor
-void StubCode::GenerateICLookupStub(Assembler* assembler) {
+void StubCode::GenerateICLookupThroughFunctionStub(Assembler* assembler) {
+  __ int3();
+}
+
+
+void StubCode::GenerateICLookupThroughCodeStub(Assembler* assembler) {
   __ int3();
 }
 
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index b4965c33..1a13f74 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -2278,7 +2278,7 @@
 //  T1: target entry point
 //  CODE_REG: target Code object
 //  S4: arguments descriptor
-void StubCode::GenerateICLookupStub(Assembler* assembler) {
+void StubCode::GenerateICLookupThroughFunctionStub(Assembler* assembler) {
   Label loop, found, miss;
   __ lw(T6, FieldAddress(S5, ICData::ic_data_offset()));
   __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset()));
@@ -2311,6 +2311,40 @@
   __ Ret();
 }
 
+
+void StubCode::GenerateICLookupThroughCodeStub(Assembler* assembler) {
+  Label loop, found, miss;
+  __ lw(T6, FieldAddress(S5, ICData::ic_data_offset()));
+  __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset()));
+  __ AddImmediate(T6, T6, Array::data_offset() - kHeapObjectTag);
+  // T6: first IC entry.
+  __ LoadTaggedClassIdMayBeSmi(T1, T0);
+  // T1: receiver cid as Smi
+
+  __ Bind(&loop);
+  __ lw(T2, Address(T6, 0));
+  __ beq(T1, T2, &found);
+  ASSERT(Smi::RawValue(kIllegalCid) == 0);
+  __ beq(T2, ZR, &miss);
+
+  const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize;
+  __ AddImmediate(T6, entry_length);  // Next entry.
+  __ b(&loop);
+
+  __ Bind(&found);
+  const intptr_t code_offset = ICData::CodeIndexFor(1) * kWordSize;
+  const intptr_t entry_offset = ICData::EntryPointIndexFor(1) * kWordSize;
+  __ lw(T1, Address(T6, entry_offset));
+  __ lw(CODE_REG, Address(T6, code_offset));
+  __ Ret();
+
+  __ Bind(&miss);
+  __ LoadIsolate(T2);
+  __ lw(CODE_REG, Address(T2, Isolate::ic_miss_code_offset()));
+  __ lw(T1, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ Ret();
+}
+
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_MIPS
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index b33ee01..a8ed6ef 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -2144,7 +2144,7 @@
 //  RCX: target entry point
 //  CODE_REG: target Code object
 //  R10: arguments descriptor
-void StubCode::GenerateICLookupStub(Assembler* assembler) {
+void StubCode::GenerateICLookupThroughFunctionStub(Assembler* assembler) {
   Label loop, found, miss;
 
   __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset()));
@@ -2181,6 +2181,44 @@
   __ ret();
 }
 
+
+void StubCode::GenerateICLookupThroughCodeStub(Assembler* assembler) {
+  Label loop, found, miss;
+
+  __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset()));
+  __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
+  __ leaq(R13, FieldAddress(R13, Array::data_offset()));
+  // R13: first IC entry
+  __ LoadTaggedClassIdMayBeSmi(RAX, RDI);
+  // RAX: receiver cid as Smi
+
+  __ Bind(&loop);
+  __ movq(R9, Address(R13, 0));
+  __ cmpq(RAX, R9);
+  __ j(EQUAL, &found, Assembler::kNearJump);
+
+  ASSERT(Smi::RawValue(kIllegalCid) == 0);
+  __ testq(R9, R9);
+  __ j(ZERO, &miss, Assembler::kNearJump);
+
+  const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize;
+  __ addq(R13, Immediate(entry_length));  // Next entry.
+  __ jmp(&loop);
+
+  __ Bind(&found);
+  const intptr_t code_offset = ICData::CodeIndexFor(1) * kWordSize;
+  const intptr_t entry_offset = ICData::EntryPointIndexFor(1) * kWordSize;
+  __ movq(RCX, Address(R13, entry_offset));
+  __ movq(CODE_REG, Address(R13, code_offset));
+  __ ret();
+
+  __ Bind(&miss);
+  __ LoadIsolate(RAX);
+  __ movq(CODE_REG, Address(RAX, Isolate::ic_miss_code_offset()));
+  __ movq(RCX, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ ret();
+}
+
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_X64
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 5b31bef75..d5f3498 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -137,7 +137,6 @@
   V(Dynamic, "dynamic")                                                        \
   V(UnresolvedClass, "UnresolvedClass")                                        \
   V(Type, "_Type")                                                             \
-  V(FunctionType, "_FunctionType")                                             \
   V(TypeRef, "_TypeRef")                                                       \
   V(TypeParameter, "_TypeParameter")                                           \
   V(BoundedType, "_BoundedType")                                               \
@@ -200,15 +199,12 @@
   V(_RawReceivePortImpl, "_RawReceivePortImpl")                                \
   V(_SendPortImpl, "_SendPortImpl")                                            \
   V(_StackTrace, "_StackTrace")                                                \
-  V(JSSyntaxRegExp, "_JSSyntaxRegExp")                                         \
+  V(_RegExp, "_RegExp")                                                        \
   V(RegExp, "RegExp")                                                          \
-  V(Irregexp, ":irregexp")                                                     \
+  V(ColonMatcher, ":matcher")                                                  \
   V(Object, "Object")                                                          \
   V(Int, "int")                                                                \
   V(Double, "double")                                                          \
-  V(_Float32x4, "_Float32x4")                                                  \
-  V(_Float64x2, "_Float64x2")                                                  \
-  V(_Int32x4, "_Int32x4")                                                      \
   V(Float32x4, "Float32x4")                                                    \
   V(Float64x2, "Float64x2")                                                    \
   V(Int32x4, "Int32x4")                                                        \
@@ -226,34 +222,20 @@
   V(Float64x2List, "Float64x2List")                                            \
   V(Float32List, "Float32List")                                                \
   V(Float64List, "Float64List")                                                \
-  V(_Int8Array, "_Int8Array")                                                  \
-  V(_Int8ArrayFactory, "_Int8Array.")                                          \
-  V(_Uint8Array, "_Uint8Array")                                                \
-  V(_Uint8ArrayFactory, "_Uint8Array.")                                        \
-  V(_Uint8ClampedArray, "_Uint8ClampedArray")                                  \
-  V(_Uint8ClampedArrayFactory, "_Uint8ClampedArray.")                          \
-  V(_Int16Array, "_Int16Array")                                                \
-  V(_Int16ArrayFactory, "_Int16Array.")                                        \
-  V(_Uint16Array, "_Uint16Array")                                              \
-  V(_Uint16ArrayFactory, "_Uint16Array.")                                      \
-  V(_Int32Array, "_Int32Array")                                                \
-  V(_Int32ArrayFactory, "_Int32Array.")                                        \
-  V(_Uint32Array, "_Uint32Array")                                              \
-  V(_Uint32ArrayFactory, "_Uint32Array.")                                      \
-  V(_Int64Array, "_Int64Array")                                                \
-  V(_Int64ArrayFactory, "_Int64Array.")                                        \
-  V(_Uint64Array, "_Uint64Array")                                              \
-  V(_Uint64ArrayFactory, "_Uint64Array.")                                      \
-  V(_Float32x4Array, "_Float32x4Array")                                        \
-  V(_Float32x4ArrayFactory, "_Float32x4Array.")                                \
-  V(_Int32x4Array, "_Int32x4Array")                                            \
-  V(_Int32x4ArrayFactory, "_Int32x4Array.")                                    \
-  V(_Float64x2Array, "_Float64x2Array")                                        \
-  V(_Float64x2ArrayFactory, "_Float64x2Array.")                                \
-  V(_Float32Array, "_Float32Array")                                            \
-  V(_Float32ArrayFactory, "_Float32Array.")                                    \
-  V(_Float64Array, "_Float64Array")                                            \
-  V(_Float64ArrayFactory, "_Float64Array.")                                    \
+  V(_Int8ArrayFactory, "Int8List.")                                          \
+  V(_Uint8ArrayFactory, "Uint8List.")                                        \
+  V(_Uint8ClampedArrayFactory, "Uint8ClampedList.")                          \
+  V(_Int16ArrayFactory, "Int16List.")                                        \
+  V(_Uint16ArrayFactory, "Uint16List.")                                      \
+  V(_Int32ArrayFactory, "Int32List.")                                        \
+  V(_Uint32ArrayFactory, "Uint32List.")                                      \
+  V(_Int64ArrayFactory, "Int64List.")                                        \
+  V(_Uint64ArrayFactory, "Uint64List.")                                      \
+  V(_Float32x4ArrayFactory, "Float32x4List.")                                \
+  V(_Int32x4ArrayFactory, "Int32x4List.")                                    \
+  V(_Float64x2ArrayFactory, "Float64x2List.")                                \
+  V(_Float32ArrayFactory, "Float32List.")                                    \
+  V(_Float64ArrayFactory, "Float64List.")                                    \
   V(_Int8ArrayView, "_Int8ArrayView")                                          \
   V(_Uint8ArrayView, "_Uint8ArrayView")                                        \
   V(_Uint8ClampedArrayView, "_Uint8ClampedArrayView")                          \
@@ -286,8 +268,8 @@
   V(ByteDataDot, "ByteData.")                                                  \
   V(ByteDataDot_view, "ByteData._view")                                        \
   V(_ByteDataView, "_ByteDataView")                                            \
-  V(_ByteBuffer, "_ByteBuffer")                                                \
-  V(_ByteBufferDot_New, "_ByteBuffer._New")                                    \
+  V(ByteBuffer, "ByteBuffer")                                                  \
+  V(ByteBufferDot_New, "ByteBuffer._New")                                      \
   V(_WeakProperty, "_WeakProperty")                                            \
   V(_MirrorReference, "_MirrorReference")                                      \
   V(InvocationMirror, "_InvocationMirror")                                     \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index c5c6e70..fd176c2 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -9,6 +9,7 @@
 #include "vm/isolate.h"
 #include "vm/lockers.h"
 #include "vm/log.h"
+#include "vm/message_handler.h"
 #include "vm/native_entry.h"
 #include "vm/object.h"
 #include "vm/os_thread.h"
@@ -21,6 +22,12 @@
 
 namespace dart {
 
+
+DECLARE_FLAG(bool, trace_isolates);
+DECLARE_FLAG(bool, trace_service);
+DECLARE_FLAG(bool, trace_service_verbose);
+
+
 Thread::~Thread() {
   // We should cleanly exit any isolate before destruction.
   ASSERT(isolate_ == NULL);
@@ -49,17 +56,21 @@
 
 Thread::Thread(Isolate* isolate)
     : BaseThread(false),
-      os_thread_(NULL),
-      thread_lock_(new Monitor()),
+      stack_limit_(0),
+      stack_overflow_flags_(0),
       isolate_(NULL),
       heap_(NULL),
+      top_exit_frame_info_(0),
+      store_buffer_block_(NULL),
+      vm_tag_(0),
+      task_kind_(kUnknownTask),
+      os_thread_(NULL),
+      thread_lock_(new Monitor()),
       zone_(NULL),
       api_reusable_scope_(NULL),
       api_top_scope_(NULL),
-      top_exit_frame_info_(0),
       top_resource_(NULL),
       long_jump_base_(NULL),
-      store_buffer_block_(NULL),
       no_callback_scope_depth_(0),
 #if defined(DEBUG)
       top_handle_scope_(NULL),
@@ -67,9 +78,12 @@
       no_safepoint_scope_depth_(0),
 #endif
       reusable_handles_(),
+      saved_stack_limit_(0),
+      deferred_interrupts_mask_(0),
+      deferred_interrupts_(0),
+      stack_overflow_count_(0),
       cha_(NULL),
       deopt_id_(0),
-      vm_tag_(0),
       pending_functions_(GrowableObjectArray::null()),
       sticky_error_(Error::null()),
       REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
@@ -211,6 +225,7 @@
   Thread* thread = isolate->ScheduleThread(kIsMutatorThread);
   if (thread != NULL) {
     ASSERT(thread->store_buffer_block_ == NULL);
+    thread->task_kind_ = kMutatorTask;
     thread->StoreBufferAcquire();
     return true;
   }
@@ -222,7 +237,7 @@
   Thread* thread = Thread::Current();
   ASSERT(thread != NULL && thread->IsMutatorThread());
   DEBUG_ASSERT(!thread->IsAnyReusableHandleScopeActive());
-
+  thread->task_kind_ = kUnknownTask;
   Isolate* isolate = thread->isolate();
   ASSERT(isolate != NULL);
   ASSERT(thread->execution_state() == Thread::kThreadInVM);
@@ -239,7 +254,10 @@
 }
 
 
-bool Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) {
+bool Thread::EnterIsolateAsHelper(Isolate* isolate,
+                                  TaskKind kind,
+                                  bool bypass_safepoint) {
+  ASSERT(kind != kMutatorTask);
   const bool kIsNotMutatorThread = false;
   Thread* thread = isolate->ScheduleThread(kIsNotMutatorThread,
                                            bypass_safepoint);
@@ -250,6 +268,7 @@
     thread->store_buffer_block_ =
         thread->isolate()->store_buffer()->PopEmptyBlock();
     // This thread should not be the main mutator.
+    thread->task_kind_ = kind;
     ASSERT(!thread->IsMutatorThread());
     return true;
   }
@@ -262,6 +281,9 @@
   ASSERT(thread != NULL);
   ASSERT(!thread->IsMutatorThread());
   ASSERT(thread->execution_state() == Thread::kThreadInVM);
+  thread->task_kind_ = kUnknownTask;
+  // Clear since GC will not visit the thread once it is unscheduled.
+  thread->ClearReusableHandles();
   thread->StoreBufferRelease();
   Isolate* isolate = thread->isolate();
   ASSERT(isolate != NULL);
@@ -282,6 +304,177 @@
 }
 
 
+void Thread::SetStackLimitFromStackBase(uword stack_base) {
+  // Set stack limit.
+#if defined(USING_SIMULATOR)
+  // Ignore passed-in native stack top and use Simulator stack top.
+  Simulator* sim = Simulator::Current();  // May allocate a simulator.
+  ASSERT(isolate()->simulator() == sim);  // Isolate's simulator is current one.
+  stack_base = sim->StackTop();
+  // The overflow area is accounted for by the simulator.
+#endif
+  SetStackLimit(stack_base - OSThread::GetSpecifiedStackSize());
+}
+
+
+void Thread::SetStackLimit(uword limit) {
+  // The thread setting the stack limit is not necessarily the thread which
+  // the stack limit is being set on.
+  MonitorLocker ml(thread_lock_);
+  if (stack_limit_ == saved_stack_limit_) {
+    // No interrupt pending, set stack_limit_ too.
+    stack_limit_ = limit;
+  }
+  saved_stack_limit_ = limit;
+}
+
+
+void Thread::ClearStackLimit() {
+  SetStackLimit(~static_cast<uword>(0));
+}
+
+
+/* static */
+uword Thread::GetCurrentStackPointer() {
+  // 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());
+  // But for performance (and to support simulators), we normally use a local.
+#if defined(__has_feature)
+#if __has_feature(address_sanitizer)
+  uword current_sp = func();
+  return current_sp;
+#else
+  uword stack_allocated_local_address = reinterpret_cast<uword>(&func);
+  return stack_allocated_local_address;
+#endif
+#else
+  uword stack_allocated_local_address = reinterpret_cast<uword>(&func);
+  return stack_allocated_local_address;
+#endif
+}
+
+
+void Thread::ScheduleInterrupts(uword interrupt_bits) {
+  MonitorLocker ml(thread_lock_);
+  ScheduleInterruptsLocked(interrupt_bits);
+}
+
+
+void Thread::ScheduleInterruptsLocked(uword interrupt_bits) {
+  ASSERT(thread_lock_->IsOwnedByCurrentThread());
+  ASSERT((interrupt_bits & ~kInterruptsMask) == 0);  // Must fit in mask.
+
+  // Check to see if any of the requested interrupts should be deferred.
+  uword defer_bits = interrupt_bits & deferred_interrupts_mask_;
+  if (defer_bits != 0) {
+    deferred_interrupts_ |= defer_bits;
+    interrupt_bits &= ~deferred_interrupts_mask_;
+    if (interrupt_bits == 0) {
+      return;
+    }
+  }
+
+  if (stack_limit_ == saved_stack_limit_) {
+    stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask;
+  }
+  stack_limit_ |= interrupt_bits;
+}
+
+
+uword Thread::GetAndClearInterrupts() {
+  MonitorLocker ml(thread_lock_);
+  if (stack_limit_ == saved_stack_limit_) {
+    return 0;  // No interrupt was requested.
+  }
+  uword interrupt_bits = stack_limit_ & kInterruptsMask;
+  stack_limit_ = saved_stack_limit_;
+  return interrupt_bits;
+}
+
+
+void Thread::DeferOOBMessageInterrupts() {
+  MonitorLocker ml(thread_lock_);
+  ASSERT(deferred_interrupts_mask_ == 0);
+  deferred_interrupts_mask_ = kMessageInterrupt;
+
+  if (stack_limit_ != saved_stack_limit_) {
+    // Defer any interrupts which are currently pending.
+    deferred_interrupts_ = stack_limit_ & deferred_interrupts_mask_;
+
+    // Clear deferrable interrupts, if present.
+    stack_limit_ &= ~deferred_interrupts_mask_;
+
+    if ((stack_limit_ & kInterruptsMask) == 0) {
+      // No other pending interrupts.  Restore normal stack limit.
+      stack_limit_ = saved_stack_limit_;
+    }
+  }
+  if (FLAG_trace_service && FLAG_trace_service_verbose) {
+    OS::Print("[+%" Pd64 "ms] Isolate %s deferring OOB interrupts\n",
+              Dart::timestamp(), isolate()->name());
+  }
+}
+
+
+void Thread::RestoreOOBMessageInterrupts() {
+  MonitorLocker ml(thread_lock_);
+  ASSERT(deferred_interrupts_mask_ == kMessageInterrupt);
+  deferred_interrupts_mask_ = 0;
+  if (deferred_interrupts_ != 0) {
+    if (stack_limit_ == saved_stack_limit_) {
+      stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask;
+    }
+    stack_limit_ |= deferred_interrupts_;
+    deferred_interrupts_ = 0;
+  }
+  if (FLAG_trace_service && FLAG_trace_service_verbose) {
+    OS::Print("[+%" Pd64 "ms] Isolate %s restoring OOB interrupts\n",
+              Dart::timestamp(), isolate()->name());
+  }
+}
+
+
+RawError* Thread::HandleInterrupts() {
+  uword interrupt_bits = GetAndClearInterrupts();
+  if ((interrupt_bits & kVMInterrupt) != 0) {
+    if (isolate()->store_buffer()->Overflowed()) {
+      if (FLAG_verbose_gc) {
+        OS::PrintErr("Scavenge scheduled by store buffer overflow.\n");
+      }
+      heap()->CollectGarbage(Heap::kNew);
+    }
+  }
+  if ((interrupt_bits & kMessageInterrupt) != 0) {
+    MessageHandler::MessageStatus status =
+        isolate()->message_handler()->HandleOOBMessages();
+    if (status != MessageHandler::kOK) {
+      // False result from HandleOOBMessages signals that the isolate should
+      // be terminating.
+      if (FLAG_trace_isolates) {
+        OS::Print("[!] Terminating isolate due to OOB message:\n"
+                  "\tisolate:    %s\n", isolate()->name());
+      }
+      Thread* thread = Thread::Current();
+      const Error& error = Error::Handle(thread->sticky_error());
+      ASSERT(!error.IsNull() && error.IsUnwindError());
+      thread->clear_sticky_error();
+      return error.raw();
+    }
+  }
+  return Error::null();
+}
+
+
+uword Thread::GetAndClearStackOverflowFlags() {
+  uword stack_overflow_flags = stack_overflow_flags_;
+  stack_overflow_flags_ = 0;
+  return stack_overflow_flags;
+}
+
+
 void Thread::StoreBufferBlockProcess(StoreBuffer::ThresholdPolicy policy) {
   StoreBufferRelease(policy);
   StoreBufferAcquire();
@@ -357,9 +550,14 @@
 }
 
 
-void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor) {
+void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor,
+                                 bool validate_frames) {
   ASSERT(visitor != NULL);
 
+  if (zone_ != NULL) {
+    zone_->VisitObjectPointers(visitor);
+  }
+
   // Visit objects in thread specific handles area.
   reusable_handles_.VisitObjectPointers(visitor);
 
@@ -374,6 +572,15 @@
     scope->local_handles()->VisitObjectPointers(visitor);
     scope = scope->previous();
   }
+
+  // Iterate over all the stack frames and visit objects on the stack.
+  StackFrameIterator frames_iterator(top_exit_frame_info(),
+                                     validate_frames);
+  StackFrame* frame = frames_iterator.NextFrame();
+  while (frame != NULL) {
+    frame->VisitObjectPointers(visitor);
+    frame = frames_iterator.NextFrame();
+  }
 }
 
 
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 3bf5aab..31313d6 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -118,6 +118,14 @@
 // must currently be called manually (issue 23474).
 class Thread : public BaseThread {
  public:
+  // The kind of task this thread is performing. Sampled by the profiler.
+  enum TaskKind {
+    kUnknownTask = 0x0,
+    kMutatorTask = 0x1,
+    kCompilerTask = 0x2,
+    kSweeperTask = 0x4,
+    kMarkerTask = 0x8,
+  };
   ~Thread();
 
   // The currently executing thread, or NULL if not yet initialized.
@@ -139,12 +147,71 @@
   // SweeperTask (which uses the class table, which is copy-on-write).
   // TODO(koda): Properly synchronize heap access to expand allowed operations.
   static bool EnterIsolateAsHelper(Isolate* isolate,
+                                   TaskKind kind,
                                    bool bypass_safepoint = false);
   static void ExitIsolateAsHelper(bool bypass_safepoint = false);
 
   // Empties the store buffer block into the isolate.
   void PrepareForGC();
 
+  void SetStackLimit(uword value);
+  void SetStackLimitFromStackBase(uword stack_base);
+  void ClearStackLimit();
+
+  // Returns the current C++ stack pointer. Equivalent taking the address of a
+  // stack allocated local, but plays well with AddressSanitizer.
+  static uword GetCurrentStackPointer();
+
+  // Access to the current stack limit for generated code.  This may be
+  // overwritten with a special value to trigger interrupts.
+  uword stack_limit_address() const {
+    return reinterpret_cast<uword>(&stack_limit_);
+  }
+  static intptr_t stack_limit_offset() {
+    return OFFSET_OF(Thread, stack_limit_);
+  }
+
+  // The true stack limit for this isolate.
+  uword saved_stack_limit() const { return saved_stack_limit_; }
+
+  // Stack overflow flags
+  enum {
+    kOsrRequest = 0x1,  // Current stack overflow caused by OSR request.
+  };
+
+  uword stack_overflow_flags_address() const {
+    return reinterpret_cast<uword>(&stack_overflow_flags_);
+  }
+  static intptr_t stack_overflow_flags_offset() {
+    return OFFSET_OF(Thread, stack_overflow_flags_);
+  }
+
+  int32_t IncrementAndGetStackOverflowCount() {
+    return ++stack_overflow_count_;
+  }
+
+  TaskKind task_kind() const {
+    return task_kind_;
+  }
+
+  // Retrieves and clears the stack overflow flags.  These are set by
+  // the generated code before the slow path runtime routine for a
+  // stack overflow is called.
+  uword GetAndClearStackOverflowFlags();
+
+  // Interrupt bits.
+  enum {
+    kVMInterrupt = 0x1,  // Internal VM checks: safepoints, store buffers, etc.
+    kMessageInterrupt = 0x2,  // An interrupt to process an out of band message.
+
+    kInterruptsMask = (kVMInterrupt | kMessageInterrupt),
+  };
+
+  void ScheduleInterrupts(uword interrupt_bits);
+  void ScheduleInterruptsLocked(uword interrupt_bits);
+  RawError* HandleInterrupts();
+  uword GetAndClearInterrupts();
+
   // OSThread corresponding to this thread.
   OSThread* os_thread() const { return os_thread_; }
   void set_os_thread(OSThread* os_thread) {
@@ -521,7 +588,7 @@
   Thread* next() const { return next_; }
 
   // Visit all object pointers.
-  void VisitObjectPointers(ObjectPointerVisitor* visitor);
+  void VisitObjectPointers(ObjectPointerVisitor* visitor, bool validate_frames);
 
   bool IsValidLocalHandle(Dart_Handle object) const;
   int CountLocalHandles() const;
@@ -533,33 +600,15 @@
  private:
   template<class T> T* AllocateReusableHandle();
 
-  OSThread* os_thread_;
-  Monitor* thread_lock_;
+  // Accessed from generated code:
+  uword stack_limit_;
+  uword stack_overflow_flags_;
   Isolate* isolate_;
   Heap* heap_;
-  Zone* zone_;
-  ApiLocalScope* api_reusable_scope_;
-  ApiLocalScope* api_top_scope_;
   uword top_exit_frame_info_;
-  StackResource* top_resource_;
-  LongJumpScope* long_jump_base_;
   StoreBufferBlock* store_buffer_block_;
-  int32_t no_callback_scope_depth_;
-#if defined(DEBUG)
-  HandleScope* top_handle_scope_;
-  int32_t no_handle_scope_depth_;
-  int32_t no_safepoint_scope_depth_;
-#endif
-  VMHandles reusable_handles_;
-
-  // Compiler state:
-  CHA* cha_;
-  intptr_t deopt_id_;  // Compilation specific counter.
   uword vm_tag_;
-  RawGrowableObjectArray* pending_functions_;
-
-  RawError* sticky_error_;
-
+  TaskKind task_kind_;
   // State that is cached in the TLS for fast access in generated code.
 #define DECLARE_MEMBERS(type_name, member_name, expr, default_init_value)      \
   type_name member_name;
@@ -576,6 +625,32 @@
 LEAF_RUNTIME_ENTRY_LIST(DECLARE_MEMBERS)
 #undef DECLARE_MEMBERS
 
+  OSThread* os_thread_;
+  Monitor* thread_lock_;
+  Zone* zone_;
+  ApiLocalScope* api_reusable_scope_;
+  ApiLocalScope* api_top_scope_;
+  StackResource* top_resource_;
+  LongJumpScope* long_jump_base_;
+  int32_t no_callback_scope_depth_;
+#if defined(DEBUG)
+  HandleScope* top_handle_scope_;
+  int32_t no_handle_scope_depth_;
+  int32_t no_safepoint_scope_depth_;
+#endif
+  VMHandles reusable_handles_;
+  uword saved_stack_limit_;
+  uint16_t deferred_interrupts_mask_;
+  uint16_t deferred_interrupts_;
+  int32_t stack_overflow_count_;
+
+  // Compiler state:
+  CHA* cha_;
+  intptr_t deopt_id_;  // Compilation specific counter.
+  RawGrowableObjectArray* pending_functions_;
+
+  RawError* sticky_error_;
+
   // Reusable handles support.
 #define REUSABLE_HANDLE_FIELDS(object)                                         \
   object* object##_handle_;
@@ -622,13 +697,19 @@
     OSThread::SetCurrentTLS(reinterpret_cast<uword>(current));
   }
 
+  void DeferOOBMessageInterrupts();
+  void RestoreOOBMessageInterrupts();
+
 #define REUSABLE_FRIEND_DECLARATION(name)                                      \
   friend class Reusable##name##HandleScope;
 REUSABLE_HANDLE_LIST(REUSABLE_FRIEND_DECLARATION)
 #undef REUSABLE_FRIEND_DECLARATION
 
   friend class ApiZone;
+  friend class InterruptChecker;
   friend class Isolate;
+  friend class IsolateTestHelper;
+  friend class NoOOBMessageScope;
   friend class Simulator;
   friend class StackZone;
   friend class ThreadRegistry;
diff --git a/runtime/vm/thread_pool.cc b/runtime/vm/thread_pool.cc
index b281d5c..fb0f7d7 100644
--- a/runtime/vm/thread_pool.cc
+++ b/runtime/vm/thread_pool.cc
@@ -4,6 +4,7 @@
 
 #include "vm/thread_pool.h"
 
+#include "vm/dart.h"
 #include "vm/flags.h"
 #include "vm/lockers.h"
 
@@ -432,6 +433,9 @@
   ThreadJoinId join_id = os_thread->join_id();
   ThreadPool* pool;
 
+  // Set the thread's stack_base based on the current stack pointer.
+  os_thread->set_stack_base(Thread::GetCurrentStackPointer());
+
   {
     MonitorLocker ml(&worker->monitor_);
     ASSERT(worker->task_);
@@ -480,6 +484,12 @@
     // wait for the thread to exit by joining on it in Shutdown().
     delete worker;
   }
+
+  // Call the thread exit hook here to notify the embedder that the
+  // thread pool thread is exiting.
+  if (Dart::thread_exit_callback() != NULL) {
+    (*Dart::thread_exit_callback())();
+  }
 }
 
 }  // namespace dart
diff --git a/runtime/vm/thread_registry.cc b/runtime/vm/thread_registry.cc
index 111ae57..c660843 100644
--- a/runtime/vm/thread_registry.cc
+++ b/runtime/vm/thread_registry.cc
@@ -56,7 +56,6 @@
   // Remove thread from the active list for the isolate.
   RemoveFromActiveListLocked(thread);
   if (!is_mutator) {
-    ASSERT(thread->api_top_scope() == NULL);
     ReturnToFreelistLocked(thread);
   }
 }
@@ -65,22 +64,20 @@
 void ThreadRegistry::VisitObjectPointers(ObjectPointerVisitor* visitor,
                                          bool validate_frames) {
   MonitorLocker ml(threads_lock());
+  bool mutator_thread_visited = false;
   Thread* thread = active_list_;
   while (thread != NULL) {
-    if (thread->zone() != NULL) {
-      thread->zone()->VisitObjectPointers(visitor);
-    }
-    thread->VisitObjectPointers(visitor);
-    // Iterate over all the stack frames and visit objects on the stack.
-    StackFrameIterator frames_iterator(thread->top_exit_frame_info(),
-                                       validate_frames);
-    StackFrame* frame = frames_iterator.NextFrame();
-    while (frame != NULL) {
-      frame->VisitObjectPointers(visitor);
-      frame = frames_iterator.NextFrame();
+    thread->VisitObjectPointers(visitor, validate_frames);
+    if (mutator_thread_ == thread) {
+      mutator_thread_visited = true;
     }
     thread = thread->next_;
   }
+  // Visit mutator thread even if it is not in the active list because of
+  // api handles.
+  if (!mutator_thread_visited && (mutator_thread_ != NULL)) {
+    mutator_thread_->VisitObjectPointers(visitor, validate_frames);
+  }
 }
 
 
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index a20d7a4..aa006df 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -111,7 +111,7 @@
                          intptr_t id)
       : isolate_(isolate), monitor_(monitor), done_(done), id_(id) {}
   virtual void Run() {
-    Thread::EnterIsolateAsHelper(isolate_);
+    Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask);
     {
       Thread* thread = Thread::Current();
       // Create a zone (which is also a stack resource) and exercise it a bit.
@@ -259,7 +259,7 @@
       local_done_(false) {}
 
   virtual void Run() {
-    Thread::EnterIsolateAsHelper(isolate_);
+    Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask);
     {
       MonitorLocker ml(monitor_);
       ++*expected_count_;
@@ -534,7 +534,7 @@
   }
 
   virtual void Run() {
-    Thread::EnterIsolateAsHelper(isolate_);
+    Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask);
     {
       Thread* thread = Thread::Current();
       StackZone stack_zone(thread);
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index cd0b0fd..5f3d719 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -138,20 +138,14 @@
     recorder_ = new TimelineEventRingRecorder();
   }
   enabled_streams_ = GetEnabledByDefaultTimelineStreams();
-  vm_stream_.Init("VM", HasStream(enabled_streams_, "VM"), NULL);
-  vm_api_stream_.Init("API",
-                      HasStream(enabled_streams_, "API"),
-                      &stream_API_enabled_);
   // Global overrides.
-#define ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT(name, not_used)                   \
-  stream_##name##_enabled_ = HasStream(enabled_streams_, #name);
-  ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT)
-#undef ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT
-}
-
-
-void Timeline::SetVMStreamEnabled(bool enabled) {
-  vm_stream_.set_enabled(enabled);
+#define TIMELINE_STREAM_FLAG_DEFAULT(name, not_used)                           \
+  stream_##name##_enabled_ = HasStream(enabled_streams_, #name);               \
+  stream_##name##_.Init(#name,                                                 \
+                        stream_##name##_enabled_,                              \
+                        &stream_##name##_enabled_);
+  TIMELINE_STREAM_LIST(TIMELINE_STREAM_FLAG_DEFAULT)
+#undef TIMELINE_STREAM_FLAG_DEFAULT
 }
 
 
@@ -177,12 +171,10 @@
     recorder_->WriteTo(FLAG_timeline_dir);
   }
   // Disable global streams.
-  vm_stream_.set_enabled(false);
-  vm_api_stream_.set_enabled(false);
-#define ISOLATE_TIMELINE_STREAM_DISABLE(name, not_used)                   \
+#define TIMELINE_STREAM_DISABLE(name, not_used)                                \
   stream_##name##_enabled_ = false;
-  ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_DISABLE)
-#undef ISOLATE_TIMELINE_STREAM_DISABLE
+  TIMELINE_STREAM_LIST(TIMELINE_STREAM_DISABLE)
+#undef TIMELINE_STREAM_DISABLE
   delete recorder_;
   recorder_ = NULL;
   if (enabled_streams_ != NULL) {
@@ -197,30 +189,6 @@
 }
 
 
-void Timeline::SetupIsolateStreams(Isolate* isolate) {
-  if (!FLAG_support_timeline) {
-    return;
-  }
-#define ISOLATE_TIMELINE_STREAM_INIT(name, enabled_by_default)                 \
-  isolate->Get##name##Stream()->Init(                                          \
-      #name,                                                                   \
-      (enabled_by_default || HasStream(enabled_streams_, #name)),              \
-      Timeline::Stream##name##EnabledFlag());
-  ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_INIT);
-#undef ISOLATE_TIMELINE_STREAM_INIT
-}
-
-
-TimelineStream* Timeline::GetVMStream() {
-  return &vm_stream_;
-}
-
-
-TimelineStream* Timeline::GetVMApiStream() {
-  return &vm_api_stream_;
-}
-
-
 void Timeline::ReclaimCachedBlocksFromThreads() {
   TimelineEventRecorder* recorder = Timeline::recorder();
   if (recorder == NULL) {
@@ -256,9 +224,8 @@
     JSONArray availableStreams(&obj, "availableStreams");
 #define ADD_STREAM_NAME(name, not_used)                                        \
     availableStreams.AddValue(#name);
-ISOLATE_TIMELINE_STREAM_LIST(ADD_STREAM_NAME);
+TIMELINE_STREAM_LIST(ADD_STREAM_NAME);
 #undef ADD_STREAM_NAME
-    availableStreams.AddValue("VM");
   }
   {
     JSONArray recordedStreams(&obj, "recordedStreams");
@@ -266,11 +233,8 @@
     if (stream_##name##_enabled_) {                                            \
       recordedStreams.AddValue(#name);                                         \
     }
-ISOLATE_TIMELINE_STREAM_LIST(ADD_RECORDED_STREAM_NAME);
+TIMELINE_STREAM_LIST(ADD_RECORDED_STREAM_NAME);
 #undef ADD_RECORDED_STREAM_NAME
-    if (vm_stream_.enabled()) {
-      recordedStreams.AddValue("VM");
-    }
   }
 }
 
@@ -286,17 +250,15 @@
 
 
 TimelineEventRecorder* Timeline::recorder_ = NULL;
-TimelineStream Timeline::vm_stream_;
-TimelineStream Timeline::vm_api_stream_;
 MallocGrowableArray<char*>* Timeline::enabled_streams_ = NULL;
 Dart_EmbedderTimelineStartRecording Timeline::start_recording_cb_ = NULL;
 Dart_EmbedderTimelineStopRecording Timeline::stop_recording_cb_ = NULL;
-Dart_EmbedderTimelineGetTimeline Timeline::get_timeline_cb_ = NULL;
 
-#define ISOLATE_TIMELINE_STREAM_DEFINE_FLAG(name, enabled_by_default)          \
-  bool Timeline::stream_##name##_enabled_ = enabled_by_default;
-  ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_DEFINE_FLAG)
-#undef ISOLATE_TIMELINE_STREAM_DEFINE_FLAG
+#define TIMELINE_STREAM_DEFINE(name, enabled_by_default)                       \
+  bool Timeline::stream_##name##_enabled_ = enabled_by_default;                \
+  TimelineStream Timeline::stream_##name##_;
+  TIMELINE_STREAM_LIST(TIMELINE_STREAM_DEFINE)
+#undef TIMELINE_STREAM_DEFINE
 
 TimelineEvent::TimelineEvent()
     : timestamp0_(0),
@@ -1027,21 +989,13 @@
 }
 
 
-void TimelineEventRecorder::PrintEmbedderJSONEvents(JSONStream* events) {
-  if (Timeline::get_get_timeline_cb() != NULL) {
-    events->PrintCommaIfNeeded();
-    Timeline::get_get_timeline_cb()(AppendJSONStreamConsumer, events);
-  }
-}
-
-
 void TimelineEventRecorder::WriteTo(const char* directory) {
   if (!FLAG_support_service) {
     return;
   }
-  Dart_FileOpenCallback file_open = Isolate::file_open_callback();
-  Dart_FileWriteCallback file_write = Isolate::file_write_callback();
-  Dart_FileCloseCallback file_close = Isolate::file_close_callback();
+  Dart_FileOpenCallback file_open = Dart::file_open_callback();
+  Dart_FileWriteCallback file_write = Dart::file_write_callback();
+  Dart_FileCloseCallback file_close = Dart::file_close_callback();
   if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) {
     return;
   }
@@ -1174,7 +1128,6 @@
     JSONArray events(&topLevel, "traceEvents");
     PrintJSONMeta(&events);
     PrintJSONEvents(&events, filter);
-    PrintEmbedderJSONEvents(js);
   }
 }
 
@@ -1186,7 +1139,6 @@
   }
   JSONArray events(js);
   PrintJSONEvents(&events, filter);
-  PrintEmbedderJSONEvents(js);
 }
 
 
@@ -1309,7 +1261,6 @@
     JSONArray events(&topLevel, "traceEvents");
     PrintJSONMeta(&events);
     PrintJSONEvents(&events, filter);
-    PrintEmbedderJSONEvents(js);
   }
 }
 
@@ -1322,7 +1273,6 @@
   }
   JSONArray events(js);
   PrintJSONEvents(&events, filter);
-  PrintEmbedderJSONEvents(js);
 }
 
 
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
index 9887aff..f16056e 100644
--- a/runtime/vm/timeline.h
+++ b/runtime/vm/timeline.h
@@ -28,7 +28,7 @@
 class Zone;
 
 // (name, enabled by default for isolate).
-#define ISOLATE_TIMELINE_STREAM_LIST(V)                                        \
+#define TIMELINE_STREAM_LIST(V)                                                \
   V(API, false)                                                                \
   V(Compiler, false)                                                           \
   V(Dart, false)                                                               \
@@ -36,6 +36,7 @@
   V(Embedder, false)                                                           \
   V(GC, false)                                                                 \
   V(Isolate, false)                                                            \
+  V(VM, false)
 
 class Timeline : public AllStatic {
  public:
@@ -48,12 +49,6 @@
   // Access the global recorder. Not thread safe.
   static TimelineEventRecorder* recorder();
 
-  static void SetupIsolateStreams(Isolate* isolate);
-
-  static TimelineStream* GetVMStream();
-
-  static TimelineStream* GetVMApiStream();
-
   // Reclaim all |TimelineEventBlocks|s that are cached by threads.
   static void ReclaimCachedBlocksFromThreads();
 
@@ -62,7 +57,12 @@
   // Print information about streams to JSON.
   static void PrintFlagsToJSON(JSONStream* json);
 
-#define ISOLATE_TIMELINE_STREAM_FLAGS(name, not_used)                          \
+#define TIMELINE_STREAM_ACCESSOR(name, not_used)                       \
+  static TimelineStream* Get##name##Stream() { return &stream_##name##_; }
+  TIMELINE_STREAM_LIST(TIMELINE_STREAM_ACCESSOR)
+#undef TIMELINE_STREAM_ACCESSOR
+
+#define TIMELINE_STREAM_FLAGS(name, not_used)                                  \
   static const bool* Stream##name##EnabledFlag() {                             \
     return &stream_##name##_enabled_;                                          \
   }                                                                            \
@@ -70,9 +70,8 @@
     StreamStateChange(#name, stream_##name##_enabled_, enabled);               \
     stream_##name##_enabled_ = enabled;                                        \
   }
-  ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_FLAGS)
-#undef ISOLATE_TIMELINE_STREAM_FLAGS
-  static void SetVMStreamEnabled(bool enabled);
+  TIMELINE_STREAM_LIST(TIMELINE_STREAM_FLAGS)
+#undef TIMELINE_STREAM_FLAGS
 
   static void set_start_recording_cb(
       Dart_EmbedderTimelineStartRecording start_recording_cb) {
@@ -92,29 +91,18 @@
     return stop_recording_cb_;
   }
 
-  static void set_get_timeline_cb(
-      Dart_EmbedderTimelineGetTimeline get_timeline_cb) {
-    get_timeline_cb_ = get_timeline_cb;
-  }
-
-  static Dart_EmbedderTimelineGetTimeline get_get_timeline_cb() {
-    return get_timeline_cb_;
-  }
-
  private:
   static void StreamStateChange(const char* stream_name, bool prev, bool curr);
   static TimelineEventRecorder* recorder_;
-  static TimelineStream vm_stream_;
-  static TimelineStream vm_api_stream_;
   static MallocGrowableArray<char*>* enabled_streams_;
   static Dart_EmbedderTimelineStartRecording start_recording_cb_;
   static Dart_EmbedderTimelineStopRecording stop_recording_cb_;
-  static Dart_EmbedderTimelineGetTimeline get_timeline_cb_;
 
-#define ISOLATE_TIMELINE_STREAM_DECLARE_FLAG(name, not_used)                   \
-  static bool stream_##name##_enabled_;
-  ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_DECLARE_FLAG)
-#undef ISOLATE_TIMELINE_STREAM_DECLARE_FLAG
+#define TIMELINE_STREAM_DECLARE(name, not_used)                                \
+  static bool stream_##name##_enabled_;                                        \
+  static TimelineStream stream_##name##_;
+  TIMELINE_STREAM_LIST(TIMELINE_STREAM_DECLARE)
+#undef TIMELINE_STREAM_DECLARE
 
   friend class TimelineRecorderOverride;
   friend class ReclaimBlocksIsolateVisitor;
@@ -222,6 +210,10 @@
     return thread_;
   }
 
+  void set_thread(ThreadId tid) {
+    thread_ = tid;
+  }
+
   Dart_Port isolate_id() const {
     return isolate_id_;
   }
@@ -384,10 +376,10 @@
 };
 
 #ifndef PRODUCT
-#define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, suffix, function)       \
+#define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, name, function)         \
   TimelineDurationScope tds(thread,                                            \
-                            thread->isolate()->GetCompilerStream(),            \
-                            "Compile" suffix);                                 \
+                            Timeline::GetCompilerStream(),                     \
+                            name);                                             \
   if (tds.enabled()) {                                                         \
     tds.SetNumArguments(1);                                                    \
     tds.CopyArgument(                                                          \
@@ -395,8 +387,12 @@
         "function",                                                            \
         function.ToLibNamePrefixedQualifiedCString());                         \
   }
+
+#define TIMELINE_FUNCTION_GC_DURATION(thread, name)                            \
+  TimelineDurationScope tds(thread, Timeline::GetGCStream(), name);
 #else
-#define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, suffix, function)
+#define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, name, function)
+#define TIMELINE_FUNCTION_GC_DURATION(thread, name)
 #endif  // !PRODUCT
 
 // See |TimelineDurationScope| and |TimelineBeginEndScope|.
@@ -678,7 +674,6 @@
   void PrintJSONMeta(JSONArray* array) const;
   TimelineEvent* ThreadBlockStartEvent();
   void ThreadBlockCompleteEvent(TimelineEvent* event);
-  void PrintEmbedderJSONEvents(JSONStream* events);
 
   Mutex lock_;
   uintptr_t async_id_;
diff --git a/runtime/vm/vm.gypi b/runtime/vm/vm.gypi
index 0f857b3..a08a1b8 100644
--- a/runtime/vm/vm.gypi
+++ b/runtime/vm/vm.gypi
@@ -30,7 +30,6 @@
     'snapshot_test_in_dat_file': 'snapshot_test_in.dat',
     'snapshot_test_dart_file': 'snapshot_test.dart',
     'typed_data_cc_file': '<(gen_source_dir)/typed_data_gen.cc',
-    'typed_data_patch_cc_file': '<(gen_source_dir)/typed_data_patch_gen.cc',
     'vmservice_cc_file': '<(gen_source_dir)/vmservice_gen.cc',
     'vmservice_patch_cc_file': '<(gen_source_dir)/vmservice_patch_gen.cc',
   },
@@ -234,7 +233,6 @@
         'generate_mirrors_patch_cc_file#host',
         'generate_profiler_cc_file#host',
         'generate_typed_data_cc_file#host',
-        'generate_typed_data_patch_cc_file#host',
         'generate_vmservice_cc_file#host',
         'generate_vmservice_patch_cc_file#host',
       ],
@@ -273,7 +271,6 @@
         '<(mirrors_patch_cc_file)',
         '<(profiler_cc_file)',
         '<(typed_data_cc_file)',
-        '<(typed_data_patch_cc_file)',
         '<(vmservice_cc_file)',
         '<(vmservice_patch_cc_file)',
       ],
@@ -974,8 +971,8 @@
       'type': 'none',
       'toolsets':['host'],
       'includes': [
-        # Load the shared library sources.
-        '../../sdk/lib/typed_data/typed_data_sources.gypi',
+        # Load the runtime implementation sources.
+        '../lib/typed_data_sources.gypi',
       ],
       'sources/': [
         # Exclude all .[cc|h] files.
@@ -1010,46 +1007,6 @@
       ]
     },
     {
-      'target_name': 'generate_typed_data_patch_cc_file',
-      'type': 'none',
-      'toolsets':['host'],
-      'includes': [
-        # Load the runtime implementation sources.
-        '../lib/typed_data_sources.gypi',
-      ],
-      'sources/': [
-        # Exclude all .[cc|h] files.
-        # This is only here for reference. Excludes happen after
-        # variable expansion, so the script has to do its own
-        # exclude processing of the sources being passed.
-        ['exclude', '\\.cc|h$'],
-      ],
-      'actions': [
-        {
-          'action_name': 'generate_typed_data_patch_cc',
-          'inputs': [
-            '../tools/gen_library_src_paths.py',
-            '<(libgen_in_cc_file)',
-            '<@(_sources)',
-          ],
-          'outputs': [
-            '<(typed_data_patch_cc_file)',
-          ],
-          'action': [
-            'python',
-            'tools/gen_library_src_paths.py',
-            '--output', '<(typed_data_patch_cc_file)',
-            '--input_cc', '<(libgen_in_cc_file)',
-            '--include', 'vm/bootstrap.h',
-            '--var_name', 'dart::Bootstrap::typed_data_patch_paths_',
-            '--library_name', 'dart:typed_data',
-            '<@(_sources)',
-          ],
-          'message': 'Generating ''<(typed_data_patch_cc_file)'' file.'
-        },
-      ]
-    },
-    {
       'target_name': 'generate_profiler_cc_file',
       'type': 'none',
       'toolsets':['host'],
diff --git a/sdk/bin/dartdevc b/sdk/bin/dartdevc
new file mode 100755
index 0000000..331eb4e
--- /dev/null
+++ b/sdk/bin/dartdevc
@@ -0,0 +1,86 @@
+#!/usr/bin/env bash
+# Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# Run dev compiler on the Dart VM. This script assumes the Dart repo's
+# directory structure.
+
+function follow_links() {
+  file="$1"
+  while [ -h "$file" ]; do
+    # On Mac OS, readlink -f doesn't work.
+    file="$(readlink "$file")"
+  done
+  echo "$file"
+}
+
+# Unlike $0, $BASH_SOURCE points to the absolute path of this file.
+PROG_NAME="$(follow_links "$BASH_SOURCE")"
+
+# Handle the case where dart-sdk/bin has been symlinked to.
+BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
+SDK_DIR="$(cd "${BIN_DIR}/.." ; pwd -P)"
+
+SDK_ARG="--dart-sdk=$SDK_DIR"
+
+DART="$BIN_DIR/dart"
+
+unset EXTRA_VM_OPTIONS
+declare -a EXTRA_VM_OPTIONS
+
+case $0 in
+  *_developer)
+    EXTRA_VM_OPTIONS+=('--checked')
+    ;;
+esac
+
+# We allow extra vm options to be passed in through an environment variable.
+if [[ $DART_VM_OPTIONS ]]; then
+  read -a OPTIONS <<< "$DART_VM_OPTIONS"
+  EXTRA_VM_OPTIONS+=("${OPTIONS[@]}")
+fi
+
+DART_ROOT="$(cd "${SDK_DIR}/.." ; pwd -P)"
+
+DEV_COMPILER="$DART_ROOT/third_party/pkg/dev_compiler/bin/dartdevc.dart"
+
+if [[ `uname` == 'Darwin' ]];
+then
+  OUT_DIR="$DART_ROOT/xcodebuild/"
+else
+  OUT_DIR="$DART_ROOT/out/"
+fi
+
+if [ -z "$DART_CONFIGURATION" ];
+then
+  DIRS=$( ls "$OUT_DIR" )
+  # list of possible configurations in decreasing desirability
+  CONFIGS=("ReleaseX64" "ReleaseIA32" "DebugX64" "DebugIA32"
+    "ReleaseARM"    "ReleaseARM64"    "ReleaseARMV5TE"    "ReleaseMIPS"
+    "DebugARM"      "DebugARM64"      "DebugARMV5TE"      "DebugMIPS")
+  DART_CONFIGURATION="None"
+  for CONFIG in ${CONFIGS[*]}
+  do
+    for DIR in $DIRS;
+    do
+      if [ "$CONFIG" = "$DIR" ];
+      then
+        # choose most desirable configuration that is available and break
+        DART_CONFIGURATION="$DIR"
+        break 2
+      fi
+    done
+  done
+  if [ "$DART_CONFIGURATION" = "None" ]
+  then
+    echo "No valid dart configuration found in $OUT_DIR"
+    exit 1
+  fi
+fi
+
+BUILD_DIR="$OUT_DIR$DART_CONFIGURATION"
+
+PACKAGE_ROOT="$BUILD_DIR/packages/"
+
+exec "$DART" "${EXTRA_VM_OPTIONS[@]}" "--package-root=$PACKAGE_ROOT" "$DEV_COMPILER" "$SDK_ARG" "$@"
diff --git a/sdk/bin/dartdevc.bat b/sdk/bin/dartdevc.bat
new file mode 100644
index 0000000..4e02005
--- /dev/null
+++ b/sdk/bin/dartdevc.bat
@@ -0,0 +1,73 @@
+@echo off
+REM Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+REM for details. All rights reserved. Use of this source code is governed by a
+REM BSD-style license that can be found in the LICENSE file.
+
+setlocal
+rem Handle the case where dart-sdk/bin has been symlinked to.
+set DIR_NAME_WITH_SLASH=%~dp0
+set DIR_NAME=%DIR_NAME_WITH_SLASH:~0,-1%%
+call :follow_links "%DIR_NAME%", RETURNED_BIN_DIR
+rem Get rid of surrounding quotes.
+for %%i in ("%RETURNED_BIN_DIR%") do set BIN_DIR=%%~fi
+
+set DART=%BIN_DIR%\dart
+
+rem Get absolute full name for SDK_DIR.
+for %%i in ("%BIN_DIR%\..\") do set SDK_DIR=%%~fi
+
+rem Remove trailing backslash if there is one
+if %SDK_DIR:~-1%==\ set SDK_DIR=%SDK_DIR:~0,-1%
+
+set SDK_ARG=--dart-sdk=%SDK_DIR%
+
+set EXTRA_VM_OPTIONS=
+
+rem We allow extra vm options to be passed in through an environment variable.
+if not "_%DART_VM_OPTIONS%_" == "__" (
+  set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% %DART_VM_OPTIONS%
+)
+
+rem Get absolute full name for DART_ROOT.
+for %%i in ("%SDK_DIR%\..\") do set DART_ROOT=%%~fi
+
+rem Remove trailing backslash if there is one
+if %DART_ROOT:~-1%==\ set DART_ROOT=%DART_ROOT:~0,-1%
+
+set DEV_COMPILER=%DART_ROOT%\third_party\pkg\dev_compiler\bin\dartdevc.dart
+
+rem DART_CONFIGURATION defaults to ReleaseX64
+if "%DART_CONFIGURATION%"=="" set DART_CONFIGURATION=ReleaseX64
+
+set BUILD_DIR=%DART_ROOT%\build\%DART_CONFIGURATION%
+
+set PACKAGE_ROOT=%BUILD_DIR%\packages
+
+"%DART%" %EXTRA_VM_OPTIONS% "--package-root=%PACKAGE_ROOT%" "DEV_COMPILER%" "%SDK_ARG%" %*
+
+endlocal
+
+exit /b %errorlevel%
+
+rem Follow the symbolic links (junctions points) using `dir to determine the
+rem canonical path. Output with a link looks something like this
+rem
+rem 01/03/2013  10:11 PM    <JUNCTION>     abc def
+rem [c:\dart_bleeding\dart-repo.9\dart\build\ReleaseIA32\dart-sdk]
+rem
+rem So in the output of 'dir /a:l "targetdir"' we are looking for a filename
+rem surrounded by right angle bracket and left square bracket. Once we get
+rem the filename, which is name of the link, we recursively follow that.
+:follow_links
+setlocal
+for %%i in (%1) do set result=%%~fi
+set current=
+for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
+                                             ^| find ">     %~n1 ["`) do (
+  set current=%%i
+)
+if not "%current%"=="" call :follow_links "%current%", result
+endlocal & set %~2=%result%
+goto :eof
+
+:end
diff --git a/sdk/bin/dartdevc_sdk b/sdk/bin/dartdevc_sdk
new file mode 100755
index 0000000..7bc98de
--- /dev/null
+++ b/sdk/bin/dartdevc_sdk
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+# Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# Run dev compiler on the Dart VM. This script assumes the Dart SDK's
+# directory structure.
+
+function follow_links() {
+  file="$1"
+  while [ -h "$file" ]; do
+    # On Mac OS, readlink -f doesn't work.
+    file="$(readlink "$file")"
+  done
+  echo "$file"
+}
+
+# Unlike $0, $BASH_SOURCE points to the absolute path of this file.
+PROG_NAME="$(follow_links "$BASH_SOURCE")"
+
+# Handle the case where dart-sdk/bin has been symlinked to.
+BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
+SDK_DIR="$(cd "${BIN_DIR}/.." ; pwd -P)"
+
+SDK_ARG="--dart-sdk=$SDK_DIR"
+
+SNAPSHOT="$BIN_DIR/snapshots/dartdevc.dart.snapshot"
+
+# We are running the snapshot in the built SDK.
+DART="$BIN_DIR/dart"
+exec "$DART" "$SNAPSHOT" "$SDK_ARG" "$@"
diff --git a/sdk/bin/dartdevc_sdk.bat b/sdk/bin/dartdevc_sdk.bat
new file mode 100644
index 0000000..72c2069
--- /dev/null
+++ b/sdk/bin/dartdevc_sdk.bat
@@ -0,0 +1,52 @@
+@echo off
+REM Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+REM for details. All rights reserved. Use of this source code is governed by a
+REM BSD-style license that can be found in the LICENSE file.
+
+setlocal
+rem Handle the case where dart-sdk/bin has been symlinked to.
+set DIR_NAME_WITH_SLASH=%~dp0
+set DIR_NAME=%DIR_NAME_WITH_SLASH:~0,-1%%
+call :follow_links "%DIR_NAME%", RETURNED_BIN_DIR
+rem Get rid of surrounding quotes.
+for %%i in ("%RETURNED_BIN_DIR%") do set BIN_DIR=%%~fi
+
+set DART=%BIN_DIR%\dart
+set SNAPSHOT=%BIN_DIR%\snapshots\dartdevc.dart.snapshot
+
+rem Get absolute full name for SDK_DIR.
+for %%i in ("%BIN_DIR%\..\") do set SDK_DIR=%%~fi
+
+rem Remove trailing backslash if there is one
+if %SDK_DIR:~-1%==\ set SDK_DIR=%SDK_DIR:~0,-1%
+
+set SDK_ARG=--dart-sdk=%SDK_DIR%
+
+"%DART%" "%SNAPSHOT%" "%SDK_ARG%" %*
+
+endlocal
+
+exit /b %errorlevel%
+
+rem Follow the symbolic links (junctions points) using `dir to determine the
+rem canonical path. Output with a link looks something like this
+rem
+rem 01/03/2013  10:11 PM    <JUNCTION>     abc def
+rem [c:\dart_bleeding\dart-repo.9\dart\build\ReleaseIA32\dart-sdk]
+rem
+rem So in the output of 'dir /a:l "targetdir"' we are looking for a filename
+rem surrounded by right angle bracket and left square bracket. Once we get
+rem the filename, which is name of the link, we recursively follow that.
+:follow_links
+setlocal
+for %%i in (%1) do set result=%%~fi
+set current=
+for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
+                                             ^| find ">     %~n1 ["`) do (
+  set current=%%i
+)
+if not "%current%"=="" call :follow_links "%current%", result
+endlocal & set %~2=%result%
+goto :eof
+
+:end
diff --git a/sdk/lib/_internal/js_runtime/lib/io_patch.dart b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
index 350ab96..e403844 100644
--- a/sdk/lib/_internal/js_runtime/lib/io_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
@@ -420,6 +420,11 @@
   static SecurityContext get defaultContext {
     throw new UnsupportedError("default SecurityContext getter");
   }
+
+  @patch
+  static bool get alpnSupported {
+    throw new UnsupportedError("SecurityContext alpnSupported getter");
+  }
 }
 
 @patch
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index ad72431..8ca10c9 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -64,9 +64,11 @@
   static const int MASK_WHENCOMPLETE = 8;
   static const int STATE_CHAIN = 0;
   static const int STATE_THEN = MASK_VALUE;
-  static const int STATE_THEN_ONERROR = MASK_VALUE | MASK_ERROR;
+  // TODO(johnmccutchan): Remove the hard coded value. See #26030.
+  static const int STATE_THEN_ONERROR = 3;  // MASK_VALUE | MASK_ERROR.
   static const int STATE_CATCHERROR = MASK_ERROR;
-  static const int STATE_CATCHERROR_TEST = MASK_ERROR | MASK_TEST_ERROR;
+  // TODO(johnmccutchan): Remove the hard coded value. See #26030.
+  static const int STATE_CATCHERROR_TEST = 6;  // MASK_ERROR | MASK_TEST_ERROR.
   static const int STATE_WHENCOMPLETE = MASK_WHENCOMPLETE;
   // Listeners on the same future are linked through this link.
   _FutureListener _nextListener = null;
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index dc2593b..7b17154 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -34132,12 +34132,14 @@
   @DomName('VTTCue.line')
   @DocsEditable()
   @Experimental() // untriaged
+  @Creates('Null')
   @Returns('num|String')
   Object line;
 
   @DomName('VTTCue.position')
   @DocsEditable()
   @Experimental() // untriaged
+  @Creates('Null')
   @Returns('num|String')
   Object position;
 
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index cf8dec0..c271d77 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -970,8 +970,16 @@
 
     return _IOService._dispatch(_SSL_PROCESS_FILTER, args).then((response) {
       if (response.length == 2) {
-        _reportError(new TlsException('${response[1]} error ${response[0]}'),
-                     null);
+        if (wasInHandshake) {
+          // If we're in handshake, throw a handshake error.
+          _reportError(
+              new HandshakeException('${response[1]} error ${response[0]}'),
+              null);
+        } else {
+          // If we're connected, throw a TLS error.
+          _reportError(new TlsException('${response[1]} error ${response[0]}'),
+                       null);
+        }
       }
       int start(int index) => response[2 * index];
       int end(int index) => response[2 * index + 1];
diff --git a/sdk/lib/io/security_context.dart b/sdk/lib/io/security_context.dart
index 86dfc96..1e169af 100644
--- a/sdk/lib/io/security_context.dart
+++ b/sdk/lib/io/security_context.dart
@@ -126,6 +126,11 @@
   void setClientAuthoritiesBytes(List<int> authCertBytes, {String password});
 
   /**
+   * Whether the platform supports ALPN.
+   */
+  external static bool get alpnSupported;
+
+  /**
    * Sets the list of application-level protocols supported by a client
    * connection or server connection. The ALPN (application level protocol
    * negotiation) extension to TLS allows a client to send a list of
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 021b554..2d3d20f 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -3179,13 +3179,12 @@
 Language/Classes/Constructors/Factories/return_type_t05: Pass, Slow # Issue 25940
 
 [ $compiler == dart2js && $runtime == ff && $system != windows ]
-LayoutTests/fast/canvas/canvas-resetTransform_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/canvas-setTransform_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/xpath/4XPath/Core/test_parser_t01: RuntimeError # Dartium JSInterop failure
 LayoutTests/fast/xpath/py-dom-xpath/abbreviations_t01: RuntimeError # Dartium JSInterop failure
 
 [ $compiler == dart2js && $runtime == ff && $system == linux]
 LayoutTests/fast/canvas/canvas-composite-text-alpha_t01: RuntimeError # co19 issue 16
+LayoutTests/fast/text/whitespace/nowrap-line-break-after-white-space_t01: Pass, RuntimeError # Please triage this failure
 
 [ $compiler == dart2js && $runtime == safari ]
 LayoutTests/fast/alignment/parse-align-items_t01: RuntimeError # Please triage this failure
diff --git a/tests/compiler/dart2js/analyze_helper.dart b/tests/compiler/dart2js/analyze_helper.dart
index 41dc321..8db5912 100644
--- a/tests/compiler/dart2js/analyze_helper.dart
+++ b/tests/compiler/dart2js/analyze_helper.dart
@@ -7,6 +7,7 @@
 import 'dart:async';
 import 'dart:io';
 import 'package:compiler/compiler.dart' as api;
+import 'package:compiler/compiler_new.dart' as new_api;
 import 'package:compiler/src/apiimpl.dart';
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/diagnostics/messages.dart' show
@@ -194,10 +195,11 @@
       provider,
       null,
       handler,
-      libraryRoot,
-      packageRoot,
-      options,
-      {});
+      new new_api.CompilerOptions.parse(
+          libraryRoot: libraryRoot,
+          packageRoot: packageRoot,
+          options: options,
+          environment: {}));
   String MESSAGE = """
 
 
diff --git a/tests/compiler/dart2js/bad_loop_test.dart b/tests/compiler/dart2js/bad_loop_test.dart
index c1b2a6d..525aa8c 100644
--- a/tests/compiler/dart2js/bad_loop_test.dart
+++ b/tests/compiler/dart2js/bad_loop_test.dart
@@ -8,7 +8,7 @@
 
 import 'package:compiler/compiler.dart'
        show Diagnostic;
-import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/compiler_new.dart' show CompilerOptions;
 import 'package:compiler/src/old_to_new_api.dart';
 
 main() {
@@ -37,10 +37,9 @@
       new LegacyCompilerInput(provider.readStringFromUri),
       new LegacyCompilerOutput(),
       new LegacyCompilerDiagnostics(diagnosticHandler),
-      libraryRoot,
-      packageRoot,
-      [Flags.analyzeOnly],
-      {});
+      new CompilerOptions(
+        libraryRoot: libraryRoot,
+        packageRoot: packageRoot));
   asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
     Expect.isTrue(compiler.compilationFailed);
     Expect.equals(5, errorCount);
diff --git a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
index 517a347..123ae7e 100644
--- a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
+++ b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
@@ -14,8 +14,7 @@
                     bool disableInlining,
                     check(compiler, element)) {
   Uri uri = new Uri(scheme: 'source');
-  var compiler = compilerFor(code, uri);
-  compiler.disableInlining = disableInlining;
+  var compiler = compilerFor(code, uri, disableInlining: disableInlining);
   asyncTest(() => compiler.run(uri).then((_) {
     var cls = findElement(compiler, className);
     var member = cls.lookupLocalMember(memberName);
diff --git a/tests/compiler/dart2js/codegen_helper.dart b/tests/compiler/dart2js/codegen_helper.dart
index c99fc49..1e1dec8 100644
--- a/tests/compiler/dart2js/codegen_helper.dart
+++ b/tests/compiler/dart2js/codegen_helper.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 import 'package:expect/expect.dart';
+import 'package:compiler/compiler_new.dart' show CompilerOptions;
 import 'package:compiler/src/null_compiler_output.dart';
 import 'memory_source_file_helper.dart';
 
@@ -16,14 +17,15 @@
   var provider = new MemorySourceFileProvider({ 'main.dart': code });
   var handler = new FormattingDiagnosticHandler(provider);
 
+  Uri uri = Uri.parse('memory:main.dart');
   CompilerImpl compiler = new CompilerImpl(provider,
                                    const NullCompilerOutput(),
                                    handler,
-                                   libraryRoot,
-                                   packageRoot,
-                                   options,
-                                   {});
-  Uri uri = Uri.parse('memory:main.dart');
+                                   new CompilerOptions.parse(
+                                       entryPoint: uri,
+                                       libraryRoot: libraryRoot,
+                                       packageRoot: packageRoot,
+                                       options: options));
   return compiler.run(uri).then((success) {
     Expect.isTrue(success);
     Map<String, String> result = new Map<String, String>();
diff --git a/tests/compiler/dart2js/compiler_helper.dart b/tests/compiler/dart2js/compiler_helper.dart
index bef0984..e365f3b 100644
--- a/tests/compiler/dart2js/compiler_helper.dart
+++ b/tests/compiler/dart2js/compiler_helper.dart
@@ -112,6 +112,10 @@
       options.add(Flags.trustJSInteropTypeAnnotations);
     }
 
+    if (disableInlining) {
+      options.add(Flags.disableInlining);
+    }
+
     Map<String, String> source;
     if (entry != 'main') {
       source = {'main.dart': "$code\n\nmain() => $entry;" };
@@ -122,12 +126,7 @@
     CompilationResult result = await runCompiler(
         memorySourceFiles: source,
         options: options,
-        outputProvider: outputCollector,
-        beforeRun: (compiler) {
-          if (disableInlining) {
-            compiler.disableInlining = true;
-          }
-        });
+        outputProvider: outputCollector);
     Expect.isTrue(result.isSuccess);
     Compiler compiler =  result.compiler;
     lego.Element element = compiler.mainApp.find(entry);
diff --git a/tests/compiler/dart2js/exit_code_test.dart b/tests/compiler/dart2js/exit_code_test.dart
index e5263e4..ec9c160 100644
--- a/tests/compiler/dart2js/exit_code_test.dart
+++ b/tests/compiler/dart2js/exit_code_test.dart
@@ -50,8 +50,14 @@
                String this.testMarker,
                String this.testType,
                Function this.onTest)
-      : super(inputProvider, outputProvider, handler, libraryRoot,
-              packageRoot, options, environment, packageConfig, findPackages) {
+      : super(inputProvider, outputProvider, handler,
+            new api.CompilerOptions.parse(
+                libraryRoot: libraryRoot,
+                packageRoot: packageRoot,
+                options: options,
+                environment: environment,
+                packageConfig: packageConfig,
+                packagesDiscoveryProvider: findPackages)) {
     scanner = new TestScanner(this);
     resolver = new TestResolver(this, backend.constantCompilerTask);
     reporter = new TestDiagnosticReporter(this, super.reporter);
diff --git a/tests/compiler/dart2js/field_type_simple_inferer_test.dart b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
index 7eeb5f9..534a7ed 100644
--- a/tests/compiler/dart2js/field_type_simple_inferer_test.dart
+++ b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
@@ -16,9 +16,9 @@
                     bool disableInlining,
                     check(compiler, element)) {
   Uri uri = new Uri(scheme: 'source');
-  var compiler = compilerFor(code, uri);
+  var compiler = compilerFor(code, uri,
+      disableInlining: disableInlining);
   asyncTest(() => compiler.run(uri).then((_) {
-    compiler.disableInlining = disableInlining;
     var cls = findElement(compiler, className);
     var member = cls.lookupMember(memberName);
     check(compiler, member);
diff --git a/tests/compiler/dart2js/incremental/compile_all.dart b/tests/compiler/dart2js/incremental/compile_all.dart
index 9d62061..fb22d15 100644
--- a/tests/compiler/dart2js/incremental/compile_all.dart
+++ b/tests/compiler/dart2js/incremental/compile_all.dart
@@ -53,7 +53,7 @@
       inputProvider: memoryCompiler.provider,
       outputProvider: memoryCompiler.userOutputProvider,
       diagnosticHandler: memoryCompiler.handler,
-      packageRoot: memoryCompiler.packageRoot,
+      packageRoot: memoryCompiler.options.packageRoot,
       options: options);
   Future.forEach(sources.keys, (String path) {
     UserTag.defaultTag.makeCurrent();
diff --git a/tests/compiler/dart2js/library_env_test.dart b/tests/compiler/dart2js/library_env_test.dart
index 0f0ff6d..7f377cf 100644
--- a/tests/compiler/dart2js/library_env_test.dart
+++ b/tests/compiler/dart2js/library_env_test.dart
@@ -24,7 +24,8 @@
 
 import 'package:compiler/compiler_new.dart' show
     CompilerInput,
-    CompilerDiagnostics;
+    CompilerDiagnostics,
+    CompilerOptions;
 
 import 'package:sdk_library_metadata/libraries.dart' show
     LibraryInfo;
@@ -80,23 +81,19 @@
 }
 
 class CustomCompiler extends CompilerImpl {
-  CustomCompiler(
-      options,
-      environment)
+  CustomCompiler(options, environment)
       : super(
           const DummyCompilerInput(),
           const NullCompilerOutput(),
           const DummyCompilerDiagnostics(),
-          Uri.base.resolve("sdk/"),
-          null,
-          options,
-          environment);
+          new CompilerOptions.parse(
+              libraryRoot: Uri.base.resolve("sdk/"),
+              options: options,
+              environment: environment));
 }
 
 runTest() async {
-  var compiler = new CustomCompiler(
-      [],
-      {});
+  var compiler = new CustomCompiler([], {});
 
   await compiler.setupSdk();
 
@@ -113,9 +110,7 @@
   Expect.equals(null, compiler.fromEnvironment("dart.library.mock.server"));
   Expect.equals(null, compiler.fromEnvironment("dart.library.io"));
 
-  compiler = new CustomCompiler(
-      ['--categories=Server'],
-      {});
+  compiler = new CustomCompiler(['--categories=Server'], {});
 
   await compiler.setupSdk();
 
@@ -133,8 +128,7 @@
   Expect.equals("true", compiler.fromEnvironment("dart.library.io"));
 
   // Check that user-defined env-variables win.
-  compiler = new CustomCompiler(
-      [],
+  compiler = new CustomCompiler([],
       {'dart.library.collection': "false",
        'dart.library.mock.client': "foo"});
 
@@ -149,4 +143,4 @@
   runTest().then((_) {
     asyncEnd();
   });
-}
\ No newline at end of file
+}
diff --git a/tests/compiler/dart2js/library_resolution_test.dart b/tests/compiler/dart2js/library_resolution_test.dart
index 28ad567..23e4a0a 100644
--- a/tests/compiler/dart2js/library_resolution_test.dart
+++ b/tests/compiler/dart2js/library_resolution_test.dart
@@ -25,16 +25,18 @@
 
 import 'package:compiler/src/old_to_new_api.dart'
     show LegacyCompilerDiagnostics, LegacyCompilerInput;
+import 'package:compiler/compiler_new.dart' show CompilerOptions;
 
 Uri sdkRoot = Uri.base.resolve("sdk/");
 Uri mock1LibraryUri = sdkRoot.resolve("lib/mock1.dart");
 Uri mock2LibraryUri = sdkRoot.resolve("lib/mock2.dart");
 
 class CustomCompiler extends CompilerImpl {
-  CustomCompiler(provider, handler, libraryRoot,
-      packageRoot, options, environment)
-      : super(provider, const NullCompilerOutput(), handler, libraryRoot,
-            packageRoot, options, environment);
+  CustomCompiler(provider, handler, libraryRoot, packageRoot)
+      : super(provider, const NullCompilerOutput(), handler,
+            new CompilerOptions(
+                libraryRoot: libraryRoot,
+                packageRoot: packageRoot));
 
   Uri lookupLibraryUri(String libraryName) {
     if (libraryName == "m_o_c_k_1") return mock1LibraryUri;
@@ -81,9 +83,7 @@
       new LegacyCompilerInput(wrappedProvider),
       new LegacyCompilerDiagnostics(wrappedHandler),
       sdkRoot,
-      packageRoot,
-      [],
-      {});
+      packageRoot);
 
   asyncStart();
   await compiler.setupSdk();
diff --git a/tests/compiler/dart2js/memory_compiler.dart b/tests/compiler/dart2js/memory_compiler.dart
index fa69df7..df9807e 100644
--- a/tests/compiler/dart2js/memory_compiler.dart
+++ b/tests/compiler/dart2js/memory_compiler.dart
@@ -11,6 +11,7 @@
 import 'package:compiler/compiler_new.dart' show
     CompilationResult,
     CompilerDiagnostics,
+    CompilerOptions,
     CompilerOutput,
     Diagnostic,
     PackagesDiscoveryProvider;
@@ -84,6 +85,7 @@
     entryPoint = Uri.parse('memory:main.dart');
   }
   CompilerImpl compiler = compilerFor(
+      entryPoint: entryPoint,
       memorySourceFiles: memorySourceFiles,
       diagnosticHandler: diagnosticHandler,
       outputProvider: outputProvider,
@@ -102,7 +104,8 @@
 }
 
 CompilerImpl compilerFor(
-    {Map<String, String> memorySourceFiles: const <String, String>{},
+    {Uri entryPoint,
+     Map<String, String> memorySourceFiles: const <String, String>{},
      CompilerDiagnostics diagnosticHandler,
      CompilerOutput outputProvider,
      List<String> options: const <String>[],
@@ -143,12 +146,14 @@
       provider,
       outputProvider,
       diagnosticHandler,
-      libraryRoot,
-      packageRoot,
-      options,
-      {},
-      packageConfig,
-      packagesDiscoveryProvider);
+      new CompilerOptions.parse(
+          entryPoint: entryPoint,
+          libraryRoot: libraryRoot,
+          packageRoot: packageRoot,
+          options: options,
+          environment: {},
+          packageConfig: packageConfig,
+          packagesDiscoveryProvider: packagesDiscoveryProvider));
 
   if (cachedCompiler != null) {
     compiler.coreLibrary =
@@ -213,7 +218,6 @@
     cachedCompiler.deferredLoadTask = null;
     cachedCompiler.mirrorUsageAnalyzerTask = null;
     cachedCompiler.dumpInfoTask = null;
-    cachedCompiler.buildId = null;
   }
   return compiler;
 }
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 11b450d..2d4862c 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -9,6 +9,7 @@
 import 'dart:collection';
 
 import 'package:compiler/compiler.dart' as api;
+import 'package:compiler/compiler_new.dart' as new_api;
 import 'package:compiler/src/common/names.dart' show
     Uris;
 import 'package:compiler/src/constants/expressions.dart';
@@ -69,7 +70,6 @@
        bool enableTypeAssertions: false,
        bool enableUserAssertions: false,
        bool enableMinification: false,
-       int maxConcreteTypeSize: 5,
        bool disableTypeInference: false,
        bool analyzeAll: false,
        bool analyzeOnly: false,
@@ -88,22 +88,24 @@
        LibrarySourceProvider this.librariesOverride})
       : sourceFiles = new Map<String, SourceFile>(),
         testedPatchVersion = patchVersion,
-        super(enableTypeAssertions: enableTypeAssertions,
+        super(options: new new_api.CompilerOptions(
+              entryPoint: new Uri(scheme: 'mock'),
+              libraryRoot: Uri.parse('placeholder_library_root_for_mock/'),
+              enableTypeAssertions: enableTypeAssertions,
               enableUserAssertions: enableUserAssertions,
+              disableInlining: disableInlining,
               enableAssertMessage: true,
               enableMinification: enableMinification,
-              maxConcreteTypeSize: maxConcreteTypeSize,
-              disableTypeInferenceFlag: disableTypeInference,
-              analyzeAllFlag: analyzeAll,
+              disableTypeInference: disableTypeInference,
+              analyzeAll: analyzeAll,
               analyzeOnly: analyzeOnly,
               emitJavaScript: emitJavaScript,
               preserveComments: preserveComments,
               trustTypeAnnotations: trustTypeAnnotations,
               trustJSInteropTypeAnnotations: trustJSInteropTypeAnnotations,
               diagnosticOptions:
-                  new DiagnosticOptions(shownPackageWarnings: const []),
+                  new DiagnosticOptions(shownPackageWarnings: const [])),
               outputProvider: new LegacyCompilerOutput(outputProvider)) {
-    this.disableInlining = disableInlining;
 
     deferredLoadTask = new MockDeferredLoadTask(this);
 
diff --git a/tests/compiler/dart2js/serialization_analysis_test.dart b/tests/compiler/dart2js/serialization_analysis_test.dart
index ffef134..e8c651d 100644
--- a/tests/compiler/dart2js/serialization_analysis_test.dart
+++ b/tests/compiler/dart2js/serialization_analysis_test.dart
@@ -8,11 +8,15 @@
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
 import 'package:compiler/src/commandline_options.dart';
-import 'package:compiler/src/elements/elements.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/serialization/serialization.dart';
+import 'package:compiler/src/serialization/element_serialization.dart';
+import 'package:compiler/src/serialization/impact_serialization.dart';
 import 'package:compiler/src/serialization/json_serializer.dart';
+import 'package:compiler/src/serialization/serialization.dart';
 import 'package:compiler/src/serialization/task.dart';
 import 'package:compiler/src/universe/world_impact.dart';
 import 'memory_compiler.dart';
@@ -142,6 +146,61 @@
   },
   expectedWarningCount: 1,
   expectedInfoCount: 1),
+
+  const Test(const {
+    'main.dart': r'''
+import 'dart:math';
+
+class MyRandom implements Random {
+  int nextInt(int max) {
+    return max.length;
+  }
+  bool nextBool() => true;
+  double nextDouble() => 0.0;
+}
+main() {
+  new MyRandom().nextInt(0);
+}'''
+  },
+  expectedWarningCount: 1,
+  expectedInfoCount: 0),
+
+  const Test(const {
+    'main.dart': r'''
+import 'dart:math';
+
+class MyRandom implements Random {
+  int nextInt(int max) {
+    return max.length;
+  }
+  bool nextBool() => true;
+  double nextDouble() => 0.0;
+}
+main() {
+  new MyRandom();
+}'''
+  }),
+
+  const Test(const {
+    'main.dart': r'''
+import 'dart:math';
+
+class MyRandom implements Random {
+  int nextInt(int max) {
+    return max.length;
+  }
+  bool nextBool() => true;
+  double nextDouble() => 0.0;
+}
+main() {
+  // Invocation of `MyRandom.nextInt` is only detected knowing the actual 
+  // implementation class for `List` and the world impact of its `shuffle` 
+  // method.  
+  [].shuffle(new MyRandom());
+}'''
+  },
+  expectedWarningCount: 1,
+  expectedInfoCount: 0),
 ];
 
 main(List<String> arguments) {
@@ -175,15 +234,17 @@
 }
 
 Future analyze(String serializedData, Uri entryPoint, Test test) async {
-  Deserializer deserializer = new Deserializer.fromText(
-      serializedData, const JsonSerializationDecoder());
   DiagnosticCollector diagnosticCollector = new DiagnosticCollector();
   await runCompiler(
       entryPoint: entryPoint,
       memorySourceFiles: test != null ? test.sourceFiles : const {},
-      options: [Flags.analyzeOnly, '--output-type=dart'],
+      options: [Flags.analyzeOnly],
       diagnosticHandler: diagnosticCollector,
       beforeRun: (Compiler compiler) {
+        Deserializer deserializer = new Deserializer.fromText(
+            serializedData,
+            const JsonSerializationDecoder());
+        deserializer.plugins.add(compiler.backend.serialization.deserializer);
         compiler.serialization.deserializer =
             new _DeserializerSystem(deserializer);
       });
@@ -203,24 +264,61 @@
 
 Future<String> serializeDartCore() async {
   Compiler compiler = compilerFor(
-      options: ['--analyze-all', '--output-type=dart']);
-  await compiler.run(Uri.parse('dart:core'));
-  return serialize(compiler.libraryLoader.libraries);
+      options: [Flags.analyzeAll]);
+  compiler.serialization.supportSerialization = true;
+  await compiler.run(Uris.dart_core);
+  return serialize(compiler);
 }
 
-String serialize(Iterable<LibraryElement> libraries) {
+String serialize(Compiler compiler) {
   Serializer serializer = new Serializer(const JsonSerializationEncoder());
-  for (LibraryElement library in libraries) {
+  serializer.plugins.add(compiler.backend.serialization.serializer);
+  serializer.plugins.add(new WorldImpactSerializer(compiler.resolution));
+
+  for (LibraryElement library in compiler.libraryLoader.libraries) {
     serializer.serialize(library);
   }
   return serializer.toText();
 }
 
+const String WORLD_IMPACT_TAG = 'worldImpact';
+
+class WorldImpactSerializer extends SerializerPlugin {
+  final Resolution resolution;
+
+  WorldImpactSerializer(this.resolution);
+
+  @override
+  void onElement(Element element, ObjectEncoder createEncoder(String tag)) {
+    if (resolution.hasBeenResolved(element)) {
+      WorldImpact impact = resolution.getWorldImpact(element);
+      ObjectEncoder encoder = createEncoder(WORLD_IMPACT_TAG);
+      impact.apply(new ImpactSerializer(encoder));
+    }
+  }
+}
+
+class WorldImpactDeserializer extends DeserializerPlugin {
+  Map<Element, WorldImpact> impactMap = <Element, WorldImpact>{};
+
+  @override
+  void onElement(Element element, ObjectDecoder getDecoder(String tag)) {
+    ObjectDecoder decoder = getDecoder(WORLD_IMPACT_TAG);
+    if (decoder != null) {
+      impactMap[element] = ImpactDeserializer.deserializeImpact(decoder);
+    }
+  }
+}
+
 class _DeserializerSystem extends DeserializerSystem {
   final Deserializer _deserializer;
   final List<LibraryElement> deserializedLibraries = <LibraryElement>[];
+  final WorldImpactDeserializer _worldImpactDeserializer =
+      new WorldImpactDeserializer();
 
-  _DeserializerSystem(this._deserializer);
+  _DeserializerSystem(this._deserializer) {
+    _deserializer.plugins.add(_worldImpactDeserializer);
+  }
 
   LibraryElement readLibrary(Uri resolvedUri) {
     LibraryElement library = _deserializer.lookupLibrary(resolvedUri);
@@ -232,11 +330,16 @@
 
   @override
   WorldImpact computeWorldImpact(Element element) {
-    return const WorldImpact();
+    WorldImpact impact = _worldImpactDeserializer.impactMap[element];
+    if (impact == null) {
+      print('No impact found for $element (${element.library})');
+      impact = const WorldImpact();
+    }
+    return impact;
   }
 
   @override
   bool isDeserialized(Element element) {
     return deserializedLibraries.contains(element.library);
   }
-}
\ No newline at end of file
+}
diff --git a/tests/compiler/dart2js/serialization_test.dart b/tests/compiler/dart2js/serialization_test.dart
index c913a3c..3522c41 100644
--- a/tests/compiler/dart2js/serialization_test.dart
+++ b/tests/compiler/dart2js/serialization_test.dart
@@ -15,9 +15,9 @@
 import 'package:compiler/src/elements/elements.dart';
 import 'package:compiler/src/elements/visitor.dart';
 import 'package:compiler/src/ordered_typeset.dart';
-import 'package:compiler/src/serialization/serialization.dart';
+import 'package:compiler/src/serialization/element_serialization.dart';
 import 'package:compiler/src/serialization/json_serializer.dart';
-import 'package:compiler/src/tree/tree.dart';
+import 'package:compiler/src/serialization/serialization.dart';
 
 main(List<String> arguments) {
   // Ensure that we can print out constant expressions.
@@ -342,6 +342,10 @@
   const ElementIdentityEquivalence();
 
   void visit(Element element1, Element element2) {
+    if (element1 == null && element2 == null) return;
+    element1 = element1.declaration;
+    element2 = element2.declaration;
+    if (element1 == element2) return;
     check(element1, element2, 'kind', element1.kind, element2.kind);
     element1.accept(this, element2);
   }
@@ -454,6 +458,9 @@
   const ElementPropertyEquivalence();
 
   void visit(Element element1, Element element2) {
+    if (element1 == null && element2 == null) return;
+    element1 = element1.declaration;
+    element2 = element2.declaration;
     if (element1 == element2) return;
     check(element1, element2, 'kind', element1.kind, element2.kind);
     element1.accept(this, element2);
@@ -472,41 +479,28 @@
           element1.libraryName, element2.libraryName);
     visitMembers(element1, element2);
     visit(element1.entryCompilationUnit, element2.entryCompilationUnit);
+
     checkElementLists(
         element1, element2, 'compilationUnits',
-        element1.compilationUnits.toList(),
-        element2.compilationUnits.toList());
+        LibrarySerializer.getCompilationUnits(element1),
+        LibrarySerializer.getCompilationUnits(element2));
 
     checkElementListIdentities(
-        element1, element2, 'imports', element1.imports, element2.imports);
+        element1, element2, 'imports',
+        LibrarySerializer.getImports(element1),
+        LibrarySerializer.getImports(element2));
     checkElementListIdentities(
         element1, element2, 'exports', element1.exports, element2.exports);
 
-    List<Element> imports1 = <Element>[];
-    List<Element> imports2 = <Element>[];
-    element1.forEachImport((Element import) {
-      if (import.isAmbiguous) return;
-      imports1.add(import);
-    });
-    element2.forEachImport((Element import) {
-      if (import.isAmbiguous) return;
-      imports2.add(import);
-    });
     checkElementListIdentities(
-        element1, element2, 'importScope', imports1, imports2);
+        element1, element2, 'importScope',
+        LibrarySerializer.getImportedElements(element1),
+        LibrarySerializer.getImportedElements(element2));
 
-    List<Element> exports1 = <Element>[];
-    List<Element> exports2 = <Element>[];
-    element1.forEachExport((Element export) {
-      if (export.isAmbiguous) return;
-      exports1.add(export);
-    });
-    element2.forEachExport((Element export) {
-      if (export.isAmbiguous) return;
-      exports2.add(export);
-    });
     checkElementListIdentities(
-        element1, element2, 'exportScope', exports1, exports2);
+        element1, element2, 'exportScope',
+        LibrarySerializer.getExportedElements(element1),
+        LibrarySerializer.getExportedElements(element2));
   }
 
   @override
@@ -536,21 +530,29 @@
   void visitMembers(ScopeContainerElement element1,
                     ScopeContainerElement element2) {
     Set<String> names = new Set<String>();
-    element1.forEachLocalMember((Element member) {
+    Iterable<Element> members1 = element1.isLibrary
+        ? LibrarySerializer.getMembers(element1)
+        : ClassSerializer.getMembers(element1);
+    Iterable<Element> members2 = element2.isLibrary
+        ? LibrarySerializer.getMembers(element2)
+        : ClassSerializer.getMembers(element2);
+    for (Element member in members1) {
       names.add(member.name);
-    });
-    element2.forEachLocalMember((Element member) {
+    }
+    for (Element member in members2) {
       names.add(member.name);
-    });
+    }
+    element1 = element1.implementation;
+    element2 = element2.implementation;
     for (String name in names) {
       Element member1 = element1.localLookup(name);
       Element member2 = element2.localLookup(name);
       if (member1 == null) {
-        print('Missing member for $member2');
+        print('Missing member for $member2 in\n ${members1.join('\n ')}');
         continue;
       }
       if (member2 == null) {
-        print('Missing member for $member1');
+        print('Missing member for $member1 in\n ${members2.join('\n ')}');
         continue;
       }
       visit(member1, member2);
@@ -576,6 +578,16 @@
         element1.typeVariables, element2.typeVariables);
     check(element1, element2, 'isAbstract',
         element1.isAbstract, element2.isAbstract);
+    check(element1, element2, 'isUnnamedMixinApplication',
+        element1.isUnnamedMixinApplication, element2.isUnnamedMixinApplication);
+    check(element1, element2, 'isEnumClass',
+        element1.isEnumClass, element2.isEnumClass);
+    if (element1.isEnumClass) {
+      EnumClassElement enum1 = element1;
+      EnumClassElement enum2 = element2;
+      checkElementLists(enum1, enum2, 'enumValues',
+                        enum1.enumValues, enum2.enumValues);
+    }
     if (!element1.isObject) {
       checkTypes(element1, element2, 'supertype',
           element1.supertype, element2.supertype);
diff --git a/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart b/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
index cb78cd4..9bc1ac8 100644
--- a/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
@@ -272,8 +272,6 @@
   }
 }
 
-const String DISABLE_INLINING = '--disable-inlining';
-
 /// Processor that computes [SourceMapInfo] for the JavaScript compiled for a
 /// given Dart file.
 class SourceMapProcessor {
@@ -315,15 +313,14 @@
     if (options.contains(Flags.useNewSourceInfo)) {
       if (verbose) print('Using the new source information system.');
     }
+    if (options.contains(Flags.disableInlining)) {
+      if (verbose) print('Inlining disabled');
+    }
     api.CompilerImpl compiler = await compilerFor(
         outputProvider: outputProvider,
         // TODO(johnniwinther): Use [verbose] to avoid showing diagnostics.
         options: ['--out=$targetUri', '--source-map=$sourceMapFileUri']
             ..addAll(options));
-    if (options.contains(DISABLE_INLINING)) {
-      if (verbose) print('Inlining disabled');
-      compiler.disableInlining = true;
-    }
 
     JavaScriptBackend backend = compiler.backend;
     var handler = compiler.handler;
diff --git a/tests/compiler/dart2js/type_test_helper.dart b/tests/compiler/dart2js/type_test_helper.dart
index fc04a58..1e20ba7 100644
--- a/tests/compiler/dart2js/type_test_helper.dart
+++ b/tests/compiler/dart2js/type_test_helper.dart
@@ -62,6 +62,7 @@
       collector = new memory.DiagnosticCollector();
       uri = Uri.parse('memory:main.dart');
       compiler = memory.compilerFor(
+          entryPoint: uri,
           memorySourceFiles: {'main.dart': source},
           diagnosticHandler: collector,
           options: stopAfterTypeInference
diff --git a/tests/html/html.status b/tests/html/html.status
index 5b30a0a..c7df0fe 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -45,7 +45,6 @@
 [ $compiler == dart2js && $browser ]
 custom/created_callback_test: Fail # Support for created constructor. Issue 14835
 fontface_loaded_test: Fail # Support for promises.
-js_typed_interop_side_cast_exp_test: RuntimeError # Issue 25937
 
 [ $compiler == dart2js && ($runtime == safari || $runtime == safarimobilesim || $runtime == ff  || $ie) ]
 custom/entered_left_view_test/viewless_document: Fail # Polyfill does not handle this
diff --git a/tests/isolate/scenarios/bad_resolve_package/.packages b/tests/isolate/scenarios/bad_resolve_package/.packages
new file mode 100644
index 0000000..5acc702
--- /dev/null
+++ b/tests/isolate/scenarios/bad_resolve_package/.packages
@@ -0,0 +1 @@
+# Intentionally left blank to ensure no packages are resolved.
diff --git a/tests/isolate/scenarios/bad_resolve_package/bad_resolve_package_test.dart b/tests/isolate/scenarios/bad_resolve_package/bad_resolve_package_test.dart
new file mode 100644
index 0000000..c8017e1
--- /dev/null
+++ b/tests/isolate/scenarios/bad_resolve_package/bad_resolve_package_test.dart
@@ -0,0 +1,47 @@
+// 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.
+
+// PackageRoot=none
+
+import 'dart:io';
+import 'dart:isolate';
+
+main([args, port]) async {
+  if (port != null) {
+    testBadResolvePackage(port);
+    return;
+  }
+  var p = new RawReceivePort();
+  Isolate.spawnUri(Platform.script, [], p.sendPort);
+  p.handler = (msg) {
+    p.close();
+    if (msg is! List) {
+      print(msg.runtimeType);
+      throw "Failure return from spawned isolate:\n\n$msg";
+    }
+    // Expecting a null resolution for inexistent package mapping.
+    if (msg[0] != null) {
+      throw "Bad package config in child isolate: ${msg[0]}\n"
+            "Expected: 'Foo'";
+    }
+    print("SUCCESS");
+  };
+}
+
+testBadResolvePackage(port) async {
+  try {
+    var packageRootStr = Platform.packageRoot;
+    var packageConfigStr = Platform.packageConfig;
+    var packageConfig = await Isolate.packageConfig;
+    var badPackageUri = Uri.parse("package:asdf/qwerty.dart");
+    var resolvedPkg = await Isolate.resolvePackageUri(badPackageUri);
+    print("Spawned isolate's package root flag: $packageRootStr");
+    print("Spawned isolate's package config flag: $packageConfigStr");
+    print("Spawned isolate's loaded package config: $packageConfig");
+    print("Spawned isolate's resolved package path: $resolvedPkg");
+    port.send([resolvedPkg]);
+  } catch (e, s) {
+    port.send("$e\n$s\n");
+  }
+}
diff --git a/tests/isolate/scenarios/short_package/.packages b/tests/isolate/scenarios/short_package/.packages
new file mode 100644
index 0000000..324934c
--- /dev/null
+++ b/tests/isolate/scenarios/short_package/.packages
@@ -0,0 +1 @@
+flu:flu_package/
diff --git a/tests/isolate/scenarios/short_package/flu_package/flu.dart b/tests/isolate/scenarios/short_package/flu_package/flu.dart
new file mode 100644
index 0000000..5e33f7c
--- /dev/null
+++ b/tests/isolate/scenarios/short_package/flu_package/flu.dart
@@ -0,0 +1,3 @@
+class Flu {
+  static var value = "Flu";
+}
diff --git a/tests/isolate/scenarios/short_package/flu_package/flu.text b/tests/isolate/scenarios/short_package/flu_package/flu.text
new file mode 100644
index 0000000..d9d3a9a
--- /dev/null
+++ b/tests/isolate/scenarios/short_package/flu_package/flu.text
@@ -0,0 +1 @@
+Bar
\ No newline at end of file
diff --git a/tests/isolate/scenarios/short_package/short_package_test.dart b/tests/isolate/scenarios/short_package/short_package_test.dart
new file mode 100644
index 0000000..bfbe61c
--- /dev/null
+++ b/tests/isolate/scenarios/short_package/short_package_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// PackageRoot=none
+
+import 'dart:io';
+import 'dart:isolate';
+
+import "package:flu";
+
+var PACKAGE_FLU = "package:flu";
+var FLU_TEXT = "flu.text";
+
+testShortResolution(package_uri) async {
+  var fluPackage = await Isolate.resolvePackageUri(Uri.parse(package_uri));
+  print("Resolved $package_uri to $fluPackage");
+  var fluText = fluPackage.resolve(FLU_TEXT);
+  print("Resolved $FLU_TEXT from $package_uri to $fluText");
+  var fluFile = new File.fromUri(fluText);
+  var fluString = await fluFile.readAsString();
+  if (fluString != "Bar") {
+    throw "Contents of $FLU_TEXT not matching.\n"
+          "Got: $fluString\n"
+          "Expected: Bar";
+  }
+}
+
+main([args, port]) async {
+  if (Flu.value != "Flu") {
+    throw "Import of wrong Flu package.";
+  }
+  await testShortResolution(PACKAGE_FLU);
+  await testShortResolution(PACKAGE_FLU + "/");
+  await testShortResolution(PACKAGE_FLU + "/abc.def");
+  print("SUCCESS");
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index ff38b09..261ea59 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -157,11 +157,23 @@
 deferred_inheritance_constraints_test: Skip
 deferred_load_constants_test: Skip # multitest gets confused
 tearoff_basic_test: RuntimeError, Crash # Conflicting flag.
-deferred_global_test: RuntimeError # Issue 25845
 
 vm/type_vm_test: RuntimeError # Expects line and column numbers
 vm/type_cast_vm_test: RuntimeError # Line number mismatch.
 
+issue13474_test: SkipByDesign # Requires checked mode.
+assertion_test: SkipByDesign # Requires checked mode.
+named_parameters_type_test/01: SkipByDesign # Requires checked mode.
+named_parameters_type_test/02: SkipByDesign # Requires checked mode.
+named_parameters_type_test/03: SkipByDesign # Requires checked mode.
+type_checks_in_factory_method_test: SkipByDesign # Requires checked mode.
+positional_parameters_type_test/01: SkipByDesign # Requires checked mode.
+positional_parameters_type_test/02: SkipByDesign # Requires checked mode.
+list_literal4_test: SkipByDesign # Requires checked mode.
+generic_test: SkipByDesign # Requires checked mode.
+map_literal4_test: SkipByDesign # Requires checked mode.
+
+
 [ $runtime == dart_precompiled ]
 deferred_global_test: RuntimeError # Tries to produce a stack trace.
 ct_const2_test: Pass, Crash # Incompatible flag --compile_all
diff --git a/tests/lib/convert/json_test.dart b/tests/lib/convert/json_test.dart
index cfed8d9..ef7b077 100644
--- a/tests/lib/convert/json_test.dart
+++ b/tests/lib/convert/json_test.dart
@@ -1,6 +1,8 @@
 // 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.
+// Disable background compilation so that the Issue 24908 can be reproduced.
+// VMOptions=--no-background-compilation
 
 library json_test;
 
diff --git a/tests/standalone/io/certificates/client1_key.p12 b/tests/standalone/io/certificates/client1_key.p12
index d9cf05b..5d11e73 100644
--- a/tests/standalone/io/certificates/client1_key.p12
+++ b/tests/standalone/io/certificates/client1_key.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/client1_key_malformed.pem b/tests/standalone/io/certificates/client1_key_malformed.pem
index 33a79bf..8c1f7d8 100644
--- a/tests/standalone/io/certificates/client1_key_malformed.pem
+++ b/tests/standalone/io/certificates/client1_key_malformed.pem
@@ -1,4 +1,3 @@
------BEGIN ENCRYPTED PRIVATE KEY-----
 MIIE4jAcBgoqhkiG9w0BDAEBMA4ECF4ZB27y60SWAgIIAASCBMCEL3ZCzfC0q+m+
 B8gM9jQe1JFRD5reAuwK6+3speBS4KE+wjbcyQq09/5UoQu3Dci1WG1nKLB1u0Bk
 w9NuRahWCpvVLzz/GQ6Psesixq3V69zD3N6iMl/XQKymQBwGK51xIkeJO+6Skh2d
diff --git a/tests/standalone/io/certificates/client_authority_malformed.pem b/tests/standalone/io/certificates/client_authority_malformed.pem
index d206dce3..d0aeff4 100644
--- a/tests/standalone/io/certificates/client_authority_malformed.pem
+++ b/tests/standalone/io/certificates/client_authority_malformed.pem
@@ -1,4 +1,3 @@
------BEGIN CERTIFICATE-----
 MIIDKjCCAhKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9jbGll
 bnRhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1WjAaMRgw
 FgYDVQQDEw9jbGllbnRhdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
diff --git a/tests/standalone/io/certificates/server_chain.p12 b/tests/standalone/io/certificates/server_chain.p12
index 1e8c66d..79e412d 100644
--- a/tests/standalone/io/certificates/server_chain.p12
+++ b/tests/standalone/io/certificates/server_chain.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/server_chain_malformed1.pem b/tests/standalone/io/certificates/server_chain_malformed1.pem
index cbbeb55..cb623fd 100644
--- a/tests/standalone/io/certificates/server_chain_malformed1.pem
+++ b/tests/standalone/io/certificates/server_chain_malformed1.pem
@@ -1,4 +1,3 @@
------BEGIN CERTIFICATE-----
 MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
 cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1
 WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
diff --git a/tests/standalone/io/certificates/server_chain_malformed2.pem b/tests/standalone/io/certificates/server_chain_malformed2.pem
index 2c99e78..978c523 100644
--- a/tests/standalone/io/certificates/server_chain_malformed2.pem
+++ b/tests/standalone/io/certificates/server_chain_malformed2.pem
@@ -1,4 +1,3 @@
------BEGIN CERTIFICATE-----
 MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
 cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1
 WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
diff --git a/tests/standalone/io/certificates/server_key.p12 b/tests/standalone/io/certificates/server_key.p12
index 2434fb7..204d42d 100644
--- a/tests/standalone/io/certificates/server_key.p12
+++ b/tests/standalone/io/certificates/server_key.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/trusted_certs.p12 b/tests/standalone/io/certificates/trusted_certs.p12
index 167f2e8..76c76ec 100644
--- a/tests/standalone/io/certificates/trusted_certs.p12
+++ b/tests/standalone/io/certificates/trusted_certs.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/trusted_certs_malformed.pem b/tests/standalone/io/certificates/trusted_certs_malformed.pem
index ea26cc7..f96698e 100644
--- a/tests/standalone/io/certificates/trusted_certs_malformed.pem
+++ b/tests/standalone/io/certificates/trusted_certs_malformed.pem
@@ -1,4 +1,3 @@
------BEGIN CERTIFICATE-----
 MIIC+zCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
 YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNFoXDTI1MTAyNDEwMjYzNFowGDEWMBQG
 A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
@@ -6,3 +5,4 @@
 FfaHczXQTwnTCaYA4u4uSDvSOsFFEfxEwYORsdKmQEM8nGpVX2NVvKsMcGIhh8kh
 ZwJfkMIOcAxmGIHGdMhF8VghonJ8uGiuqktxdfpARq0g3fqIjDHsF9/LpfshUfk9
 wsRyTF0yr90U/dsfnE+u8l7GvVl8j2Zegp0sagAGtLaNv7tP17AibqEGg2yDBrBN
+a
diff --git a/tests/standalone/io/https_bad_certificate_test.dart b/tests/standalone/io/https_bad_certificate_test.dart
index 90c630f..7dc5aa2 100644
--- a/tests/standalone/io/https_bad_certificate_test.dart
+++ b/tests/standalone/io/https_bad_certificate_test.dart
@@ -57,8 +57,8 @@
                  result) async {
   HttpClient client = new HttpClient(context: context);
   client.badCertificateCallback = (X509Certificate certificate, host, port) {
-    Expect.equals('/CN=rootauthority', certificate.subject);
-    Expect.equals('/CN=rootauthority', certificate.issuer);
+    Expect.isTrue(certificate.subject.contains('rootauthority'));
+    Expect.isTrue(certificate.issuer.contains('rootauthority'));
     // Throw exception if one is requested.
     if (callbackReturns == 'exception') throw new CustomException();
     return callbackReturns;
diff --git a/tests/standalone/io/secure_bad_certificate_test.dart b/tests/standalone/io/secure_bad_certificate_test.dart
index 610bcdb..7b28284 100644
--- a/tests/standalone/io/secure_bad_certificate_test.dart
+++ b/tests/standalone/io/secure_bad_certificate_test.dart
@@ -55,8 +55,8 @@
                  callbackReturns,
                  result) async {
   badCertificateCallback(X509Certificate certificate) {
-    Expect.equals('/CN=rootauthority', certificate.subject);
-    Expect.equals('/CN=rootauthority', certificate.issuer);
+    Expect.isTrue(certificate.subject.contains('rootauthority'));
+    Expect.isTrue(certificate.issuer.contains('rootauthority'));
     // Throw exception if one is requested.
     if (callbackReturns == 'exception') throw new CustomException();
     return callbackReturns;
diff --git a/tests/standalone/io/secure_builtin_roots_test.dart b/tests/standalone/io/secure_builtin_roots_test.dart
index 6cb85d6..ce89d11 100644
--- a/tests/standalone/io/secure_builtin_roots_test.dart
+++ b/tests/standalone/io/secure_builtin_roots_test.dart
@@ -13,7 +13,7 @@
   // We need to use an external server that is backed by a
   // built-in root certificate authority.
   try {
-  // First, check if the lookup works.
+    // First, check if the lookup works.
     await InternetAddress.lookup('www.google.com');
     var request = await client.getUrl(Uri.parse('https://www.google.com'));
     request.followRedirects = false;
diff --git a/tests/standalone/io/secure_server_client_certificate_test.dart b/tests/standalone/io/secure_server_client_certificate_test.dart
index 6891037..4c16ab0 100644
--- a/tests/standalone/io/secure_server_client_certificate_test.dart
+++ b/tests/standalone/io/secure_server_client_certificate_test.dart
@@ -66,15 +66,15 @@
   X509Certificate clientCertificate = serverEnd.peerCertificate;
   if (sendCert) {
     Expect.isNotNull(clientCertificate);
-    Expect.equals("/CN=user1", clientCertificate.subject);
-    Expect.equals("/CN=clientauthority", clientCertificate.issuer);
+    Expect.isTrue(clientCertificate.subject.contains("user1"));
+    Expect.isTrue(clientCertificate.issuer.contains("clientauthority"));
   } else {
     Expect.isNull(clientCertificate);
   }
   X509Certificate serverCertificate = clientEnd.peerCertificate;
   Expect.isNotNull(serverCertificate);
-  Expect.equals("/CN=localhost", serverCertificate.subject);
-  Expect.equals("/CN=intermediateauthority", serverCertificate.issuer);
+  Expect.isTrue(serverCertificate.subject.contains("localhost"));
+  Expect.isTrue(serverCertificate.issuer.contains("intermediateauthority"));
   clientEnd.close();
   serverEnd.close();
 }
diff --git a/tests/standalone/io/secure_socket_alpn_test.dart b/tests/standalone/io/secure_socket_alpn_test.dart
index 8599991..8bd4e27 100644
--- a/tests/standalone/io/secure_socket_alpn_test.dart
+++ b/tests/standalone/io/secure_socket_alpn_test.dart
@@ -113,6 +113,9 @@
 }
 
 main() {
+  if (!SecurityContext.alpnSupported) {
+    return 0;
+  }
   final longname256 = 'p' * 256;
   final String longname255 = 'p' * 255;
   final String strangelongname255 = 'ø' + 'p' * 253;
diff --git a/tests/standalone/io/secure_socket_test.dart b/tests/standalone/io/secure_socket_test.dart
index 1566b5a..bf128df 100644
--- a/tests/standalone/io/secure_socket_test.dart
+++ b/tests/standalone/io/secure_socket_test.dart
@@ -50,6 +50,7 @@
 
 Future test(String certType, String password) {
   List<int> body = <int>[];
+  Completer completer = new Completer();
   startServer(certType, password).then((server) {
     SecureSocket.connect(
         "localhost", server.port, context: clientContext(certType, password))
@@ -65,14 +66,17 @@
           Expect.equals(72, body[0]);
           Expect.equals(9, body[body.length - 1]);
           server.close();
+          completer.complete(null);
         },
         onError: (e, trace) {
           String msg = "Unexpected error $e";
           if (trace != null) msg += "\nStackTrace: $trace";
           Expect.fail(msg);
+          completer.complete(null);
         });
     });
   });
+  return completer.future;
 }
 
 main() async {
diff --git a/tests/standalone/io/security_context_argument_test.dart b/tests/standalone/io/security_context_argument_test.dart
index 6e9ddcf..fc6ff1c 100644
--- a/tests/standalone/io/security_context_argument_test.dart
+++ b/tests/standalone/io/security_context_argument_test.dart
@@ -116,9 +116,6 @@
     Expect.throws(() => c.setClientAuthorities(
         localFile('certificates/client_authority_malformed.pem')),
         tlsException);
-
-    c.usePrivateKey(
-        localFile('certificates/server_key.pem'), password: "dartdart");
 }
 
 void main() {
diff --git a/tests/standalone/regress_26031_test.dart b/tests/standalone/regress_26031_test.dart
new file mode 100644
index 0000000..44765c2b
--- /dev/null
+++ b/tests/standalone/regress_26031_test.dart
@@ -0,0 +1,20 @@
+// 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:isolate';
+
+import "package:expect/expect.dart";
+
+void checkResolvedExecutable(String re) {
+  Expect.equals(Platform.resolvedExecutable, re);
+}
+
+main() {
+  var exitPort = new ReceivePort();
+  Isolate.spawn(checkResolvedExecutable,
+                Platform.resolvedExecutable,
+                onExit: exitPort.sendPort);
+  exitPort.listen((_) => exitPort.close());
+}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index fecad33..7cd6257 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -44,6 +44,8 @@
 # This is expected as MacOS by default runs with a very low number
 # of allowed open files ('ulimit -n' says something like 256).
 io/socket_many_connections_test: Skip
+# Re-enable once the bots have been updated. Issue #26057
+io/secure_server_client_certificate_test: Skip
 
 [ $runtime == vm && $system == linux ]
 # These tests have started timing out and issue 25649 has been filed to
@@ -69,6 +71,7 @@
 verbose_gc_to_bmu_test: Skip
 precompilation_test: Skip # Standalone only test.
 precompilation_dart2js_test: Skip # Standalone only test.
+regress_26031_test: SkipByDesign # Standalone only test
 
 [ $compiler == dartanalyzer || $compiler == dart2analyzer ]
 issue14236_test: Skip # Analyzer can't handle Script snapshots.
@@ -270,6 +273,8 @@
 io/test_extension_test: Skip # Platform.executable
 io/regress_7679_test: Skip # Platform.executable
 io/process_*: Skip # Most use Platform.executable
+assert_test: SkipByDesign # Requires checked mode.
+no_assert_test: SkipByDesign # Requires checked mode.
 
 # Code coverage is not supported in product mode.
 [ $mode == product ]
diff --git a/tools/VERSION b/tools/VERSION
index 4c33897..4d89b8c 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 16
 PATCH 0
-PRERELEASE 1
+PRERELEASE 2
 PRERELEASE_PATCH 0
diff --git a/tools/create_sdk.py b/tools/create_sdk.py
index 0d72c9d..65f585e 100755
--- a/tools/create_sdk.py
+++ b/tools/create_sdk.py
@@ -19,6 +19,7 @@
 # ......dartfmt
 # ......dart2js
 # ......dartanalyzer
+# ......dartdevc
 # ......pub
 # ......snapshots/
 # ........analysis_server.dart.snapshot
@@ -26,6 +27,7 @@
 # ........dartanalyzer.dart.snapshot
 # ........dartdoc.dart.snapshot
 # ........dartfmt.dart.snapshot
+# ........dartdevc.dart.snapshot
 # ........pub.dart.snapshot
 # ........utils_wrapper.dart.snapshot
 #.........resources/
@@ -129,14 +131,14 @@
 
 def CopyDartScripts(home, sdk_root):
   for executable in ['dart2js_sdk', 'dartanalyzer_sdk', 'dartfmt_sdk',
-                     'pub_sdk', 'dartdoc']:
+                     'pub_sdk', 'dartdoc', 'dartdevc_sdk']:
     CopyShellScript(os.path.join(home, 'sdk', 'bin', executable),
                     os.path.join(sdk_root, 'bin'))
 
 
 def CopySnapshots(snapshots, sdk_root):
   for snapshot in ['analysis_server', 'dart2js', 'dartanalyzer', 'dartfmt',
-                   'utils_wrapper', 'pub', 'dartdoc']:
+                   'utils_wrapper', 'pub', 'dartdoc', 'dartdevc']:
     snapshot += '.dart.snapshot'
     copyfile(join(snapshots, snapshot),
              join(sdk_root, 'bin', 'snapshots', snapshot))
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index 0af7797..7187fd1 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -8,8 +8,8 @@
 # Now we need to override some settings and add some new ones.
 
 vars.update({
-  "dartium_chromium_commit": "18e2b11bf18e8db4dd3e0f77991a1dc6b87ce07b",
-  "dartium_webkit_commit": "28b9a6c03797eaecf6c92677cba747eb9df0787c",
+  "dartium_chromium_commit": "b16942297fc65fd478c6f46afd1c3aaecde77009",
+  "dartium_webkit_commit": "bf6d7afefd0ed68cae4a595a8fb8eea089303326",
   "chromium_base_revision": "338390",
 
   # We use mirrors of all github repos to guarantee reproducibility and
diff --git a/tools/dom/scripts/dartmetadata.py b/tools/dom/scripts/dartmetadata.py
index 9beaef9..37877f1 100644
--- a/tools/dom/scripts/dartmetadata.py
+++ b/tools/dom/scripts/dartmetadata.py
@@ -340,10 +340,12 @@
     ],
 
     'VTTCue.line': [
+       "@Creates('Null')",
        "@Returns('num|String')",
     ],
 
     'VTTCue.position': [
+       "@Creates('Null')",
        "@Returns('num|String')",
     ],
 
diff --git a/tools/gyp/xcode.gypi b/tools/gyp/xcode.gypi
index 1c0faff..1799baf 100644
--- a/tools/gyp/xcode.gypi
+++ b/tools/gyp/xcode.gypi
@@ -18,8 +18,8 @@
     # Chrome normally builds with the Mac OS X 10.5 SDK and sets the
     # deployment target to 10.5.  Other projects, such as O3D, may override
     # these defaults.
-    'mac_sdk%': '<!(python <(DEPTH)/tools/gyp/find_mac_sdk.py 10.6)',
-    'mac_deployment_target%': '10.6',
+    'mac_sdk%': '<!(python <(DEPTH)/tools/gyp/find_mac_sdk.py 10.8)',
+    'mac_deployment_target%': '10.8',
   },
   'xcode_settings': {
     # DON'T ADD ANYTHING NEW TO THIS BLOCK UNLESS YOU REALLY REALLY NEED IT!
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index ed9f2c0..5c8d41d 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -517,7 +517,7 @@
       CommandBuilder commandBuilder,
       List arguments,
       Map<String, String> environmentOverrides) {
-    var exec = "$buildDir/dart_no_snapshot";
+    var exec = "$buildDir/dart_bootstrap";
     var args = new List();
     args.add("--full-snapshot-after-run=$outputName");
     args.addAll(arguments);
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 2151a6d..a4abf47 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -793,14 +793,11 @@
   }
 
   int get timeout {
-    return configuration['timeout'] * SLOW_TIMEOUT_MULTIPLIER;
-/*
     if (expectedOutcomes.contains(Expectation.SLOW)) {
       return configuration['timeout'] * SLOW_TIMEOUT_MULTIPLIER;
     } else {
       return configuration['timeout'];
     }
-*/
   }
 
   String get configurationString {
diff --git a/utils/dartdevc/dartdevc.gyp b/utils/dartdevc/dartdevc.gyp
new file mode 100644
index 0000000..60e3f65
--- /dev/null
+++ b/utils/dartdevc/dartdevc.gyp
@@ -0,0 +1,37 @@
+# Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+{
+  'targets': [
+    {
+      'target_name': 'dartdevc',
+      'type': 'none',
+      'dependencies': [
+        '../../runtime/dart-runtime.gyp:dart',
+        '../../pkg/pkg.gyp:pkg_packages',
+      ],
+      'actions': [
+        {
+          'action_name': 'generate_dartdevc_snapshot',
+          'inputs': [
+            '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
+            '../../sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart',
+            '<!@(["python", "../../tools/list_files.py", "\\.dart$", "../../third_party/pkg/dev_compiler/bin"])',
+            '<(SHARED_INTERMEDIATE_DIR)/packages.stamp',
+            '<(SHARED_INTERMEDIATE_DIR)/pkg_files.stamp',
+          ],
+          'outputs': [
+            '<(SHARED_INTERMEDIATE_DIR)/dartdevc.dart.snapshot',
+          ],
+          'action': [
+            '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
+            '--snapshot=<(SHARED_INTERMEDIATE_DIR)/dartdevc.dart.snapshot',
+            '--package-root=<(PRODUCT_DIR)/packages/',
+            '../../third_party/pkg/dev_compiler/bin/dartdevc.dart'
+          ],
+        },
+      ],
+    },
+  ],
+}